From 2d634639a2a2f62d61fd4ae6f375b1a3f6728bd5 Mon Sep 17 00:00:00 2001 From: Drew Slobodnjak <60050885+drew08t@users.noreply.github.com> Date: Mon, 30 Jun 2025 09:06:16 -0700 Subject: [PATCH] Geomap: Render one marker at duplicate coordinates (#106962) * Geomap: Render one marker at duplicate coordinates * Take into account all dims for uniqueness * Simplify marker uniqueness key --- .../panel/geomap/layers/data/markersLayer.tsx | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx b/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx index 35c25310fb8..fff70ecda1a 100644 --- a/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx +++ b/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx @@ -22,7 +22,7 @@ import { MarkersLegend, MarkersLegendProps } from '../../components/MarkersLegen import { ObservablePropsWrapper } from '../../components/ObservablePropsWrapper'; import { StyleEditor } from '../../editor/StyleEditor'; import { getWebGLStyle, textMarker } from '../../style/markers'; -import { DEFAULT_SIZE, defaultStyleConfig, StyleConfig } from '../../style/types'; +import { DEFAULT_SIZE, defaultStyleConfig, StyleConfig, StyleConfigValues } from '../../style/types'; import { getDisplacement, getRGBValues, getStyleConfigState, styleUsesText } from '../../style/utils'; import { getStyleDimension } from '../../utils/utils'; @@ -122,12 +122,24 @@ export const markersLayer: MapLayerRegistryItem = { // Track if we find any line strings during feature processing let hasLineString = false; + // Track coordinates to avoid rendering duplicate markers at the same location + const processedMarkers = new Set(); + + // Helper function to create a robust uniqueness key + const createMarkerKey = (coordinates: number[], markerValues: StyleConfigValues): string => { + const coord = `${coordinates[0]},${coordinates[1]}`; + const { color, size, text, rotation } = markerValues; + return `markerAddressKey|${coord}|${color}|${size}|${text}|${rotation}`; + }; source.forEachFeature((feature) => { - const isLineString = feature.getGeometry()?.getType() === 'LineString'; + const geometry = feature.getGeometry(); + const isLineString = geometry?.getType() === 'LineString'; + if (isLineString) { hasLineString = true; } + const idx: number = feature.get('rowIndex'); const dims = style.dims; const values = { ...style.base }; @@ -144,6 +156,25 @@ export const markersLayer: MapLayerRegistryItem = { if (dims?.rotation) { values.rotation = dims.rotation.get(idx); } + + // For point geometries, check if we've already processed this marker + if (geometry?.getType() === 'Point') { + const coordinates = geometry.getCoordinates(); + + // Skip this feature if coordinates are invalid + if (!coordinates || coordinates.length < 2) { + return; + } + + const markerKey = createMarkerKey(coordinates, values); + + // Skip this feature if we've already processed a marker with identical properties + if (processedMarkers.has(markerKey)) { + return; + } + processedMarkers.add(markerKey); + } + if (!isLineString) { const colorString = tinycolor(theme.visualization.getColorByName(values.color)).toString(); const colorValues = getRGBValues(colorString);