ThinkGeo.com    |     Documentation    |     Premium Support

Best way to show overlapping markers

We build maps of doctors, hospitals, etc.  Most of the time, there will be 5, 10, 20 doctors at the same physical location (i.e., a medical office building).  I was thinking that I could change the Marker Icon to indicate more than one person, and then the tooltip could give a list of all of the Doctors at that location.


Is there some simple code for determining that Markers overlap?  For example, some equation based on the Lat, Long of each doctor?  Thanks!!


And here's the trick, can that equation work with different zoom levels?  i.e., At one zoom level they overlap, at another they don't.


bob



 Hello Bob,


 
Thanks for your post, sorry to say, we don't have an API that can simply knows if a group markers are overlapped, you have to loop them and compare each of them using Feature.Containing or Feature.Intersection to check if any of them are overlapped.
 
But there is a trick that using Cluster, it will groups together various features into one symbol with the count of all the features being labeled, you can check details here: wiki.thinkgeo.com/wiki/Map_S...PointStyle
 
Please feel free to let us know your queries.
 
Regards,
 
Gary

I think the Feature.Containing/Intersection is the best approach for us. The question is, at various zoom levels they may/may not overlap.  Is there an example of how to determine overlap based on zoom level? 
  
 Thanks Bob

 


Hi Bob,
Regarding the question “at various zoom levels they may/may not overlap. Is there an example of how to determine overlap based on zoom level?, the answer is that we can try “refreshing” the markers using “CurrentScaleChanged” event to make sure the marker overlay which be refresh for each zoom level. 
I think Gray’s suggestion is feasible based on the attached online demo, could you have a try with the help of “CurrentScaleChange” event, and any problem please let me know.
Thanks,
Johnny

The cluster example given above does look like it may help, but it introduces concepts like MapSuiteTileMatrix which your user manual doesn’t explain very well.  Can you give me a bigger picture of what is going on in this code?   
  
 My requirements include the need to know the identity of each point that will be clustered so that when the user clicks on the clustered marker I can display a list of all Doctors whose physical location lies in the boundaries of the clustered marker? 
  
 Thanks. 
  
 bob

Tim 
  
 Thanks for your information. 
 After check our resource code, we did find this issue with your data caused by the accuracy. We have fixed it and you can get the latest version(6.0.0.289) and then have a try. 
  
 If any problems, please feel free to let us known. 
 Regards 


 Hi Bob,


 
The ClusterPointStyle have been in the Desktop edition and here are some codes which might fit your requirements.
 


int clusterCellsize = 50;
        private void Form_Load(object sender, EventArgs e)
        {
            winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
            winformsMap1.CurrentExtent = new RectangleShape(-131.22, 55.05, -54.03, 16.91);

            WorldMapKitWmsDesktopOverlay worldMapKitOverlay = new WorldMapKitWmsDesktopOverlay();
            winformsMap1.Overlays.Add(worldMapKitOverlay);


            ClusterPointStyle clusterPointStyle = new ClusterPointStyle(PointSymbolType.Triangle,
                new GeoSolidBrush(GeoColor.FromArgb(150, GeoColor.StandardColors.Orange)),
                new GeoPen(GeoColor.StandardColors.Red, 2), 27);
            clusterPointStyle.CellSize = clusterCellsize;
            clusterPointStyle.TextStyle = new TextStyle("FeatureCount", new GeoFont("Arial", 8), new GeoSolidBrush(GeoColor.StandardColors.Black));
            clusterPointStyle.TextStyle.DuplicateRule = LabelDuplicateRule.UnlimitedDuplicateLabels;
            clusterPointStyle.TextStyle.PointPlacement = PointPlacement.Center;

            ShapeFileFeatureLayer clusterMajorCitiesLayer = new ShapeFileFeatureLayer(@"..\..\SampleData\Data\MajorCities.shp", ShapeFileReadWriteMode.ReadOnly);
            clusterMajorCitiesLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Clear();
            clusterMajorCitiesLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(clusterPointStyle);
            clusterMajorCitiesLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            LayerOverlay overlay = new LayerOverlay();
            overlay.Layers.Add(clusterMajorCitiesLayer);
            winformsMap1.Overlays.Add(overlay);

            winformsMap1.Refresh();
        }

private void winformsMap1_MapClick(object sender, MapClickWinformsMapEventArgs e)
        {
            //  We get the scale to determine the grid.  This scale property should really be on the Canvas!
            double scale = ExtentHelper.GetScale(winformsMap1.CurrentExtent, winformsMap1.Width, winformsMap1.MapUnit);

            // Setup our grid for clustering the points.  This is where we specify our cell size in pixels
            MapSuiteTileMatrix mapSuiteTileMatrix = new MapSuiteTileMatrix(scale, clusterCellsize, clusterCellsize, winformsMap1.MapUnit);

            // Pass in the current extent to get our grid cells.  All points in these cells will be consolidated
            IEnumerable<TileMatrixCell> tileMatricCells = mapSuiteTileMatrix.GetContainedCells(winformsMap1.CurrentExtent);
            foreach (var cell in tileMatricCells)
            {
                if (cell.BoundingBox.Contains(e.WorldLocation))
                {
                    ShapeFileFeatureSource clusterMajorCitiesLayer = new ShapeFileFeatureSource(@"..\..\SampleData\Data\MajorCities.shp", ShapeFileReadWriteMode.ReadOnly);
                    clusterMajorCitiesLayer.Open();
                    Collection<Feature> clusterCells = clusterMajorCitiesLayer.GetFeaturesInsideBoundingBox(cell.BoundingBox, ReturningColumnsType.AllColumns);
                    // you can show those features information according to your need.
                    MessageBox.Show(clusterCells.Count + "");
                }
            }

        }


 
 
In the code above, the tileMatricCells means the current map had been splited into many cells and one cluster marker represents one cell. In this way, we can use “cell.BoundingBox.Contains(e.WorldLocation)” to get the current cluster marker’s features.
 
Besides, you may need to do more work to filter the places where the user clicked on the map.
 
Hope those codes would help for you.
 
Regards,
 
Johnny