Azure Map Web SDK - Line Layer going from one edge to another

Anisha KC 125 Reputation points Microsoft Employee
2024-08-23T18:41:36.2966667+00:00

Hi,

We are using Azure Map React. We were wondering if there is a way to configure the line layer such that it goes from one edge to another. We want to draw lines on the global map over the Pacific Ocean not across the entire map. So if there is a line that goes from America to Asia - rather than going over the whole map, we want it to go from the left edge and show up in the right edge in Asia. Is this possible?

Thank you!

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

1 answer

Sort by: Most helpful
  1. rbrundritt 18,591 Reputation points Microsoft Employee
    2024-08-23T21:05:00.68+00:00

    The GeoJSON specification does not allow shapes to cross the antemeridian. I'm not a fan of this, luckily there are a couple of tools in Azure Maps to assist with this.

    Options 1: Use longitude values that are outside the range of -180/180, this will cause points to render on the adjacent map. The atlas.math.getPathDenormalizedAtAntimerian function in Azure Maps takes in an array of coordinates for a path, and does this for you. This keeps the geometry a LineString, but not everyone is a fan of using longitude values outside the -180/180 range, so then there is option 2.

    Option 2: Go through each line segment and split any that have a longitude difference of more than 180 degrees. This will generate a MultiLineString. The geometry type changes, but the longitude values stay within the -180/180 range. The atlas.math.getPathSplitByAntimeridian function in Azure Maps takes in an array of coordinates for a path, and does this for you. This is a much more complex calculation than option 1, but unless you are doing this with a ton of lines, this option should work fine. If you do have a ton of lines, you may also want to consider splitting them in your source data ahead of time.

    If you plan on exporting the data that's in the map, you will likely find option 2 better as the output would be valid GeoJSON while the output from option 1 is invalid.

    Here is a code sample showing all two options:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<title></title>
    
    	<meta charset="utf-8" />
    	<meta http-equiv="x-ua-compatible" content="IE=Edge" />
    	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
    
    	<!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
    	<link rel="stylesheet" href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.css" type="text/css" />
    	<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.js"></script>
    
    	<script type='text/javascript'>
    		var map, datasource;
    
    		var data = {
    			"type": "Feature",
    			"properties": {},
    			"geometry": {
    				"type": "LineString",
    				"coordinates": [
    					[
    						144.9586,
    						-37.848381
    					],
    					[
    						-118.1948,
    						33.767109
    					]
    				]
    			}
    		};
    
    		function GetMap() {
    			//Initialize a map instance.
    			map = new atlas.Map('myMap', {
    				view: 'Auto',
    
    				//Add your Azure Maps subscription client ID to the map SDK. Get an Azure Maps client ID at https://azure.com/maps
    				authOptions: {
    					authType: 'subscriptionKey',
    					subscriptionKey: '<Your Azure Maps Key>'
    				}
    			});
    
    			//Wait until the map resources are ready.
    			map.events.add('ready', function () {
    				//Create a data source to add your data to.
    				datasource = new atlas.source.DataSource();
    				map.sources.add(datasource);
    
    				//Add a layer for rendering data.
    				map.layers.add(new atlas.layer.LineLayer(datasource));
    
    				map.setCamera({
    					bounds: atlas.data.BoundingBox.fromData(data)
    				});
    			});
    		}
    
    		function option1() {
    			//Denormalize the coordinates that cross the antimeridian. This will result in some longitude values being outside of the -180 to 180 range.
    			//Docs: https://video2.skills-academy.com/en-us/javascript/api/azure-maps-control/atlas.math?view=azure-maps-typescript-latest#azure-maps-control-atlas-math-getpathdenormalizedatantimerian
    			var newCoords = atlas.math.getPathDenormalizedAtAntimerian(data.geometry.coordinates);
    
    			datasource.setShapes(new atlas.data.LineString(newCoords));
    		}
    
    		function option2() {
    			//This splits the line on the antimeridian if any line segments cross it (distance between longitudes is greater than 180).
    			//Docs: https://video2.skills-academy.com/en-us/javascript/api/azure-maps-control/atlas.math?view=azure-maps-typescript-latest#azure-maps-control-atlas-math-getpathdenormalizedatantimerian
    			var newCoords = atlas.math.getPathSplitByAntimeridian(data.geometry.coordinates);
    
    			datasource.setShapes(new atlas.data.MultiLineString(newCoords));
    		}
    	</script>
    </head>
    <body onload="GetMap()">
    	<div id="myMap" style="position:relative;width:100%;height:600px;"></div>
    
    	<input type="button" onclick="option1()" value="Option 1" />
    	<input type="button" onclick="option2()" value="Option 2" />
    </body>
    </html>
    
    0 comments No comments

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.