Arcgis Analysis Services
by SaschaBrunnerCH
Perform spatial analysis, geometry operations, and use ArcGIS REST services. Use for routing, geocoding, geoprocessing, elevation analysis, viewshed, and feature queries with statistics.
Skill Details
Repository Files
1 file in this skill directory
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 use -
API 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 clusters -
Statistics query returns features: Statistics queries return features with calculated attributes, not raw numbers
Related Skills
Attack Tree Construction
Build comprehensive attack trees to visualize threat paths. Use when mapping attack scenarios, identifying defense gaps, or communicating security risks to stakeholders.
Grafana Dashboards
Create and manage production Grafana dashboards for real-time visualization of system and application metrics. Use when building monitoring dashboards, visualizing metrics, or creating operational observability interfaces.
Matplotlib
Foundational plotting library. Create line plots, scatter, bar, histograms, heatmaps, 3D, subplots, export PNG/PDF/SVG, for scientific visualization and publication figures.
Scientific Visualization
Create publication figures with matplotlib/seaborn/plotly. Multi-panel layouts, error bars, significance markers, colorblind-safe, export PDF/EPS/TIFF, for journal-ready scientific plots.
Seaborn
Statistical visualization. Scatter, box, violin, heatmaps, pair plots, regression, correlation matrices, KDE, faceted plots, for exploratory analysis and publication figures.
Shap
Model interpretability and explainability using SHAP (SHapley Additive exPlanations). Use this skill when explaining machine learning model predictions, computing feature importance, generating SHAP plots (waterfall, beeswarm, bar, scatter, force, heatmap), debugging models, analyzing model bias or fairness, comparing models, or implementing explainable AI. Works with tree-based models (XGBoost, LightGBM, Random Forest), deep learning (TensorFlow, PyTorch), linear models, and any black-box model
Pydeseq2
Differential gene expression analysis (Python DESeq2). Identify DE genes from bulk RNA-seq counts, Wald tests, FDR correction, volcano/MA plots, for RNA-seq analysis.
Query Writing
For writing and executing SQL queries - from simple single-table queries to complex multi-table JOINs and aggregations
Pydeseq2
Differential gene expression analysis (Python DESeq2). Identify DE genes from bulk RNA-seq counts, Wald tests, FDR correction, volcano/MA plots, for RNA-seq analysis.
Scientific Visualization
Meta-skill for publication-ready figures. Use when creating journal submission figures requiring multi-panel layouts, significance annotations, error bars, colorblind-safe palettes, and specific journal formatting (Nature, Science, Cell). Orchestrates matplotlib/seaborn/plotly with publication styles. For quick exploration use seaborn or plotly directly.
