Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save hhkaos/55744a9532be8db63fb8ab2acb328e54 to your computer and use it in GitHub Desktop.
Save hhkaos/55744a9532be8db63fb8ab2acb328e54 to your computer and use it in GitHub Desktop.
ArcGIS Developer Guide: Snap to roads using travel mode.
<!--
To run this demo, you need to replace 'YOUR_ACCESS_TOKEN' with an access token from ArcGIS that has the correct privileges.
To get started, sign up for a free ArcGIS Location Platform account or a free trial of ArcGIS Online and create developer credentials.
https://developers.arcgis.com/documentation/security-and-authentication/get-started/
-->
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>
ArcGIS Developer Guide: Snap to roads using a travel mode.
</title>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.32/esri/themes/light/main.css"
/>
<!-- <link rel="stylesheet" href="https://js.arcgis.com/4.32/esri/themes/light/main.css" /> -->
<script src="https://js.arcgis.com/4.32/"></script>
<!-- <script src="https://js.arcgis.com/4.32"></script> -->
<!-- Load Calcite Components -->
<script
type="module"
src="https://js.arcgis.com/calcite-components/3.1.0/calcite.esm.js"
></script>
<style>
html,
body,
#viewDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#travelModeSelectContainer {
padding: 6px;
background-color: #ffffff;
}
</style>
<script type="module">
const [
EsriConfig,
EsriMap,
EsriMapView,
EsriDraw,
EsriGraphic,
EsriPolyline,
EsricrossesOperator,
EsriPoint,
EsriGeoprocessor,
EsriWebMercatorUtils,
EsriGraphicsLayer,
EsriFeatureLayer,
] = await $arcgis.import([
"@arcgis/core/config",
"@arcgis/core/Map",
"@arcgis/core/views/MapView",
"@arcgis/core/views/draw/Draw",
"@arcgis/core/Graphic",
"@arcgis/core/geometry/Polyline",
"@arcgis/core/geometry/operators/crossesOperator",
"@arcgis/core/geometry/Point",
"@arcgis/core/rest/geoprocessor",
"@arcgis/core/geometry/support/webMercatorUtils",
"@arcgis/core/layers/GraphicsLayer",
"@arcgis/core/layers/FeatureLayer",
])
let currentVertices, currentTravelMode
const accessToken = "YOUR_ACCESS_TOKEN"
EsriConfig.apiKey = accessToken
const serviceURL =
"https://route-api.arcgis.com/arcgis/rest/services/World/SnapToRoadsSync/GPServer/SnapToRoads"
const travelModeURL =
"https://route-api.arcgis.com/arcgis/rest/services/World/Utilities/GPServer/GetTravelModes"
const inputPointsLayer = new EsriFeatureLayer({
portalItem: { id: "75fba88319044f499271b5040467bc4f" },
})
const map = new EsriMap({
basemap: "arcgis/navigation-night",
layers: [inputPointsLayer],
})
const view = new EsriMapView({
container: "viewDiv",
map: map,
zoom: 17,
center: [-117.1557, 32.7297],
})
// add the button for the draw tool
view.ui.add("travelModeSelectContainer", "top-right")
const drawRoutes = async () => {
const btn = document.getElementById("snapPointsButton")
try {
btn.loading = true
const result = await createGraphic()
if (result[0] && result[1]) {
// /event.preventDefault()
// view.goTo(result.snappedRoutes[0].geometry.extent)
view.graphics.removeAll()
view.graphics.addMany([...result[0], ...result[1]])
}
} catch (err) {
console.log(err)
} finally {
btn.loading = false
}
}
// create a new graphic presenting the polyline that is being drawn on the view
const createGraphic = async () => {
let snappedResults = null
snappedResults = await snapToRoads()
return snappedResults
}
// get network travel modes from our portal
const getTravelModes = async modeName => {
const params = {
token: accessToken,
f: "json",
}
const response = await EsriGeoprocessor.execute(travelModeURL, params)
const tmode = response.results[0].value.features.find(f => {
return f.attributes.Name === modeName
})
return tmode.attributes.TravelMode
}
// send request to the Snap to Roads operation
const snapToRoads = async () => {
const pts = await inputPointsLayer.queryFeatures()
const inputParams = {
points: pts,
travel_mode: currentTravelMode,
return_location_fields: true,
road_properties_on_lines: ["length_miles"],
token: accessToken,
return_lines: true,
}
const results = await EsriGeoprocessor.execute(serviceURL, inputParams)
const routes = results.results[1].value.features.map(r => {
return new EsriGraphic({
geometry: r.geometry,
attributes: r.attributes,
symbol: {
type: "simple-line", // autocasts as new SimpleFillSymbol
color: [0, 150, 255, 0.5],
width: 4,
cap: "round",
join: "round",
},
popupTemplate: {
title: "Segment id: {ObjectID}",
content: [
{
type: "fields",
fieldInfos: [
{
fieldName: "line_type",
label: "Line type",
},
{
fieldName: "length_miles",
label: "Segment length (miles)",
format: { places: 2 },
},
],
},
],
},
})
})
const resultPoints = results.results[0].value.features.map(pt => {
return new EsriGraphic({
geometry: pt.geometry,
attributes: pt.attributes,
symbol: {
type: "simple-marker",
color: [0, 0, 0, 1],
size: "9px",
outline: {
color: "#ffffff",
width: 1,
},
},
popupTemplate: {
title: "Snapped point {ObjectID}",
content: [
{
type: "fields",
fieldInfos: [
{
fieldName: "confidence",
label: "Snap confidence",
format: { places: 5 },
},
{
fieldName: "line_id",
label: "Line ID",
},
],
},
],
},
})
})
return [routes, resultPoints]
}
document
.getElementById("snapPointsButton")
.addEventListener("click", drawRoutes)
document.getElementById("resetButton").addEventListener("click", () => {
view.graphics.removeAll()
})
// get the list of travel modes
currentTravelMode = await getTravelModes("Walking Distance")
</script>
</head>
<body>
<div id="viewDiv">
<div id="travelModeSelectContainer" class="esri-widget">
<calcite-button id="snapPointsButton" icon-start="pin-plus"
>Snap GPS points</calcite-button
>
<calcite-button id="resetButton" icon-start="reset"></calcite-button>
</div>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment