Learn how to calculate the area that can be reached in a given driving time from a location.
A service area , also known as an isochrone, is a polygon that represents the area that can be reached when driving or walking on a street network. The area that can be reached is restricted by either time or distance. To calculate service areas , you can use the routing service . You provide a start location (facilities), one or more time or distance values, and a spatial reference. Once processed, the service returns the service areas that can be reached.
In this tutorial, you create and display five, ten, and fifteen minute drive time service areas when the map is clicked. You use data-driven styling to give each polygon a different shade of blue.
Prerequisites You need an ArcGIS Developer or ArcGIS Online account to access the developer dashboard and create an API key .
Steps Create a new pen To get started, either complete the Display a scene tutorial or use this pen . Set the API key To access location services , you need an API key or OAuth 2.0 access token . To learn how to create and scope your key, visit the Create an API key tutorial.
Go to your dashboard to get an API key. The API key must be scoped to access the services used in this tutorial.
In CodePen , update api Key
to use your key. Update cesium Access Token
to use your Cesium ion access token .
Use dark colors for code blocks
Change line Change line
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
const apiKey = "YOUR_API_KEY" ;
Cesium.ArcGisMapService.defaultAccessToken = apiKey;
const cesiumAccessToken = "YOUR_CESIUM_ACCESS_TOKEN" ;
Cesium.Ion.defaultAccessToken = cesiumAccessToken;
const arcGisImagery = Cesium.ArcGisMapServerImageryProvider.fromBasemapType(Cesium.ArcGisBaseMapType.SATELLITE);
const viewer = new Cesium.Viewer( "cesiumContainer" , {
baseLayer : Cesium.ImageryLayer.fromProviderAsync(arcGisImagery),
});
Add references to ArcGIS REST JS In the <head>
element, reference the routing
and request
packages from ArcGIS REST JS.
Expand
Use dark colors for code blocks
Add line. Add line.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
< script src = "https://cesium.com/downloads/cesiumjs/releases/1.105/Build/Cesium/Cesium.js" > </ script >
< link href = "https://cesium.com/downloads/cesiumjs/releases/1.105/Build/Cesium/Widgets/widgets.css" rel = "stylesheet" >
< script src = "https://unpkg.com/@esri/arcgis-rest-request@4.0.0/dist/bundled/request.umd.js" > </ script >
< script src = "https://unpkg.com/@esri/arcgis-rest-routing@4.0.0/dist/bundled/routing.umd.js" > </ script >
Update the scene This routing application uses a 3D object layer San Francisco. Update the scene extent to focus on San Francisco, CA.
Update the set View
command to center on location [-122.38329, 37.74015, 16000]
, San Francisco.
Expand
Use dark colors for code blocks
Change line Change line Change line Change line Change line
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
viewer.camera.setView({
destination : Cesium.Cartesian3.fromDegrees( 8.68019 , 50.1147 , 500 ),
orientation : {
heading : Cesium.Math.toRadians(- 120 ),
pitch : Cesium.Math.toRadians(- 28.0 ),
}
});
Add the San Francisco Buildings 3D object layer to the scene as an I3SData Provider
.
Expand
Use dark colors for code blocks
Add line. Add line. Add line. Add line. Add line. Add line.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
viewer.camera.setView({
destination : Cesium.Cartesian3.fromDegrees( 8.68019 , 50.1147 , 500 ),
orientation : {
heading : Cesium.Math.toRadians(- 120 ),
pitch : Cesium.Math.toRadians(- 28.0 ),
}
});
const geoidService = await Cesium.ArcGISTiledElevationTerrainProvider.fromUrl( "https://tiles.arcgis.com/tiles/z2tnIkrLQ2BRzr6P/arcgis/rest/services/EGM2008/ImageServer" );
const i3sProvider = await Cesium.I3SDataProvider.fromUrl( "https://tiles.arcgis.com/tiles/cFEFS0EWrhfDeVw9/arcgis/rest/services/Buildings_Frankfurt_2021/SceneServer" , {
geoidTiledTerrainProvider : geoidService,
token : apiKey
})
viewer.scene.primitives.add(i3sProvider);
Create a starting location graphic Create a Billboard
entity to indicate the location from which a service area will be calculated. You can use Billboard
entities to display custom pins and images.
Add a new Billboard
entity to the viewer to represent the origin location. Set the position
of the entity to null
.
Use dark colors for code blocks
Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<!DOCTYPE html >
< html lang = "en" >
< head >
< title > CesiumJS: Find service areas </ title >
< script src = "https://cesium.com/downloads/cesiumjs/releases/1.105/Build/Cesium/Cesium.js" > </ script >
< link href = "https://cesium.com/downloads/cesiumjs/releases/1.105/Build/Cesium/Widgets/widgets.css" rel = "stylesheet" >
<!-- Load ArcGIS REST JS from CDN -->
< script src = "https://unpkg.com/@esri/arcgis-rest-request@4.0.0/dist/bundled/request.umd.js" > </ script >
< script src = "https://unpkg.com/@esri/arcgis-rest-routing@4.0.0/dist/bundled/routing.umd.js" > </ script >
< style >
html , body , #cesiumContainer {
margin : 0px ;
padding : 0px ;
height : 100% ;
width : 100% ;
}
</ style >
</ head >
< body >
< div id = "cesiumContainer" > </ div >
< script >
const apiKey = "YOUR_API_KEY" ;
Cesium.ArcGisMapService.defaultAccessToken = apiKey;
const authentication = arcgisRest.ApiKeyManager.fromKey(apiKey);
const cesiumAccessToken = "YOUR_CESIUM_ACCESS_TOKEN" ;
Cesium.Ion.defaultAccessToken = cesiumAccessToken;
const arcGisImagery = Cesium.ArcGisMapServerImageryProvider.fromBasemapType(Cesium.ArcGisBaseMapType.SATELLITE, {
enablePickFeatures : false
});
const viewer = new Cesium.Viewer( "cesiumContainer" , {
baseLayer : Cesium.ImageryLayer.fromProviderAsync(arcGisImagery),
terrain : Cesium.Terrain.fromWorldTerrain(),
timeline : false ,
animation : false ,
geocoder : false
});
viewer.camera.setView({
destination : Cesium.Cartesian3.fromDegrees(- 122.38329 , 37.74015 , 16000 ),
orientation : {
pitch : Cesium.Math.toRadians(- 70.0 ),
}
});
const origin = viewer.entities.add({
name : 'start' ,
position : null ,
billboard : {
verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
heightReference : Cesium.HeightReference.CLAMP_TO_GROUND,
}
})
</ script >
</ body >
</ html >
Create a Pin Builder
and use it to set the image
property of the billboard.
Expand
Use dark colors for code blocks
Add line. Add line.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
const pinBuilder = new Cesium.PinBuilder();
const origin = viewer.entities.add({
name : 'start' ,
position : null ,
billboard : {
verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
heightReference : Cesium.HeightReference.CLAMP_TO_GROUND,
image : pinBuilder.fromColor(Cesium.Color.fromCssColorString( '#ffffff' ), 48 ).toDataURL(),
}
})
Add a click handler Use an event handler to set the location of the origin and when a user clicks.
Create a Screen Space Event Handler
for the Viewer
that listens for left clicks. Create an o n Left Click
function that runs when a click is detected.
Expand
Use dark colors for code blocks
Add line. Add line. Add line.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
image : pinBuilder.fromColor(Cesium.Color.fromCssColorString( '#ffffff' ), 48 ).toDataURL(),
}
})
viewer.screenSpaceEventHandler.setInputAction( movement => {
},Cesium.ScreenSpaceEventType.LEFT_CLICK);
Set the position of the origin
entity to the coordinates of the clicked location. Call viewer.data Sources.remove All()
to remove stale service area polygons.
Expand
Use dark colors for code blocks
Add line. Add line. Add line. Add line.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
viewer.screenSpaceEventHandler.setInputAction( movement => {
const pickedPosition = viewer.scene.pickPosition(movement.position);
origin.position = pickedPosition;
viewer.dataSources.removeAll();
},Cesium.ScreenSpaceEventType.LEFT_CLICK);
Get service areas To calculate a service area from a point, use the ArcGIS REST JS service Area
function to make a request to the routing service .
In order to access ArcGIS location services with ArcGIS REST JS , you need an access token , either an API key or a token created by OAuth 2.0 authentication. API keys have scopes, so make sure to scope your API key with permissions to access the service.
Create a new arcgis Rest.Api K e y Manager
and set your API key.
Expand
Use dark colors for code blocks
Add line.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
const apiKey = "YOUR_API_KEY" ;
Cesium.ArcGisMapService.defaultAccessToken = apiKey;
const authentication = arcgisRest.ApiKeyManager.fromKey(apiKey);
Create a function called get Service Area
that accepts a coordinate pair. Inside, call arcgis Rest.service Area
and set the facilities
parameter to the set of coordinates.
More info arcgis Rest.service Area
creates a direct request to the solve Service Area
endpoint of the routing service . To learn more about the solve Service Area
endpoint, go to the Routing service page in the Mapping APIs and location services guide.
Expand
Use dark colors for code blocks
Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
viewer.screenSpaceEventHandler.setInputAction( movement => {
const pickedPosition = viewer.scene.pickPosition(movement.position);
origin.position = pickedPosition;
viewer.dataSources.removeAll();
},Cesium.ScreenSpaceEventType.LEFT_CLICK);
function getServiceArea ( coordinates ) {
arcgisRest
.serviceArea({
facilities : [coordinates],
authentication
})
}
Access the service response and add the returned GeoJSON to your application as a Geo Json Data Source
.
Expand
Use dark colors for code blocks
Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
function getServiceArea ( coordinates ) {
arcgisRest
.serviceArea({
facilities : [coordinates],
authentication
})
.then( ( response ) => {
const serviceJSON = response.saPolygons.geoJson;
Cesium.GeoJsonDataSource.load(serviceJSON,{
clampToGround : true
})
.then( ( dataSource )=> {
viewer.dataSources.add(dataSource);
});
})
}
Set the material
of each service area polygon based on its drive time from the origin using the From Break
property.
Expand
Use dark colors for code blocks
Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
.then( ( response ) => {
const serviceJSON = response.saPolygons.geoJson;
Cesium.GeoJsonDataSource.load(serviceJSON,{
clampToGround : true
})
.then( ( dataSource )=> {
viewer.dataSources.add(dataSource);
const entities = dataSource.entities.values;
for ( let i= 0 ; i<entities.length;i++) {
const feature = entities[i];
feature.polygon.outline = false ;
if (feature.properties.FromBreak == 0 ) {
feature.polygon.material = Cesium.Color.fromHsl( 0.5833 , .8 , .4 , .7 );
feature.polygon.extrudedHeight = 300 ;
}
else if (feature.properties.FromBreak == 5 ) {
feature.polygon.material = Cesium.Color.fromHsl( 0.5833 , .8 , .6 , .7 );
feature.polygon.extrudedHeight = 200 ;
}
else {
feature.polygon.material = Cesium.Color.fromHsl( 0.5833 , .8 , .8 , .7 );
feature.polygon.extrudedHeight = 100 ;
}
}
});
})
In your o n Left Click
function, convert the coordinates of the user's click from Cartesian
to longitude and latitude degrees. Call get Service Area
with the longitude and latitude
Expand
Use dark colors for code blocks
Add line. Add line. Add line. Add line.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
viewer.screenSpaceEventHandler.setInputAction( movement => {
const pickedPosition = viewer.scene.pickPosition(movement.position);
origin.position = pickedPosition;
viewer.dataSources.removeAll();
const cartographic = Cesium.Cartographic.fromCartesian(pickedPosition);
const originLatLng = [Cesium.Math.toDegrees(cartographic.longitude),Cesium.Math.toDegrees(cartographic.latitude)]
getServiceArea(originLatLng);
},Cesium.ScreenSpaceEventType.LEFT_CLICK);
Run the app In CodePen , run your code to display the map.
When the application loads, you should be able to click on a locations to create an origin point. The routing service should then calculate drive time polygons representing the areas reachable within a 5, 10, and 15 minute drive.
What's next? Learn how to use additional ArcGIS location services in these tutorials: