Learn how to find a route and directions with the route service.
Routing is the process of finding the path from an origin to a destination in a street network. You can use the route service to find routes, get driving directions, calculate drive times, and solve complicated, multiple vehicle routing problems. To create a route, you typically define a set of stops (origin and one or more destinations) and use the service to find a route with directions. You can also use a number of additional parameters such as barriers and mode of travel to refine the results.
In this tutorial, you define an origin and destination by clicking on the map. These values are used to get a route and directions from the route service. The directions are also displayed on the map.
Prerequisites
An ArcGIS Location Platform or ArcGIS Online account.
Steps
Get the starter app
Select a type of authentication below and follow the steps to create a new application.
Set up authentication
Create developer credentials in your portal for the type of authentication you selected.
Set developer credentials
Use the API key or OAuth developer credentials created in the previous step in your application.
Get a Cesium ion access token
All Cesium applications must use an access token provided through Cesium ion. This token allows you to access assets such as Cesium World Terrain in your application.
-
Go to your Cesium ion dashboard to generate an access token. Copy the key to your clipboard.
-
Create a
cesium
variable and replaceAccess Token YOUR
with the access token you copied from the Cesium ion dashboard._CESIUM _ACCESS _TOKEN Use dark colors for code blocks <script> /* Use for API key authentication */ const accessToken = "YOUR_ACCESS_TOKEN"; // or /* Use for user authentication */ // const session = await arcgisRest.ArcGISIdentityManager.beginOAuth2({ // clientId: "YOUR_CLIENT_ID", // Your client ID from OAuth credentials // redirectUri: "YOUR_REDIRECT_URL", // The redirect URL registered in your OAuth credentials // portal: "YOUR_PORTAL_URL" // Your portal URL // }) // const accessToken = session.token; Cesium.ArcGisMapService.defaultAccessToken = accessToken; const cesiumAccessToken = "YOUR_CESIUM_ACCESS_TOKEN"; </script>
-
Configure
Cesium.
with the Cesium access token to validate the application.Ion.default Access Token Use dark colors for code blocks <script> /* Use for API key authentication */ const accessToken = "YOUR_ACCESS_TOKEN"; // or /* Use for user authentication */ // const session = await arcgisRest.ArcGISIdentityManager.beginOAuth2({ // clientId: "YOUR_CLIENT_ID", // Your client ID from OAuth credentials // redirectUri: "YOUR_REDIRECT_URL", // The redirect URL registered in your OAuth credentials // portal: "YOUR_PORTAL_URL" // Your portal URL // }) // const accessToken = session.token; Cesium.ArcGisMapService.defaultAccessToken = accessToken; const cesiumAccessToken = "YOUR_CESIUM_ACCESS_TOKEN"; Cesium.Ion.defaultAccessToken = cesiumAccessToken; </script>
Add references to ArcGIS REST JS
-
In the
<head
element, reference the> routing
andrequest
packages from ArcGIS REST JS.Use dark colors for code blocks <script src="https://cesium.com/downloads/cesiumjs/releases/1.121/Build/Cesium/Cesium.js"></script> <link href="https://cesium.com/downloads/cesiumjs/releases/1.121/Build/Cesium/Widgets/widgets.css" rel="stylesheet"> <script src="https://unpkg.com/@esri/arcgis-rest-request@4/dist/bundled/request.umd.js"></script> <script src="https://unpkg.com/@esri/arcgis-rest-routing@4/dist/bundled/routing.umd.js"></script>
Update the scene
This routing application uses an integrated mesh layer of Frankfurt, Germany. Update the scene extent to focus on Frankfurt.
-
Update the
set
command to center on locationView [8.68019, 50.1147]
, Frankfurt.Use dark colors for code blocks viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(8.68019, 50.1147, 500), orientation: { heading: Cesium.Math.toRadians(-120), pitch: Cesium.Math.toRadians(-28.0), } });
-
Initialize a terrain provider called
geoid
that references the Earth Gravitational Model EGM2008. This provider will allow for geoid conversion between the gravity-based 3D object layer and the ellipsoidal-based Cesium World Terrain.Service Use dark colors for code blocks const geoidService = await Cesium.ArcGISTiledElevationTerrainProvider.fromUrl("https://tiles.arcgis.com/tiles/GVgbJbqm8hXASVYi/arcgis/rest/services/EGM2008/ImageServer");
-
Add the data attribution for the elevation layer source.
- Go to the EGM2008 item.
- Scroll down to the Credits (Attribution) section and copy its value.
- Create an
attribution
property and paste the attribution value from the item.Use dark colors for code blocks const geoidService = await Cesium.ArcGISTiledElevationTerrainProvider.fromUrl("https://tiles.arcgis.com/tiles/GVgbJbqm8hXASVYi/arcgis/rest/services/EGM2008/ImageServer"); // Attribution text retrieved from https://arcgis.com/home/item.html?id=d798c71512404bbb9c1551b827bf5467 viewer.creditDisplay.addStaticCredit(new Cesium.Credit("National Geospatial-Intelligence Agency (NGA)", false));
-
Add the Frankfurt integrated mesh layer to the scene as an
I3
.S Data Provider Use dark colors for code blocks const i3sProvider = await Cesium.I3SDataProvider.fromUrl("https://tiles.arcgis.com/tiles/cFEFS0EWrhfDeVw9/arcgis/rest/services/Buildings_Frankfurt_2021/SceneServer", { geoidTiledTerrainProvider: geoidService, token: accessToken }) viewer.scene.primitives.add(i3sProvider);
-
Add the data attribution for the scene layer source.
- Go to the Buildings Frankfurt 2021 item.
- Scroll down to the Credits (Attribution) section and copy its value.
- Create an
attribution
property and paste the attribution value from the item.Use dark colors for code blocks const i3sProvider = await Cesium.I3SDataProvider.fromUrl("https://tiles.arcgis.com/tiles/cFEFS0EWrhfDeVw9/arcgis/rest/services/Buildings_Frankfurt_2021/SceneServer", { geoidTiledTerrainProvider: geoidService, token: accessToken }) // Attribution text retrieved from https://www.arcgis.com/home/item.html?id=79c3563e42ee40ddb1b8c688eaf0dd2a viewer.creditDisplay.addStaticCredit(new Cesium.Credit("Aerowest GmbH / Esri", false)); viewer.scene.primitives.add(i3sProvider);
Create start and end point graphics
Billboard
entities are used to represent the start and end points of the route. You can customize Billboard
entities to display custom pins and images.
-
Add two new
Billboard
entities to the viewer to represent start and end points. Set theposition
of both entities tonull
.Use dark colors for code blocks const geoidService = await Cesium.ArcGISTiledElevationTerrainProvider.fromUrl("https://tiles.arcgis.com/tiles/GVgbJbqm8hXASVYi/arcgis/rest/services/EGM2008/ImageServer"); // Attribution text retrieved from https://arcgis.com/home/item.html?id=d798c71512404bbb9c1551b827bf5467 viewer.creditDisplay.addStaticCredit(new Cesium.Credit("National Geospatial-Intelligence Agency (NGA)", false)); const i3sProvider = await Cesium.I3SDataProvider.fromUrl("https://tiles.arcgis.com/tiles/cFEFS0EWrhfDeVw9/arcgis/rest/services/Buildings_Frankfurt_2021/SceneServer", { geoidTiledTerrainProvider: geoidService, token: accessToken }) // Attribution text retrieved from https://www.arcgis.com/home/item.html?id=79c3563e42ee40ddb1b8c688eaf0dd2a viewer.creditDisplay.addStaticCredit(new Cesium.Credit("Aerowest GmbH / Esri", false)); viewer.scene.primitives.add(i3sProvider); const startPoint = viewer.entities.add({ name: 'start', position: null, billboard: { verticalOrigin: Cesium.VerticalOrigin.BOTTOM, heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, } }) const endPoint = viewer.entities.add({ name: 'end', position: null, billboard: { verticalOrigin: Cesium.VerticalOrigin.BOTTOM, heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, } })
-
Create a
Pin
and use it to set theBuilder image
property of the billboards.Use dark colors for code blocks const pinBuilder = new Cesium.PinBuilder(); const startPoint = viewer.entities.add({ name: 'start', position: null, billboard: { verticalOrigin: Cesium.VerticalOrigin.BOTTOM, heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, image: pinBuilder.fromText("1", Cesium.Color.fromCssColorString('#348bdb'), 48).toDataURL(), } }) const endPoint = viewer.entities.add({ name: 'end', position: null, billboard: { verticalOrigin: Cesium.VerticalOrigin.BOTTOM, heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, image: pinBuilder.fromText("2", Cesium.Color.fromCssColorString('#348bdb'), 48).toDataURL(), } })
Add a click handler
Use an event handler to set the start (origin) and end (destination) points for the route. The first click will set the start
for the route and the second click will set the end
. Subsequent clicks will start a new route.
-
Create a
current
variable initialized toStep 'start'
. Declarestart
andCoords end
variables that will be used within the click handler.Coords Use dark colors for code blocks const geoidService = await Cesium.ArcGISTiledElevationTerrainProvider.fromUrl("https://tiles.arcgis.com/tiles/GVgbJbqm8hXASVYi/arcgis/rest/services/EGM2008/ImageServer"); // Attribution text retrieved from https://arcgis.com/home/item.html?id=d798c71512404bbb9c1551b827bf5467 viewer.creditDisplay.addStaticCredit(new Cesium.Credit("National Geospatial-Intelligence Agency (NGA)", false)); const i3sProvider = await Cesium.I3SDataProvider.fromUrl("https://tiles.arcgis.com/tiles/cFEFS0EWrhfDeVw9/arcgis/rest/services/Buildings_Frankfurt_2021/SceneServer", { geoidTiledTerrainProvider: geoidService, token: accessToken }) // Attribution text retrieved from https://www.arcgis.com/home/item.html?id=79c3563e42ee40ddb1b8c688eaf0dd2a viewer.creditDisplay.addStaticCredit(new Cesium.Credit("Aerowest GmbH / Esri", false)); viewer.scene.primitives.add(i3sProvider); let currentStep = 'start'; let startCoords, endCoords; const pinBuilder = new Cesium.PinBuilder();
-
Create a
Screen
for theSpace Event Handler Viewer
that listens for left clicks. Create anon
function that runs when a click is detected.Left Click Use dark colors for code blocks const endPoint = viewer.entities.add({ name: 'end', position: null, billboard: { verticalOrigin: Cesium.VerticalOrigin.BOTTOM, heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, image: pinBuilder.fromText("2", Cesium.Color.fromCssColorString('#348bdb'), 48).toDataURL(), } }) function onLeftClick(movement) { } viewer.screenSpaceEventHandler.setInputAction(onLeftClick, Cesium.ScreenSpaceEventType.LEFT_CLICK);
-
Get the coordinates of the clicked location and use transform them from
Cartesian
coordinates to longitude and latitude degrees to use with the routing service.Use dark colors for code blocks function onLeftClick(movement) { const pickedPosition = viewer.scene.pickPosition(movement.position); const cartographic = Cesium.Cartographic.fromCartesian(pickedPosition); const point = [Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)] } viewer.screenSpaceEventHandler.setInputAction(onLeftClick, Cesium.ScreenSpaceEventType.LEFT_CLICK);
-
Set the locations of the
start
andPoint end
billboards using a conditional statement. When a new starting position is set, remove all previous billboards and routes.Point Use dark colors for code blocks function onLeftClick(movement) { const pickedPosition = viewer.scene.pickPosition(movement.position); const cartographic = Cesium.Cartographic.fromCartesian(pickedPosition); const point = [Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)] if (currentStep === 'start') { startCoords = point; startPoint.position = pickedPosition; viewer.dataSources.removeAll(); endPoint.position = null; endCoords = null; currentStep = 'end'; } else { endCoords = point; endPoint.position = pickedPosition; currentStep = 'start'; } } viewer.screenSpaceEventHandler.setInputAction(onLeftClick, Cesium.ScreenSpaceEventType.LEFT_CLICK);
-
Run the app. You should be able to click on the map to create two billboards that display the numbers "1" and "2". Subsequent clicks should set new positions for the billboards.
Get the route and directions
To find a route between the points as well as turn-by-turn directions, use the ArcGIS REST JS solve
function to make a request to the routing service.
-
Create a new
arcgis
and set your access token.Rest. Api Key Manager Use dark colors for code blocks /* Use for API key authentication */ const accessToken = "YOUR_ACCESS_TOKEN"; // or /* Use for user authentication */ // const session = await arcgisRest.ArcGISIdentityManager.beginOAuth2({ // clientId: "YOUR_CLIENT_ID", // Your client ID from OAuth credentials // redirectUri: "YOUR_REDIRECT_URL", // The redirect URL registered in your OAuth credentials // portal: "https://www.arcgis.com/sharing/rest" // Your portal URL // }) // const accessToken = session.token; Cesium.ArcGisMapService.defaultAccessToken = accessToken; const authentication = arcgisRest.ApiKeyManager.fromKey(accessToken);
-
Create a function called
get
that accepts two sets of coordinate pairs. Inside, callRoute arcgis
and provide the coordinates of the starting and ending points.Rest.solve Route arcgis
creates a direct request to theRest.solve Route solve
endpoint of the routing service. To learn more about thesolve
endpoint, go to Routing service in the Mapping and location services guide.Use dark colors for code blocks viewer.screenSpaceEventHandler.setInputAction(onLeftClick, Cesium.ScreenSpaceEventType.LEFT_CLICK); function getRoute(start, end) { arcgisRest .solveRoute({ stops: [start, end], authentication }) }
-
Access the service response and add the returned GeoJSON to your application as a
Geo
.Json Data Source Use dark colors for code blocks function getRoute(start, end) { arcgisRest .solveRoute({ stops: [start, end], authentication }) .then((response) => { Cesium.GeoJsonDataSource.load(response.routes.geoJson, { stroke: Cesium.Color.fromCssColorString('#76fcfc'), strokeWidth: 5, clampToGround: true }).then((data) => { viewer.dataSources.add(data); }); }) }
-
Access the
directions
returned by the service and format them as HTML. Create an invisibleEntity
and set itsdescription
to display directions on the map.Use dark colors for code blocks function getRoute(start, end) { arcgisRest .solveRoute({ stops: [start, end], authentication }) .then((response) => { Cesium.GeoJsonDataSource.load(response.routes.geoJson, { stroke: Cesium.Color.fromCssColorString('#76fcfc'), strokeWidth: 5, clampToGround: true }).then((data) => { viewer.dataSources.add(data); }); const directionsHTML = response.directions[0].features.map((f) => f.attributes.text).join("<br/>"); const directionsPopup = viewer.entities.add({ name: "Directions", description: directionsHTML, position: Cesium.Cartesian3.fromDegrees(0, 0), }); viewer.selectedEntity = directionsPopup; }) }
-
In your
on
function, callLeft Click get
when both a start point and end point have been set.Route Use dark colors for code blocks function onLeftClick(movement) { const pickedPosition = viewer.scene.pickPosition(movement.position); const cartographic = Cesium.Cartographic.fromCartesian(pickedPosition); const point = [Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)] if (currentStep === 'start') { startCoords = point; startPoint.position = pickedPosition; viewer.dataSources.removeAll(); endPoint.position = null; endCoords = null; currentStep = 'end'; } else { endCoords = point; endPoint.position = pickedPosition; currentStep = 'start'; } if (startCoords && endCoords) { getRoute(startCoords, endCoords); } } viewer.screenSpaceEventHandler.setInputAction(onLeftClick, Cesium.ScreenSpaceEventType.LEFT_CLICK);
Run the app
Run the app.
When the application loads, you should be able to click on two different locations to create an origin point and a destination. The routing service should then calculate a driving route between them.
What's next?
Learn how to use additional ArcGIS location services in these tutorials:
Find service areas
Calculate the area that can be reached in a given driving time from a location.
Find nearby places and details
Find points of interest near a location and get detailed information about them
Find place addresses
Search for coffee shops, gas stations, restaurants and other nearby places with the Geocoding service.