| name | arcgis-analysis-services |
| description | Perform spatial analysis, geometry operations, and use ArcGIS REST services. Use for routing, geocoding, geoprocessing, elevation analysis, viewshed, and feature queries with statistics. |
ArcGIS Analysis & Services
Use this skill for spatial analysis, geometry operations, REST services, and feature reduction (clustering/binning).
Geometry Operators
ArcGIS Maps SDK provides geometry operators for client-side spatial operations.
Loading Operators
import bufferOperator from "@arcgis/core/geometry/operators/bufferOperator.js";
import intersectOperator from "@arcgis/core/geometry/operators/intersectOperator.js";
import centroidOperator from "@arcgis/core/geometry/operators/centroidOperator.js";
// Load before use (most operators require this)
await bufferOperator.load();
Buffer
import bufferOperator from "@arcgis/core/geometry/operators/bufferOperator.js";
await bufferOperator.load();
const buffered = bufferOperator.execute(point, 1000); // 1000 meters
Geodesic Buffer (accurate over large distances)
import geodesicBufferOperator from "@arcgis/core/geometry/operators/geodesicBufferOperator.js";
await geodesicBufferOperator.load();
const buffered = geodesicBufferOperator.execute(point, {
distances: [100],
unit: "kilometers"
});
Intersect
import intersectOperator from "@arcgis/core/geometry/operators/intersectOperator.js";
await intersectOperator.load();
const intersection = intersectOperator.execute(geometry1, geometry2);
Union
import unionOperator from "@arcgis/core/geometry/operators/unionOperator.js";
await unionOperator.load();
const unioned = unionOperator.execute([polygon1, polygon2, polygon3]);
Centroid
import centroidOperator from "@arcgis/core/geometry/operators/centroidOperator.js";
await centroidOperator.load();
const centroid = centroidOperator.execute(polygon);
Contains / Within
import containsOperator from "@arcgis/core/geometry/operators/containsOperator.js";
await containsOperator.load();
const isContained = containsOperator.execute(polygon, point); // true/false
Distance
import geodeticLengthOperator from "@arcgis/core/geometry/operators/geodeticLengthOperator.js";
await geodeticLengthOperator.load();
const length = geodeticLengthOperator.execute(polyline, { unit: "miles" });
Area
import geodeticAreaOperator from "@arcgis/core/geometry/operators/geodeticAreaOperator.js";
await geodeticAreaOperator.load();
const area = geodeticAreaOperator.execute(polygon, { unit: "square-kilometers" });
Available Operators
| Operator | Purpose |
|---|---|
bufferOperator |
Create buffer around geometry |
geodesicBufferOperator |
Geodetic buffer (accurate) |
intersectOperator |
Find intersection |
unionOperator |
Combine geometries |
differenceOperator |
Subtract geometries |
clipOperator |
Clip geometry by envelope |
convexHullOperator |
Create convex hull |
centroidOperator |
Get centroid point |
containsOperator |
Test if contains |
withinOperator |
Test if within |
intersectsOperator |
Test if intersects |
distanceOperator |
Calculate planar distance |
geodeticLengthOperator |
Calculate geodetic length |
geodeticAreaOperator |
Calculate geodetic area |
simplifyOperator |
Simplify geometry |
densifyOperator |
Add vertices to geometry |
projectOperator |
Project to spatial reference |
Analysis Objects
ElevationProfileAnalysis
import ElevationProfileAnalysis from "@arcgis/core/analysis/ElevationProfileAnalysis.js";
const analysis = new ElevationProfileAnalysis({
profiles: [
{ type: "ground", color: "brown" },
{ type: "input", color: "blue" }
],
displayUnits: {
distance: "meters",
elevation: "meters"
}
});
// Add to SceneView
view.analyses.add(analysis);
// Set line geometry
analysis.geometry = polyline;
// Get analysis view for results
const analysisView = await view.whenAnalysisView(analysis);
// Watch progress and results
reactiveUtils.watch(
() => analysisView.progress,
(progress) => {
if (progress === 1) {
console.log("Results:", analysisView.results);
}
}
);
LineOfSightAnalysis
import LineOfSightAnalysis from "@arcgis/core/analysis/LineOfSightAnalysis.js";
const analysis = new LineOfSightAnalysis({
observer: {
type: "point",
x: -122.4,
y: 37.8,
z: 100,
spatialReference: { wkid: 4326 }
},
targets: [
{ type: "point", x: -122.41, y: 37.81, z: 50 },
{ type: "point", x: -122.42, y: 37.79, z: 75 }
]
});
view.analyses.add(analysis);
ViewshedAnalysis
import ViewshedAnalysis from "@arcgis/core/analysis/ViewshedAnalysis.js";
const analysis = new ViewshedAnalysis({
observer: {
type: "point",
x: -122.4,
y: 37.8,
z: 100,
spatialReference: { wkid: 4326 }
},
farDistance: 1000,
heading: 45,
tilt: 90,
horizontalFieldOfView: 120,
verticalFieldOfView: 90
});
view.analyses.add(analysis);
ShadowCastAnalysis
import ShadowCastAnalysis from "@arcgis/core/analysis/ShadowCastAnalysis.js";
const analysis = new ShadowCastAnalysis();
view.analyses.add(analysis);
// Configure date/time for shadow calculation
view.environment.lighting.date = new Date("2024-06-21T12:00:00");
SliceAnalysis
import SliceAnalysis from "@arcgis/core/analysis/SliceAnalysis.js";
const analysis = new SliceAnalysis({
plane: {
position: { type: "point", x: -122.4, y: 37.8, z: 50 },
heading: 0,
tilt: 0
}
});
view.analyses.add(analysis);
REST Services
Routing
import route from "@arcgis/core/rest/route.js";
const routeParams = {
stops: [
{ geometry: { x: -122.4, y: 37.8 } },
{ geometry: { x: -122.5, y: 37.7 } }
],
outSpatialReference: { wkid: 4326 },
returnDirections: true,
returnRoutes: true
};
const result = await route.solve(
"https://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World",
routeParams
);
const routeGeometry = result.routeResults[0].route.geometry;
const directions = result.routeResults[0].directions;
Geocoding (Address to Location)
import locator from "@arcgis/core/rest/locator.js";
const results = await locator.addressToLocations(
"https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer",
{
address: { SingleLine: "380 New York St, Redlands, CA" },
outFields: ["*"],
maxLocations: 5
}
);
results.forEach(result => {
console.log(result.address, result.location);
});
Reverse Geocoding (Location to Address)
import locator from "@arcgis/core/rest/locator.js";
const result = await locator.locationToAddress(
"https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer",
{
location: { x: -117.195, y: 34.057 }
}
);
console.log(result.address);
Geoprocessing
import geoprocessor from "@arcgis/core/rest/geoprocessor.js";
const params = {
inputLayer: featureSet,
distance: 1000,
distanceUnits: "Meters"
};
const result = await geoprocessor.execute(
"https://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Buffer/GPServer/Buffer",
params
);
const outputFeatures = result.results[0].value;
import print from "@arcgis/core/rest/print.js";
const params = {
view: view,
template: {
format: "pdf",
layout: "letter-ansi-a-landscape",
layoutOptions: {
titleText: "My Map"
}
}
};
const result = await print.execute(
"https://utility.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task",
params
);
// Download the PDF
window.open(result.url);
Places Service
import places from "@arcgis/core/rest/places.js";
import PlacesQueryParameters from "@arcgis/core/rest/support/PlacesQueryParameters.js";
import FetchPlaceParameters from "@arcgis/core/rest/support/FetchPlaceParameters.js";
// Query places near a point
const queryParams = new PlacesQueryParameters({
categoryIds: ["4d4b7104d754a06370d81259"], // Arts and Entertainment
radius: 500, // meters
point: { type: "point", longitude: -87.626, latitude: 41.882 },
icon: "png"
});
const results = await places.queryPlacesNearPoint(queryParams);
// Process results
results.results.forEach(place => {
console.log(place.name, place.location, place.categories[0].label);
console.log("Distance:", place.distance / 1000, "km");
});
// Fetch detailed information about a place
const fetchParams = new FetchPlaceParameters({
placeId: results.results[0].placeId,
requestedFields: ["all"]
});
const details = await places.fetchPlace(fetchParams);
const placeDetails = details.placeDetails;
console.log("Address:", placeDetails.address.streetAddress);
console.log("Phone:", placeDetails.contactInfo.telephone);
console.log("Website:", placeDetails.contactInfo.website);
Places Category IDs
| Category | ID |
|---|---|
| Arts and Entertainment | 4d4b7104d754a06370d81259 |
| Business Services | 4d4b7105d754a06375d81259 |
| Community and Government | 63be6904847c3692a84b9b9a |
| Dining and Drinking | 63be6904847c3692a84b9bb5 |
| Health and Medicine | 63be6904847c3692a84b9bb9 |
| Landmarks and Outdoors | 4d4b7105d754a06377d81259 |
| Retail | 4d4b7105d754a06378d81259 |
| Sports and Recreation | 4f4528bc4b90abdf24c9de85 |
| Travel and Transportation | 4d4b7105d754a06379d81259 |
Feature Queries with Statistics
Basic Statistics
const query = featureLayer.createQuery();
query.outStatistics = [
{
statisticType: "sum",
onStatisticField: "population",
outStatisticFieldName: "totalPop"
},
{
statisticType: "avg",
onStatisticField: "population",
outStatisticFieldName: "avgPop"
},
{
statisticType: "max",
onStatisticField: "population",
outStatisticFieldName: "maxPop"
},
{
statisticType: "min",
onStatisticField: "population",
outStatisticFieldName: "minPop"
},
{
statisticType: "count",
onStatisticField: "population",
outStatisticFieldName: "count"
},
{
statisticType: "stddev",
onStatisticField: "population",
outStatisticFieldName: "stdDev"
}
];
const result = await featureLayer.queryFeatures(query);
console.log(result.features[0].attributes);
Group By Statistics
const query = featureLayer.createQuery();
query.groupByFieldsForStatistics = ["state"];
query.outStatistics = [{
statisticType: "sum",
onStatisticField: "population",
outStatisticFieldName: "totalPop"
}];
query.orderByFields = ["totalPop DESC"];
const result = await featureLayer.queryFeatures(query);
// Returns one feature per state with total population
Spatial Statistics Query
const query = featureLayer.createQuery();
query.geometry = view.extent;
query.spatialRelationship = "intersects";
query.outStatistics = [{
statisticType: "count",
onStatisticField: "ObjectID",
outStatisticFieldName: "featureCount"
}];
const result = await featureLayer.queryFeatures(query);
console.log("Features in view:", result.features[0].attributes.featureCount);
Feature Reduction
Clustering
const clusterConfig = {
type: "cluster",
clusterRadius: "100px",
clusterMinSize: "24px",
clusterMaxSize: "60px",
popupTemplate: {
title: "Cluster summary",
content: "This cluster represents {cluster_count} features.",
fieldInfos: [{
fieldName: "cluster_count",
format: { digitSeparator: true, places: 0 }
}]
},
labelingInfo: [{
deconflictionStrategy: "none",
labelExpressionInfo: {
expression: "Text($feature.cluster_count, '#,###')"
},
symbol: {
type: "text",
color: "white",
font: { size: "12px", weight: "bold" }
},
labelPlacement: "center-center"
}]
};
featureLayer.featureReduction = clusterConfig;
// Toggle clustering
featureLayer.featureReduction = null; // Disable
featureLayer.featureReduction = clusterConfig; // Enable
Cluster with Aggregated Fields
const clusterConfig = {
type: "cluster",
clusterRadius: "100px",
fields: [{
name: "avg_magnitude",
statisticType: "avg",
onStatisticField: "magnitude"
}, {
name: "total_count",
statisticType: "count",
onStatisticField: "ObjectID"
}],
renderer: {
type: "simple",
symbol: {
type: "simple-marker",
style: "circle",
color: "#69dcff"
},
visualVariables: [{
type: "size",
field: "total_count",
stops: [
{ value: 1, size: 8 },
{ value: 100, size: 40 }
]
}]
}
};
Binning
const binConfig = {
type: "binning",
fixedBinLevel: 4, // Level of detail
renderer: {
type: "simple",
symbol: {
type: "simple-fill",
outline: { color: "white", width: 0.5 }
},
visualVariables: [{
type: "color",
field: "aggregateCount",
stops: [
{ value: 1, color: "#feebe2" },
{ value: 50, color: "#fbb4b9" },
{ value: 100, color: "#f768a1" },
{ value: 500, color: "#c51b8a" },
{ value: 1000, color: "#7a0177" }
]
}]
},
popupTemplate: {
title: "Bin",
content: "{aggregateCount} features in this bin"
}
};
featureLayer.featureReduction = binConfig;
Projection
import projectOperator from "@arcgis/core/geometry/operators/projectOperator.js";
await projectOperator.load();
// Project to Web Mercator
const projected = projectOperator.execute(geometry, { wkid: 3857 });
// Project to WGS 84
const wgs84 = projectOperator.execute(geometry, { wkid: 4326 });
TypeScript Usage
Feature reduction configurations use autocasting with type properties. For TypeScript safety, use as const:
// Use 'as const' for type safety
const clusterConfig = {
type: "cluster",
clusterRadius: "100px",
renderer: {
type: "simple",
symbol: {
type: "simple-marker",
color: "#69dcff"
}
} as const,
labelingInfo: [{
labelExpressionInfo: {
expression: "Text($feature.cluster_count, '#,###')"
},
symbol: {
type: "text",
color: "white"
} as const
}]
} as const;
featureLayer.featureReduction = clusterConfig;
Tip: See arcgis-core-maps skill for detailed guidance on autocasting vs explicit classes.
Common Pitfalls
Operator not loaded: Most operators require
await operator.load()before useAPI key required: Some REST services (routing, geocoding) require an API key
Analysis only in SceneView: Some analyses (viewshed, line of sight) only work in 3D
Cluster fields: Use
cluster_countto access feature count in clustersStatistics query returns features: Statistics queries return features with calculated attributes, not raw numbers