Makers Get Visible on Certain Zoom And Disappear on ZoomOut

Nilesh Khonde 60 Reputation points
2024-05-13T06:59:26.95+00:00

Hi, I am developing an application using Azure Maps. I'm having trouble understanding why it's working this way.

1.If I want to plot only markers on the map using the symbol layer, I encounter a problem: when I zoom out, the markers get hidden, but when I zoom in, the markers become visible again. Is this intended functionality, or am I missing something?

Here's the sample code for your reference:

//Here is My Code
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Data-driven symbol icons - Azure Maps Web SDK Samples</title>
    <meta charset="utf-8" />
	<link rel="shortcut icon" href="/favicon.ico"/>
    
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
    <meta name="description" content="This sample shows how to use multiple custom icons in a single symbol layer by using data-driven styling with an expression." />
    <meta name="keywords" content="Microsoft maps, map, gis, API, SDK, markers, pins, pushpins, symbols, layer, icon, image, expression" />
    <meta name="author" content="Microsoft Azure Maps" /><meta name="version" content="1.0" />
    <meta name="screenshot" content="screenshot.jpg" />
    <!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
    <link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.css" rel="stylesheet" />
    <script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.js"></script>
    <script>
        var map, popups = [], datasource, shapeLayer, markerColl = [];
        function getMap() {
            //Initialize a map instance.
            map = new atlas.Map('myMap', {
                center: [-73.985708, 40.75773],
                zoom: 9,
                view: 'Auto',
                //Add authentication details for connecting to Azure Maps.
                authOptions: {
                    //Use Azure Active Directory authentication.
                    // authType: 'anonymous',
                    // clientId: 'e6b6ab59-eb5d-4d25-aa57-581135b927f0', //Your Azure Maps client id for accessing your Azure Maps account.
                    // getToken: function (resolve, reject, map) {
                    //     //URL to your authentication service that retrieves an Azure Active Directory Token.
                    //     var tokenServiceUrl = 'https://samples.azuremaps.com/api/GetAzureMapsToken';
                    //     fetch(tokenServiceUrl).then(r => r.text()).then(token => resolve(token));
                    // }
                    //Alternatively, use an Azure Maps key. Get an Azure Maps key at https://azure.com/maps. NOTE: The primary key should be used as the key.
                    authType: 'subscriptionKey',
                    subscriptionKey: ''
                }
            });
            //Wait until the map resources are ready.
            map.events.add('ready', function () {
                //Create a data source and add it to the map.
                datasource = new atlas.source.DataSource();
                map.sources.add(datasource);
                //Load some point data into the data source.
                // datasource.importDataFromUrl('/data/geojson/SamplePoiDataSet.json');
                var coordinates = [
                    [40.7128, -74.0060],
                    [34.0522, -118.2437],
                    [41.8781, -87.6298],
                    [29.7604, -95.3698],
                    [33.4484, -112.0740],
                    [39.9526, -75.1652],
                    [37.7749, -122.4194],
                    [32.7767, -96.7970],
                    [30.2672, -97.7431],
                    [35.2271, -80.8431],
                    [49.6062, -122.3321],
                    [25.7617, -80.1918],
                    [42.3601, -71.0589],
                    [38.9072, -77.0369],
                    [36.7783, -119.4179],
                    [33.7490, -84.3880],
                    [34.0522, -118.2437],
                    [40.7128, -74.0060],
                    [37.7749, -122.4194],
                    [41.8781, -87.6298],
                    [32.7157, -117.1611],
                    [39.2904, -76.6122],
                    [29.7604, -95.3698],
                    [33.4484, -112.0740],
                    [35.2271, -80.8431],
                    [30.2672, -97.7431],
                    [34.0522, -118.2437],
                    [42.3601, -71.0589],
                    [38.9072, -77.0369],
                    [36.7783, -119.4179],
                    [33.7490, -84.3880],
                    [40.7128, -74.0060],
                    [37.7749, -122.4194],
                    [41.8781, -87.6298],
                    [32.7157, -117.1611],
                    [39.2904, -76.6122],
                    [29.7604, -95.3698],
                    [33.4484, -112.0740],
                    [35.2271, -80.8431],
                    [30.2672, -97.7431],
                    [34.0522, -118.2437],
                    [42.3601, -71.0589],
                    [38.9072, -77.0369],
                    [36.7783, -119.4179],
                    [33.7490, -84.3880],
                    [40.7128, -74.0060],
                    [37.7749, -122.4194],
                    [41.8781, -87.6298],
                    [32.7157, -117.1611],
                    [39.2904, -76.6122],
                    [29.7604, -95.3698],
                    [33.4484, -112.0740],
                    [35.2271, -80.8431],
                    [30.2672, -97.7431],
                    [34.0522, -118.2437],
                    [42.3601, -71.0589],
                    [38.9072, -77.0369],
                    [36.7783, -119.4179],
                    [33.7490, -84.3880],
                    [40.7128, -74.0060],
                ]
                coordinates.forEach(function (marker) {
                    var point = new atlas.Shape(new atlas.data.Point([marker[1], marker[0]]), null, {
                        color: 'DodgerBlue',
                        title: "test",
                    });
                    markerColl.push(point);
                });
                datasource.add(markerColl);
                    //Add a layer for rendering point data as symbols.
                    map.layers.add(new atlas.layer.SymbolLayer(datasource, null, {
                            iconOptions: {
                            // image: 'none',
                            ignorePlacement: true,
                            allowOverlap: true
                        },
                        textOptions: {
                            textField: ['get', 'title'], //Alternatively replace with 'label' property name.
                            anchor: "top", //Show the label below the pin.
                            offset: [0, 1.2],
                            color: ['get', 'pink'], //Set the color of the text. Alternatively pass in a color value here if the color will always be one color.
                        },
                    }));
                });
            // });
        }
    </script>
</head>
<body onload="getMap()">
    <div id="myMap" style="position:relative;width:100%;min-width:290px;height:600px;"></div>
    <fieldset style="width:calc(100% - 30px);min-width:290px;margin-top:10px;">
        <legend>Data-driven symbol icons</legend>
        This sample shows how to use multiple custom icons in a single symbol layer by using data-driven styling with an expression. 
        This sample uses a GeoJSON file that contains points of interest as a data source. 
        Each record in this data set has an EntityType property which is one of the following properties: 
        'Gas Station', 'Grocery Store', 'Restaurant', 'School'. 
        This sample uses the EntityType property to select the icon to display on the map.
    </fieldset>
</body>
</html>

2I was searching for functionality to filter the data plotted inside a polygon and came across demo code for that at https://github.com/Azure-Samples/AzureMapsCodeSamples/blob/main/Samples/Drawing%20Tools%20Module/Select%20data%20in%20drawn%20polygon%20area/Select%20data%20in%20drawn%20polygon%20area.html.

However, I was somewhat surprised because in the source code, they are using turf.js, an external library. Does Azure Maps have its own API or code to perform this functionality? We prefer not to depend on an external library for our app's functionality.

Azure Maps
Azure Maps
An Azure service that provides geospatial APIs to add maps, spatial analytics, and mobility solutions to apps.
736 questions
0 comments No comments
{count} votes

Accepted answer
  1. rbrundritt 18,686 Reputation points Microsoft Employee
    2024-05-13T16:31:17.05+00:00

    For #1, add the ignore placement and allow overlap options to the text options as well. It appears that if there is an image for a symbol, it won't display unless the text is displayed as well.

    For #2, if you want to filter points within a polygon on the map, there are two approaches. The first is to filter the points ahead of time via code and only include the filtered data inside the data source. This is good if you need to both filter the points on the map and need to know what is shown to do something outside of the map. The other is to use the within data driven expression which allows you pass in a polygon into the filter of a layer and it will automatically limit which points are displayed. This does the visual filter but doesn't tell you which points are displayed. Here is an example data driven expression:

    ['within', {"type": "Polygon""coordinates": [[[-114.33170,45.54248],[-118.17243,38.71702],[-102.38278,39.84012],[-114.33170,45.54248]]]} ]
    

    If you want to create a user experience where the user draws areas on the map and filters the points, the Azure Maps Selection Control module provides this capability, and also exposes a reusable function for doing point in polygon calculations.

    Azure Maps includes a set of standard geospatial math functions but doesn't dive too deep into "boolean operations" as the code for those can grow very quickly, and there are different methods that can produce different results depending on if the user wants geospatial or pixel accuracy. Turf.js is a well-established geospatial math library that's been around for years and is used by thousands of big companies. It's worth noting a large percentage of geospatial math capabilities in most geospatial platforms come from open-source libraries such as Java Topology Suite which has been around for well over 20 years and has a .NET version NetTopoloygySuite. All that said, if you simply want point in polygon and nothing more complex than that, there is a fair easy way to do this with decent performance (higher performance can be achieved using graphs, but then the code gets a lot bigger, and that's what these libraries take care of). Here is a simple point in polygon function for GeoJSON data:

    function pointInRing(point, ring) {
        var x = point.coordinates[0], y = point.coordinates[1];
        var inside = false;
        for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {
            var xi = ring[i][0], yi = ring[i][1];
            var xj = ring[j][0], yj = ring[j][1];
            
            var intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
            if (intersect) inside = !inside;
        }
        return inside;
    }
    
    function filterPointsWithinPolygon(points, polygon) {
    	//A polygon can have one or more rings. The first ring is the external outline, while additional rings are holes in the polygon.
        return points.filter(function(point) {
    		//Make sure the point is within the external ring.
            if(pointInRing(point, polygon.coordinates[0])){
    			//Make sure the point is not inside any of the holes.
    			for(var i=1;i<polygon.coordinates.length;i++){
    				//If the point is in any hole, fail.
    				if(pointInRing(point, polygon.coordinates[0])) {
    					return false;
    				}
    			}
    		}
    		
    		return true;
        });
    }
    
    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.