Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
AzureMapsGovCloudCodeSamples/AzureMapsCodeSamples/REST Services/Elevation path gradient.html
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
293 lines (238 sloc)
12.9 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<title>Elevation path gradient - Azure Maps Web SDK Samples</title> | |
<meta charset="utf-8" /> | |
<link rel="shortcut icon" href="/favicon.ico" /> | |
<meta http-equiv="x-ua-compatible" content="IE=Edge" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> | |
<meta name="description" content="This sample shows how to retrieve elevation data along a path, and then render that path as a gradient based on the elevation." /> | |
<meta name="keywords" content="Microsoft maps, map, gis, API, SDK, services, module, elevation, elevations" /> | |
<meta name="author" content="Microsoft Azure Maps" /> | |
<!-- Add references to the Azure Maps Map control JavaScript and CSS files. --> | |
<link rel="stylesheet" href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css" type="text/css" /> | |
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script> | |
<!-- Add references to the Azure Maps Map Drawing Tools JavaScript and CSS files. --> | |
<link rel="stylesheet" href="https://atlas.microsoft.com/sdk/javascript/drawing/1/atlas-drawing.min.css" type="text/css" /> | |
<script src="https://atlas.microsoft.com/sdk/javascript/drawing/1/atlas-drawing.min.js"></script> | |
<script type='text/javascript'> | |
var map, datasource, layer, drawingManager; | |
var elevationLineUrl = 'https://{azMapsDomain}/elevation/line/json?api-version=1.0&lines={lines}&samples={samples}'; | |
var maxSampleSize = 100; | |
var colors = ['#1a9641', '#a6d96a', '#ffffbf', '#fdae61', '#d7191c']; | |
var elvSteps = 50; | |
function GetMap() { | |
//Point the Azure Maps domain to the US Azure Gov Cloud domain. | |
atlas.setDomain('atlas.azure.us'); | |
//Initialize a map instance. | |
map = new atlas.Map('myMap', { | |
center: [-122.335, 47.608], | |
zoom: 12, | |
view: 'Auto', | |
//Add authentication details for connecting to Azure Maps. | |
authOptions: { | |
//Use Azure Active Directory authentication. | |
authType: 'anonymous', | |
clientId: 'c9f2f391-13f1-407b-a4a5-f0a241bacfbf', //Your Azure Active Directory 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://azuremapscodesamples.azurewebsites.us/Common/TokenService.ashx'; | |
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: '<Your Azure Maps Key>' | |
} | |
}); | |
//Wait until the map resources are ready. | |
map.events.add('ready', function () { | |
//Add a style control to the map. | |
map.controls.add(new atlas.control.StyleControl({ | |
mapStyles: 'all' | |
}), { | |
position: 'top-left' | |
}); | |
//Create a data source for the route line. | |
datasource = new atlas.source.DataSource(null, { | |
lineMetrics: true //Enable line metrics on the data source. This is needed to enable support for strokeGradient. | |
}); | |
map.sources.add(datasource); | |
//Create a layer for rendering the line gradient. | |
layer = new atlas.layer.LineLayer(datasource, null, { | |
strokeWidth: 7, | |
lineJoin: 'round', | |
lineCap: 'round' | |
}); | |
map.layers.add([ | |
//Optionally. Add a second line layer behind the gradient layer. This layer will provide a board around the line so it is easier to see the details. | |
new atlas.layer.LineLayer(datasource, null, { | |
strokeWidth: 9, | |
strokeColor: 'black', | |
lineJoin: 'round', | |
lineCap: 'round' | |
}), | |
layer | |
]); | |
//Create an instance of the drawing manager and display the line drawing option of the drawing toolbar. | |
drawingManager = new atlas.drawing.DrawingManager(map, { | |
toolbar: new atlas.control.DrawingToolbar({ | |
buttons: ['draw-line'], | |
position: 'top-left', | |
style: 'light' | |
}) | |
}); | |
///Clear the map and drawing canvas when the user enters into a drawing mode. | |
map.events.add('drawingmodechanged', drawingManager, drawingModeChanged); | |
//Monitor for when a line drawing has been completed. | |
map.events.add('drawingcomplete', drawingManager, getElevations); | |
}); | |
} | |
function drawingModeChanged(mode) { | |
//Clear the drawing canvas and data source. | |
if (mode.startsWith('draw')) { | |
drawingManager.getSource().clear(); | |
datasource.clear(); | |
} | |
} | |
function getElevations(line) { | |
//Exit drawing mode and clear the drawing canvas. | |
drawingManager.setOptions({ mode: 'idle' }); | |
drawingManager.getSource().clear(); | |
//Get the coordinates from the drawn line. | |
var cleanLineCoords = []; | |
var lastCoord; | |
var lineCoords = line.getCoordinates(); | |
//Round coordinates to 6 decimal places (~10cm accuracy) to reduce the length of URLs. | |
lineCoords.forEach(c => { | |
c[0] = Math.round(c[0] * 1000000) / 1000000; | |
c[1] = Math.round(c[1] * 1000000) / 1000000; | |
//The elevation service does not allow repeat coordinates in the path. | |
if (!lastCoord || !atlas.data.Position.areEqual(lastCoord, c)) { | |
cleanLineCoords.push(c); | |
} | |
lastCoord = c; | |
}); | |
if (cleanLineCoords.length < 2) { | |
alert('Not enough unique positions in the line.'); | |
return; | |
} | |
//Get the total length of the path. | |
var totalLength = atlas.math.getLengthOfPath(cleanLineCoords); | |
//Format line coordinates as "longitude0,latitude0|longitude1,latitude1|..." | |
var lineParam = cleanLineCoords.map(c => c.join(',')).join('|'); | |
//The elevation dataset has a 24 meter sample spacing, no need for smaller sample spacing. | |
//Elevation service requires a minimum of 2 samples. | |
var sampleSize = Math.max(2, Math.min(Math.round(totalLength / 24), maxSampleSize)); | |
var url = elevationLineUrl.replace('{lines}', lineParam).replace('{samples}', sampleSize); | |
//Show loading icon. | |
document.getElementById('loadingIcon').style.display = ''; | |
processRequest(url).then(response => { | |
if (response.error) { | |
alert(response.error.message); | |
return; | |
} | |
//Convert response into array of positions: [longitude, latitude, elevation] | |
var points = response.data.map(c => [c.coordinate.longitude, c.coordinate.latitude, c.elevationInMeter]); | |
//Generate a data driven style expression for a gradient based on the elevation. | |
var exp = calculateElevationGradientExpression(points, totalLength); | |
layer.setOptions({ strokeGradient: exp }); | |
datasource.setShapes([line]); | |
//Hide loading icon. | |
document.getElementById('loadingIcon').style.display = 'none'; | |
}); | |
} | |
function calculateElevationGradientExpression(points, totalLength) { | |
var exp = [ | |
'interpolate', //This will cause the colors from each data point to create a gradient between points. | |
['linear'], | |
['line-progress'] | |
]; | |
//The line progress will be a fraction of the total length of the path, | |
//so we can calculate the line progress value of each data point and set the color accordingly. | |
var progress = 0; | |
for (var i = 0; i < points.length; i++) { | |
var elv = points[i][2]; | |
//Elevation may not be available sometimes. Skip these values. | |
if (elv !== 'NaN') { | |
//The line progress value is a value between 0 and 1. | |
//Taking the travelled distance and dividing it by the total distance of the path, will give us the line progress value. | |
exp.push(progress / totalLength); | |
//Add our business logic on how a data point should be colored based on the elevation. | |
//Calculate the index in the color array based on the elevation step size. | |
var colorIdx = Math.max(0, Math.min(Math.round(elv / elvSteps), colors.length - 1)); | |
exp.push(colors[colorIdx]); | |
if (i < points.length - 1) { | |
progress += atlas.math.getDistanceTo(points[i], points[i + 1]); | |
} | |
} | |
} | |
return exp; | |
} | |
function processRequest(url) { | |
//This is a reusable function that sets the Azure Maps platform domain, sings the request, and makes use of any transformRequest set on the map. | |
return new Promise((resolve, reject) => { | |
//Replace the domain placeholder to ensure the same Azure Maps cloud is used throughout the app. | |
url = url.replace('{azMapsDomain}', atlas.getDomain()); | |
//Get the authentication details from the map for use in the request. | |
var requestParams = map.authentication.signRequest({ url: url }); | |
//Transform the request. | |
var transform = map.getServiceOptions().tranformRequest; | |
if (transform) { | |
requestParams = transform(url); | |
} | |
fetch(requestParams.url, { | |
method: 'GET', | |
mode: 'cors', | |
headers: new Headers(requestParams.headers) | |
}) | |
.then(r => r.json(), e => reject(e)) | |
.then(r => { | |
resolve(r); | |
}, e => reject(e)); | |
}); | |
} | |
</script> | |
<style> | |
.legend { | |
position: absolute; | |
top: 10px; | |
right: 10px; | |
background-color: white; | |
border-radius: 10px; | |
padding: 10px; | |
font-size: 11px; | |
} | |
.colorSquare { | |
width: 16px; | |
height: 16px; | |
text-align: center; | |
} | |
</style> | |
</head> | |
<body onload="GetMap()"> | |
<div id="myMap" style="position:relative;width:100%;min-width:290px;height:600px;"></div> | |
<div class="legend"> | |
<div style="font-size:14px;font-weight:bold;">Elevation</div> | |
<div style="float:left"> | |
<div class="colorSquare" style="background-color:#d7191c"></div> | |
<div class="colorSquare" style="background-color:#fdae61"></div> | |
<div class="colorSquare" style="background-color:#ffffbf"></div> | |
<div class="colorSquare" style="background-color:#a6d96a"></div> | |
<div class="colorSquare" style="background-color:#1a9641"></div> | |
</div> | |
<div style="float:left;margin:9px 5px 0 5px;"> | |
<div class="colorSquare">200m</div> | |
<div class="colorSquare">150m</div> | |
<div class="colorSquare">100m</div> | |
<div class="colorSquare">50m</div> | |
</div> | |
</div> | |
<div style="position:absolute;top:0px;left:calc(50% - 100px);background-color:white;padding:5px;">Draw rectangle on the map</div> | |
<img id="loadingIcon" src="../Common/images/loadingIcon.gif" title="Loading" style="position:absolute;left:calc(50% - 25px);top:250px;display:none;" /> | |
<fieldset style="width:calc(100% - 30px);min-width:290px;margin-top:10px;"> | |
<legend><h1 style="font-size:16px">Elevation path gradient</h1></legend> | |
This sample shows how to retrieve elevation data along a path, and then render that path as a gradient based on the elevation. | |
Elevation data from the <a href="https://docs.microsoft.com/azure/azure-maps/how-to-request-elevation-data" target="_blank">Azure Maps Elevation services</a> © DLR 2011-2014 / © Airbus 2021. | |
</fieldset> | |
</body> | |
</html> |