@saschabrunnerch/arcgis-maps-sdk-js-ai-context 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +163 -201
  2. package/bin/cli.js +157 -173
  3. package/contexts/4.34/{claude → skills}/arcgis-3d-advanced/SKILL.md +586 -586
  4. package/contexts/4.34/{claude → skills}/arcgis-advanced-layers/SKILL.md +431 -431
  5. package/contexts/4.34/{claude → skills}/arcgis-analysis-services/SKILL.md +607 -607
  6. package/contexts/4.34/{claude → skills}/arcgis-authentication/SKILL.md +301 -301
  7. package/contexts/4.34/{claude → skills}/arcgis-cim-symbols/SKILL.md +486 -486
  8. package/contexts/4.34/{claude → skills}/arcgis-coordinates-projection/SKILL.md +406 -406
  9. package/contexts/4.34/{claude → skills}/arcgis-core-maps/SKILL.md +739 -739
  10. package/contexts/4.34/{claude → skills}/arcgis-core-utilities/SKILL.md +732 -732
  11. package/contexts/4.34/{claude → skills}/arcgis-custom-rendering/SKILL.md +445 -445
  12. package/contexts/4.34/{claude → skills}/arcgis-editing-advanced/SKILL.md +702 -702
  13. package/contexts/4.34/{claude → skills}/arcgis-feature-effects/SKILL.md +393 -393
  14. package/contexts/4.34/{claude → skills}/arcgis-geometry-operations/SKILL.md +489 -489
  15. package/contexts/4.34/{claude → skills}/arcgis-imagery/SKILL.md +307 -307
  16. package/contexts/4.34/{claude → skills}/arcgis-interaction/SKILL.md +572 -572
  17. package/contexts/4.34/{claude → skills}/arcgis-knowledge-graphs/SKILL.md +582 -582
  18. package/contexts/4.34/{claude → skills}/arcgis-layers/SKILL.md +601 -601
  19. package/contexts/4.34/{claude → skills}/arcgis-map-tools/SKILL.md +668 -668
  20. package/contexts/4.34/{claude → skills}/arcgis-media-layers/SKILL.md +290 -290
  21. package/contexts/4.34/{claude → skills}/arcgis-portal-content/SKILL.md +679 -679
  22. package/contexts/4.34/{claude → skills}/arcgis-scene-effects/SKILL.md +512 -512
  23. package/contexts/4.34/{claude → skills}/arcgis-smart-mapping/SKILL.md +686 -686
  24. package/contexts/4.34/skills/arcgis-starter-app/SKILL.md +273 -0
  25. package/contexts/4.34/skills/arcgis-starter-app-extended/SKILL.md +649 -0
  26. package/contexts/4.34/{claude → skills}/arcgis-tables-forms/SKILL.md +877 -877
  27. package/contexts/4.34/{claude → skills}/arcgis-time-animation/SKILL.md +722 -722
  28. package/contexts/4.34/{claude → skills}/arcgis-utility-networks/SKILL.md +301 -301
  29. package/contexts/4.34/{claude → skills}/arcgis-visualization/SKILL.md +580 -580
  30. package/contexts/4.34/{claude → skills}/arcgis-widgets-ui/SKILL.md +574 -574
  31. package/lib/installer.js +294 -379
  32. package/package.json +45 -45
  33. package/contexts/4.34/copilot/arcgis-3d.instructions.md +0 -267
  34. package/contexts/4.34/copilot/arcgis-analysis.instructions.md +0 -294
  35. package/contexts/4.34/copilot/arcgis-arcade.instructions.md +0 -234
  36. package/contexts/4.34/copilot/arcgis-authentication.instructions.md +0 -187
  37. package/contexts/4.34/copilot/arcgis-cim-symbols.instructions.md +0 -177
  38. package/contexts/4.34/copilot/arcgis-core-maps.instructions.md +0 -246
  39. package/contexts/4.34/copilot/arcgis-core-utilities.instructions.md +0 -247
  40. package/contexts/4.34/copilot/arcgis-editing.instructions.md +0 -262
  41. package/contexts/4.34/copilot/arcgis-geometry.instructions.md +0 -225
  42. package/contexts/4.34/copilot/arcgis-layers.instructions.md +0 -278
  43. package/contexts/4.34/copilot/arcgis-popup-templates.instructions.md +0 -266
  44. package/contexts/4.34/copilot/arcgis-portal-advanced.instructions.md +0 -275
  45. package/contexts/4.34/copilot/arcgis-smart-mapping.instructions.md +0 -184
  46. package/contexts/4.34/copilot/arcgis-time-animation.instructions.md +0 -112
  47. package/contexts/4.34/copilot/arcgis-visualization.instructions.md +0 -321
  48. package/contexts/4.34/copilot/arcgis-widgets-ui.instructions.md +0 -277
  49. /package/contexts/4.34/{claude → skills}/arcgis-arcade/SKILL.md +0 -0
  50. /package/contexts/4.34/{claude → skills}/arcgis-popup-templates/SKILL.md +0 -0
@@ -1,607 +1,607 @@
1
- ---
2
- name: arcgis-analysis-services
3
- description: Perform spatial analysis, geometry operations, and use ArcGIS REST services. Use for routing, geocoding, geoprocessing, elevation analysis, viewshed, and feature queries with statistics.
4
- ---
5
-
6
- # ArcGIS Analysis & Services
7
-
8
- Use this skill for spatial analysis, geometry operations, REST services, and feature reduction (clustering/binning).
9
-
10
- ## Geometry Operators
11
-
12
- ArcGIS Maps SDK provides geometry operators for client-side spatial operations.
13
-
14
- ### Loading Operators
15
-
16
- ```javascript
17
- import bufferOperator from "@arcgis/core/geometry/operators/bufferOperator.js";
18
- import intersectOperator from "@arcgis/core/geometry/operators/intersectOperator.js";
19
- import centroidOperator from "@arcgis/core/geometry/operators/centroidOperator.js";
20
-
21
- // Load before use (most operators require this)
22
- await bufferOperator.load();
23
- ```
24
-
25
- ### Buffer
26
- ```javascript
27
- import bufferOperator from "@arcgis/core/geometry/operators/bufferOperator.js";
28
- await bufferOperator.load();
29
-
30
- const buffered = bufferOperator.execute(point, 1000); // 1000 meters
31
- ```
32
-
33
- ### Geodesic Buffer (accurate over large distances)
34
- ```javascript
35
- import geodesicBufferOperator from "@arcgis/core/geometry/operators/geodesicBufferOperator.js";
36
- await geodesicBufferOperator.load();
37
-
38
- const buffered = geodesicBufferOperator.execute(point, {
39
- distances: [100],
40
- unit: "kilometers"
41
- });
42
- ```
43
-
44
- ### Intersect
45
- ```javascript
46
- import intersectOperator from "@arcgis/core/geometry/operators/intersectOperator.js";
47
- await intersectOperator.load();
48
-
49
- const intersection = intersectOperator.execute(geometry1, geometry2);
50
- ```
51
-
52
- ### Union
53
- ```javascript
54
- import unionOperator from "@arcgis/core/geometry/operators/unionOperator.js";
55
- await unionOperator.load();
56
-
57
- const unioned = unionOperator.execute([polygon1, polygon2, polygon3]);
58
- ```
59
-
60
- ### Centroid
61
- ```javascript
62
- import centroidOperator from "@arcgis/core/geometry/operators/centroidOperator.js";
63
- await centroidOperator.load();
64
-
65
- const centroid = centroidOperator.execute(polygon);
66
- ```
67
-
68
- ### Contains / Within
69
- ```javascript
70
- import containsOperator from "@arcgis/core/geometry/operators/containsOperator.js";
71
- await containsOperator.load();
72
-
73
- const isContained = containsOperator.execute(polygon, point); // true/false
74
- ```
75
-
76
- ### Distance
77
- ```javascript
78
- import geodeticLengthOperator from "@arcgis/core/geometry/operators/geodeticLengthOperator.js";
79
- await geodeticLengthOperator.load();
80
-
81
- const length = geodeticLengthOperator.execute(polyline, { unit: "miles" });
82
- ```
83
-
84
- ### Area
85
- ```javascript
86
- import geodeticAreaOperator from "@arcgis/core/geometry/operators/geodeticAreaOperator.js";
87
- await geodeticAreaOperator.load();
88
-
89
- const area = geodeticAreaOperator.execute(polygon, { unit: "square-kilometers" });
90
- ```
91
-
92
- ### Available Operators
93
-
94
- | Operator | Purpose |
95
- |----------|---------|
96
- | `bufferOperator` | Create buffer around geometry |
97
- | `geodesicBufferOperator` | Geodetic buffer (accurate) |
98
- | `intersectOperator` | Find intersection |
99
- | `unionOperator` | Combine geometries |
100
- | `differenceOperator` | Subtract geometries |
101
- | `clipOperator` | Clip geometry by envelope |
102
- | `convexHullOperator` | Create convex hull |
103
- | `centroidOperator` | Get centroid point |
104
- | `containsOperator` | Test if contains |
105
- | `withinOperator` | Test if within |
106
- | `intersectsOperator` | Test if intersects |
107
- | `distanceOperator` | Calculate planar distance |
108
- | `geodeticLengthOperator` | Calculate geodetic length |
109
- | `geodeticAreaOperator` | Calculate geodetic area |
110
- | `simplifyOperator` | Simplify geometry |
111
- | `densifyOperator` | Add vertices to geometry |
112
- | `projectOperator` | Project to spatial reference |
113
-
114
- ## Analysis Objects
115
-
116
- ### ElevationProfileAnalysis
117
- ```javascript
118
- import ElevationProfileAnalysis from "@arcgis/core/analysis/ElevationProfileAnalysis.js";
119
-
120
- const analysis = new ElevationProfileAnalysis({
121
- profiles: [
122
- { type: "ground", color: "brown" },
123
- { type: "input", color: "blue" }
124
- ],
125
- displayUnits: {
126
- distance: "meters",
127
- elevation: "meters"
128
- }
129
- });
130
-
131
- // Add to SceneView
132
- view.analyses.add(analysis);
133
-
134
- // Set line geometry
135
- analysis.geometry = polyline;
136
-
137
- // Get analysis view for results
138
- const analysisView = await view.whenAnalysisView(analysis);
139
-
140
- // Watch progress and results
141
- reactiveUtils.watch(
142
- () => analysisView.progress,
143
- (progress) => {
144
- if (progress === 1) {
145
- console.log("Results:", analysisView.results);
146
- }
147
- }
148
- );
149
- ```
150
-
151
- ### LineOfSightAnalysis
152
- ```javascript
153
- import LineOfSightAnalysis from "@arcgis/core/analysis/LineOfSightAnalysis.js";
154
-
155
- const analysis = new LineOfSightAnalysis({
156
- observer: {
157
- type: "point",
158
- x: -122.4,
159
- y: 37.8,
160
- z: 100,
161
- spatialReference: { wkid: 4326 }
162
- },
163
- targets: [
164
- { type: "point", x: -122.41, y: 37.81, z: 50 },
165
- { type: "point", x: -122.42, y: 37.79, z: 75 }
166
- ]
167
- });
168
-
169
- view.analyses.add(analysis);
170
- ```
171
-
172
- ### ViewshedAnalysis
173
- ```javascript
174
- import ViewshedAnalysis from "@arcgis/core/analysis/ViewshedAnalysis.js";
175
-
176
- const analysis = new ViewshedAnalysis({
177
- observer: {
178
- type: "point",
179
- x: -122.4,
180
- y: 37.8,
181
- z: 100,
182
- spatialReference: { wkid: 4326 }
183
- },
184
- farDistance: 1000,
185
- heading: 45,
186
- tilt: 90,
187
- horizontalFieldOfView: 120,
188
- verticalFieldOfView: 90
189
- });
190
-
191
- view.analyses.add(analysis);
192
- ```
193
-
194
- ### ShadowCastAnalysis
195
- ```javascript
196
- import ShadowCastAnalysis from "@arcgis/core/analysis/ShadowCastAnalysis.js";
197
-
198
- const analysis = new ShadowCastAnalysis();
199
- view.analyses.add(analysis);
200
-
201
- // Configure date/time for shadow calculation
202
- view.environment.lighting.date = new Date("2024-06-21T12:00:00");
203
- ```
204
-
205
- ### SliceAnalysis
206
- ```javascript
207
- import SliceAnalysis from "@arcgis/core/analysis/SliceAnalysis.js";
208
-
209
- const analysis = new SliceAnalysis({
210
- plane: {
211
- position: { type: "point", x: -122.4, y: 37.8, z: 50 },
212
- heading: 0,
213
- tilt: 0
214
- }
215
- });
216
-
217
- view.analyses.add(analysis);
218
- ```
219
-
220
- ## REST Services
221
-
222
- ### Routing
223
-
224
- ```javascript
225
- import route from "@arcgis/core/rest/route.js";
226
-
227
- const routeParams = {
228
- stops: [
229
- { geometry: { x: -122.4, y: 37.8 } },
230
- { geometry: { x: -122.5, y: 37.7 } }
231
- ],
232
- outSpatialReference: { wkid: 4326 },
233
- returnDirections: true,
234
- returnRoutes: true
235
- };
236
-
237
- const result = await route.solve(
238
- "https://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World",
239
- routeParams
240
- );
241
-
242
- const routeGeometry = result.routeResults[0].route.geometry;
243
- const directions = result.routeResults[0].directions;
244
- ```
245
-
246
- ### Geocoding (Address to Location)
247
-
248
- ```javascript
249
- import locator from "@arcgis/core/rest/locator.js";
250
-
251
- const results = await locator.addressToLocations(
252
- "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer",
253
- {
254
- address: { SingleLine: "380 New York St, Redlands, CA" },
255
- outFields: ["*"],
256
- maxLocations: 5
257
- }
258
- );
259
-
260
- results.forEach(result => {
261
- console.log(result.address, result.location);
262
- });
263
- ```
264
-
265
- ### Reverse Geocoding (Location to Address)
266
-
267
- ```javascript
268
- import locator from "@arcgis/core/rest/locator.js";
269
-
270
- const result = await locator.locationToAddress(
271
- "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer",
272
- {
273
- location: { x: -117.195, y: 34.057 }
274
- }
275
- );
276
-
277
- console.log(result.address);
278
- ```
279
-
280
- ### Geoprocessing
281
-
282
- ```javascript
283
- import geoprocessor from "@arcgis/core/rest/geoprocessor.js";
284
-
285
- const params = {
286
- inputLayer: featureSet,
287
- distance: 1000,
288
- distanceUnits: "Meters"
289
- };
290
-
291
- const result = await geoprocessor.execute(
292
- "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Buffer/GPServer/Buffer",
293
- params
294
- );
295
-
296
- const outputFeatures = result.results[0].value;
297
- ```
298
-
299
- ### Print
300
-
301
- ```javascript
302
- import print from "@arcgis/core/rest/print.js";
303
-
304
- const params = {
305
- view: view,
306
- template: {
307
- format: "pdf",
308
- layout: "letter-ansi-a-landscape",
309
- layoutOptions: {
310
- titleText: "My Map"
311
- }
312
- }
313
- };
314
-
315
- const result = await print.execute(
316
- "https://utility.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task",
317
- params
318
- );
319
-
320
- // Download the PDF
321
- window.open(result.url);
322
- ```
323
-
324
- ### Places Service
325
-
326
- ```javascript
327
- import places from "@arcgis/core/rest/places.js";
328
- import PlacesQueryParameters from "@arcgis/core/rest/support/PlacesQueryParameters.js";
329
- import FetchPlaceParameters from "@arcgis/core/rest/support/FetchPlaceParameters.js";
330
-
331
- // Query places near a point
332
- const queryParams = new PlacesQueryParameters({
333
- categoryIds: ["4d4b7104d754a06370d81259"], // Arts and Entertainment
334
- radius: 500, // meters
335
- point: { type: "point", longitude: -87.626, latitude: 41.882 },
336
- icon: "png"
337
- });
338
-
339
- const results = await places.queryPlacesNearPoint(queryParams);
340
-
341
- // Process results
342
- results.results.forEach(place => {
343
- console.log(place.name, place.location, place.categories[0].label);
344
- console.log("Distance:", place.distance / 1000, "km");
345
- });
346
-
347
- // Fetch detailed information about a place
348
- const fetchParams = new FetchPlaceParameters({
349
- placeId: results.results[0].placeId,
350
- requestedFields: ["all"]
351
- });
352
-
353
- const details = await places.fetchPlace(fetchParams);
354
- const placeDetails = details.placeDetails;
355
-
356
- console.log("Address:", placeDetails.address.streetAddress);
357
- console.log("Phone:", placeDetails.contactInfo.telephone);
358
- console.log("Website:", placeDetails.contactInfo.website);
359
- ```
360
-
361
- ### Places Category IDs
362
-
363
- | Category | ID |
364
- |----------|-----|
365
- | Arts and Entertainment | `4d4b7104d754a06370d81259` |
366
- | Business Services | `4d4b7105d754a06375d81259` |
367
- | Community and Government | `63be6904847c3692a84b9b9a` |
368
- | Dining and Drinking | `63be6904847c3692a84b9bb5` |
369
- | Health and Medicine | `63be6904847c3692a84b9bb9` |
370
- | Landmarks and Outdoors | `4d4b7105d754a06377d81259` |
371
- | Retail | `4d4b7105d754a06378d81259` |
372
- | Sports and Recreation | `4f4528bc4b90abdf24c9de85` |
373
- | Travel and Transportation | `4d4b7105d754a06379d81259` |
374
-
375
- ## Feature Queries with Statistics
376
-
377
- ### Basic Statistics
378
- ```javascript
379
- const query = featureLayer.createQuery();
380
- query.outStatistics = [
381
- {
382
- statisticType: "sum",
383
- onStatisticField: "population",
384
- outStatisticFieldName: "totalPop"
385
- },
386
- {
387
- statisticType: "avg",
388
- onStatisticField: "population",
389
- outStatisticFieldName: "avgPop"
390
- },
391
- {
392
- statisticType: "max",
393
- onStatisticField: "population",
394
- outStatisticFieldName: "maxPop"
395
- },
396
- {
397
- statisticType: "min",
398
- onStatisticField: "population",
399
- outStatisticFieldName: "minPop"
400
- },
401
- {
402
- statisticType: "count",
403
- onStatisticField: "population",
404
- outStatisticFieldName: "count"
405
- },
406
- {
407
- statisticType: "stddev",
408
- onStatisticField: "population",
409
- outStatisticFieldName: "stdDev"
410
- }
411
- ];
412
-
413
- const result = await featureLayer.queryFeatures(query);
414
- console.log(result.features[0].attributes);
415
- ```
416
-
417
- ### Group By Statistics
418
- ```javascript
419
- const query = featureLayer.createQuery();
420
- query.groupByFieldsForStatistics = ["state"];
421
- query.outStatistics = [{
422
- statisticType: "sum",
423
- onStatisticField: "population",
424
- outStatisticFieldName: "totalPop"
425
- }];
426
- query.orderByFields = ["totalPop DESC"];
427
-
428
- const result = await featureLayer.queryFeatures(query);
429
- // Returns one feature per state with total population
430
- ```
431
-
432
- ### Spatial Statistics Query
433
- ```javascript
434
- const query = featureLayer.createQuery();
435
- query.geometry = view.extent;
436
- query.spatialRelationship = "intersects";
437
- query.outStatistics = [{
438
- statisticType: "count",
439
- onStatisticField: "ObjectID",
440
- outStatisticFieldName: "featureCount"
441
- }];
442
-
443
- const result = await featureLayer.queryFeatures(query);
444
- console.log("Features in view:", result.features[0].attributes.featureCount);
445
- ```
446
-
447
- ## Feature Reduction
448
-
449
- ### Clustering
450
-
451
- ```javascript
452
- const clusterConfig = {
453
- type: "cluster",
454
- clusterRadius: "100px",
455
- clusterMinSize: "24px",
456
- clusterMaxSize: "60px",
457
- popupTemplate: {
458
- title: "Cluster summary",
459
- content: "This cluster represents {cluster_count} features.",
460
- fieldInfos: [{
461
- fieldName: "cluster_count",
462
- format: { digitSeparator: true, places: 0 }
463
- }]
464
- },
465
- labelingInfo: [{
466
- deconflictionStrategy: "none",
467
- labelExpressionInfo: {
468
- expression: "Text($feature.cluster_count, '#,###')"
469
- },
470
- symbol: {
471
- type: "text",
472
- color: "white",
473
- font: { size: "12px", weight: "bold" }
474
- },
475
- labelPlacement: "center-center"
476
- }]
477
- };
478
-
479
- featureLayer.featureReduction = clusterConfig;
480
-
481
- // Toggle clustering
482
- featureLayer.featureReduction = null; // Disable
483
- featureLayer.featureReduction = clusterConfig; // Enable
484
- ```
485
-
486
- ### Cluster with Aggregated Fields
487
- ```javascript
488
- const clusterConfig = {
489
- type: "cluster",
490
- clusterRadius: "100px",
491
- fields: [{
492
- name: "avg_magnitude",
493
- statisticType: "avg",
494
- onStatisticField: "magnitude"
495
- }, {
496
- name: "total_count",
497
- statisticType: "count",
498
- onStatisticField: "ObjectID"
499
- }],
500
- renderer: {
501
- type: "simple",
502
- symbol: {
503
- type: "simple-marker",
504
- style: "circle",
505
- color: "#69dcff"
506
- },
507
- visualVariables: [{
508
- type: "size",
509
- field: "total_count",
510
- stops: [
511
- { value: 1, size: 8 },
512
- { value: 100, size: 40 }
513
- ]
514
- }]
515
- }
516
- };
517
- ```
518
-
519
- ### Binning
520
- ```javascript
521
- const binConfig = {
522
- type: "binning",
523
- fixedBinLevel: 4, // Level of detail
524
- renderer: {
525
- type: "simple",
526
- symbol: {
527
- type: "simple-fill",
528
- outline: { color: "white", width: 0.5 }
529
- },
530
- visualVariables: [{
531
- type: "color",
532
- field: "aggregateCount",
533
- stops: [
534
- { value: 1, color: "#feebe2" },
535
- { value: 50, color: "#fbb4b9" },
536
- { value: 100, color: "#f768a1" },
537
- { value: 500, color: "#c51b8a" },
538
- { value: 1000, color: "#7a0177" }
539
- ]
540
- }]
541
- },
542
- popupTemplate: {
543
- title: "Bin",
544
- content: "{aggregateCount} features in this bin"
545
- }
546
- };
547
-
548
- featureLayer.featureReduction = binConfig;
549
- ```
550
-
551
- ## Projection
552
-
553
- ```javascript
554
- import projectOperator from "@arcgis/core/geometry/operators/projectOperator.js";
555
- await projectOperator.load();
556
-
557
- // Project to Web Mercator
558
- const projected = projectOperator.execute(geometry, { wkid: 3857 });
559
-
560
- // Project to WGS 84
561
- const wgs84 = projectOperator.execute(geometry, { wkid: 4326 });
562
- ```
563
-
564
- ## TypeScript Usage
565
-
566
- Feature reduction configurations use autocasting with `type` properties. For TypeScript safety, use `as const`:
567
-
568
- ```typescript
569
- // Use 'as const' for type safety
570
- const clusterConfig = {
571
- type: "cluster",
572
- clusterRadius: "100px",
573
- renderer: {
574
- type: "simple",
575
- symbol: {
576
- type: "simple-marker",
577
- color: "#69dcff"
578
- }
579
- } as const,
580
- labelingInfo: [{
581
- labelExpressionInfo: {
582
- expression: "Text($feature.cluster_count, '#,###')"
583
- },
584
- symbol: {
585
- type: "text",
586
- color: "white"
587
- } as const
588
- }]
589
- } as const;
590
-
591
- featureLayer.featureReduction = clusterConfig;
592
- ```
593
-
594
- > **Tip:** See [arcgis-core-maps skill](../arcgis-core-maps/SKILL.md) for detailed guidance on autocasting vs explicit classes.
595
-
596
- ## Common Pitfalls
597
-
598
- 1. **Operator not loaded**: Most operators require `await operator.load()` before use
599
-
600
- 2. **API key required**: Some REST services (routing, geocoding) require an API key
601
-
602
- 3. **Analysis only in SceneView**: Some analyses (viewshed, line of sight) only work in 3D
603
-
604
- 4. **Cluster fields**: Use `cluster_count` to access feature count in clusters
605
-
606
- 5. **Statistics query returns features**: Statistics queries return features with calculated attributes, not raw numbers
607
-
1
+ ---
2
+ name: arcgis-analysis-services
3
+ description: Perform spatial analysis, geometry operations, and use ArcGIS REST services. Use for routing, geocoding, geoprocessing, elevation analysis, viewshed, and feature queries with statistics.
4
+ ---
5
+
6
+ # ArcGIS Analysis & Services
7
+
8
+ Use this skill for spatial analysis, geometry operations, REST services, and feature reduction (clustering/binning).
9
+
10
+ ## Geometry Operators
11
+
12
+ ArcGIS Maps SDK provides geometry operators for client-side spatial operations.
13
+
14
+ ### Loading Operators
15
+
16
+ ```javascript
17
+ import bufferOperator from "@arcgis/core/geometry/operators/bufferOperator.js";
18
+ import intersectOperator from "@arcgis/core/geometry/operators/intersectOperator.js";
19
+ import centroidOperator from "@arcgis/core/geometry/operators/centroidOperator.js";
20
+
21
+ // Load before use (most operators require this)
22
+ await bufferOperator.load();
23
+ ```
24
+
25
+ ### Buffer
26
+ ```javascript
27
+ import bufferOperator from "@arcgis/core/geometry/operators/bufferOperator.js";
28
+ await bufferOperator.load();
29
+
30
+ const buffered = bufferOperator.execute(point, 1000); // 1000 meters
31
+ ```
32
+
33
+ ### Geodesic Buffer (accurate over large distances)
34
+ ```javascript
35
+ import geodesicBufferOperator from "@arcgis/core/geometry/operators/geodesicBufferOperator.js";
36
+ await geodesicBufferOperator.load();
37
+
38
+ const buffered = geodesicBufferOperator.execute(point, {
39
+ distances: [100],
40
+ unit: "kilometers"
41
+ });
42
+ ```
43
+
44
+ ### Intersect
45
+ ```javascript
46
+ import intersectOperator from "@arcgis/core/geometry/operators/intersectOperator.js";
47
+ await intersectOperator.load();
48
+
49
+ const intersection = intersectOperator.execute(geometry1, geometry2);
50
+ ```
51
+
52
+ ### Union
53
+ ```javascript
54
+ import unionOperator from "@arcgis/core/geometry/operators/unionOperator.js";
55
+ await unionOperator.load();
56
+
57
+ const unioned = unionOperator.execute([polygon1, polygon2, polygon3]);
58
+ ```
59
+
60
+ ### Centroid
61
+ ```javascript
62
+ import centroidOperator from "@arcgis/core/geometry/operators/centroidOperator.js";
63
+ await centroidOperator.load();
64
+
65
+ const centroid = centroidOperator.execute(polygon);
66
+ ```
67
+
68
+ ### Contains / Within
69
+ ```javascript
70
+ import containsOperator from "@arcgis/core/geometry/operators/containsOperator.js";
71
+ await containsOperator.load();
72
+
73
+ const isContained = containsOperator.execute(polygon, point); // true/false
74
+ ```
75
+
76
+ ### Distance
77
+ ```javascript
78
+ import geodeticLengthOperator from "@arcgis/core/geometry/operators/geodeticLengthOperator.js";
79
+ await geodeticLengthOperator.load();
80
+
81
+ const length = geodeticLengthOperator.execute(polyline, { unit: "miles" });
82
+ ```
83
+
84
+ ### Area
85
+ ```javascript
86
+ import geodeticAreaOperator from "@arcgis/core/geometry/operators/geodeticAreaOperator.js";
87
+ await geodeticAreaOperator.load();
88
+
89
+ const area = geodeticAreaOperator.execute(polygon, { unit: "square-kilometers" });
90
+ ```
91
+
92
+ ### Available Operators
93
+
94
+ | Operator | Purpose |
95
+ |----------|---------|
96
+ | `bufferOperator` | Create buffer around geometry |
97
+ | `geodesicBufferOperator` | Geodetic buffer (accurate) |
98
+ | `intersectOperator` | Find intersection |
99
+ | `unionOperator` | Combine geometries |
100
+ | `differenceOperator` | Subtract geometries |
101
+ | `clipOperator` | Clip geometry by envelope |
102
+ | `convexHullOperator` | Create convex hull |
103
+ | `centroidOperator` | Get centroid point |
104
+ | `containsOperator` | Test if contains |
105
+ | `withinOperator` | Test if within |
106
+ | `intersectsOperator` | Test if intersects |
107
+ | `distanceOperator` | Calculate planar distance |
108
+ | `geodeticLengthOperator` | Calculate geodetic length |
109
+ | `geodeticAreaOperator` | Calculate geodetic area |
110
+ | `simplifyOperator` | Simplify geometry |
111
+ | `densifyOperator` | Add vertices to geometry |
112
+ | `projectOperator` | Project to spatial reference |
113
+
114
+ ## Analysis Objects
115
+
116
+ ### ElevationProfileAnalysis
117
+ ```javascript
118
+ import ElevationProfileAnalysis from "@arcgis/core/analysis/ElevationProfileAnalysis.js";
119
+
120
+ const analysis = new ElevationProfileAnalysis({
121
+ profiles: [
122
+ { type: "ground", color: "brown" },
123
+ { type: "input", color: "blue" }
124
+ ],
125
+ displayUnits: {
126
+ distance: "meters",
127
+ elevation: "meters"
128
+ }
129
+ });
130
+
131
+ // Add to SceneView
132
+ view.analyses.add(analysis);
133
+
134
+ // Set line geometry
135
+ analysis.geometry = polyline;
136
+
137
+ // Get analysis view for results
138
+ const analysisView = await view.whenAnalysisView(analysis);
139
+
140
+ // Watch progress and results
141
+ reactiveUtils.watch(
142
+ () => analysisView.progress,
143
+ (progress) => {
144
+ if (progress === 1) {
145
+ console.log("Results:", analysisView.results);
146
+ }
147
+ }
148
+ );
149
+ ```
150
+
151
+ ### LineOfSightAnalysis
152
+ ```javascript
153
+ import LineOfSightAnalysis from "@arcgis/core/analysis/LineOfSightAnalysis.js";
154
+
155
+ const analysis = new LineOfSightAnalysis({
156
+ observer: {
157
+ type: "point",
158
+ x: -122.4,
159
+ y: 37.8,
160
+ z: 100,
161
+ spatialReference: { wkid: 4326 }
162
+ },
163
+ targets: [
164
+ { type: "point", x: -122.41, y: 37.81, z: 50 },
165
+ { type: "point", x: -122.42, y: 37.79, z: 75 }
166
+ ]
167
+ });
168
+
169
+ view.analyses.add(analysis);
170
+ ```
171
+
172
+ ### ViewshedAnalysis
173
+ ```javascript
174
+ import ViewshedAnalysis from "@arcgis/core/analysis/ViewshedAnalysis.js";
175
+
176
+ const analysis = new ViewshedAnalysis({
177
+ observer: {
178
+ type: "point",
179
+ x: -122.4,
180
+ y: 37.8,
181
+ z: 100,
182
+ spatialReference: { wkid: 4326 }
183
+ },
184
+ farDistance: 1000,
185
+ heading: 45,
186
+ tilt: 90,
187
+ horizontalFieldOfView: 120,
188
+ verticalFieldOfView: 90
189
+ });
190
+
191
+ view.analyses.add(analysis);
192
+ ```
193
+
194
+ ### ShadowCastAnalysis
195
+ ```javascript
196
+ import ShadowCastAnalysis from "@arcgis/core/analysis/ShadowCastAnalysis.js";
197
+
198
+ const analysis = new ShadowCastAnalysis();
199
+ view.analyses.add(analysis);
200
+
201
+ // Configure date/time for shadow calculation
202
+ view.environment.lighting.date = new Date("2024-06-21T12:00:00");
203
+ ```
204
+
205
+ ### SliceAnalysis
206
+ ```javascript
207
+ import SliceAnalysis from "@arcgis/core/analysis/SliceAnalysis.js";
208
+
209
+ const analysis = new SliceAnalysis({
210
+ plane: {
211
+ position: { type: "point", x: -122.4, y: 37.8, z: 50 },
212
+ heading: 0,
213
+ tilt: 0
214
+ }
215
+ });
216
+
217
+ view.analyses.add(analysis);
218
+ ```
219
+
220
+ ## REST Services
221
+
222
+ ### Routing
223
+
224
+ ```javascript
225
+ import route from "@arcgis/core/rest/route.js";
226
+
227
+ const routeParams = {
228
+ stops: [
229
+ { geometry: { x: -122.4, y: 37.8 } },
230
+ { geometry: { x: -122.5, y: 37.7 } }
231
+ ],
232
+ outSpatialReference: { wkid: 4326 },
233
+ returnDirections: true,
234
+ returnRoutes: true
235
+ };
236
+
237
+ const result = await route.solve(
238
+ "https://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World",
239
+ routeParams
240
+ );
241
+
242
+ const routeGeometry = result.routeResults[0].route.geometry;
243
+ const directions = result.routeResults[0].directions;
244
+ ```
245
+
246
+ ### Geocoding (Address to Location)
247
+
248
+ ```javascript
249
+ import locator from "@arcgis/core/rest/locator.js";
250
+
251
+ const results = await locator.addressToLocations(
252
+ "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer",
253
+ {
254
+ address: { SingleLine: "380 New York St, Redlands, CA" },
255
+ outFields: ["*"],
256
+ maxLocations: 5
257
+ }
258
+ );
259
+
260
+ results.forEach(result => {
261
+ console.log(result.address, result.location);
262
+ });
263
+ ```
264
+
265
+ ### Reverse Geocoding (Location to Address)
266
+
267
+ ```javascript
268
+ import locator from "@arcgis/core/rest/locator.js";
269
+
270
+ const result = await locator.locationToAddress(
271
+ "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer",
272
+ {
273
+ location: { x: -117.195, y: 34.057 }
274
+ }
275
+ );
276
+
277
+ console.log(result.address);
278
+ ```
279
+
280
+ ### Geoprocessing
281
+
282
+ ```javascript
283
+ import geoprocessor from "@arcgis/core/rest/geoprocessor.js";
284
+
285
+ const params = {
286
+ inputLayer: featureSet,
287
+ distance: 1000,
288
+ distanceUnits: "Meters"
289
+ };
290
+
291
+ const result = await geoprocessor.execute(
292
+ "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Buffer/GPServer/Buffer",
293
+ params
294
+ );
295
+
296
+ const outputFeatures = result.results[0].value;
297
+ ```
298
+
299
+ ### Print
300
+
301
+ ```javascript
302
+ import print from "@arcgis/core/rest/print.js";
303
+
304
+ const params = {
305
+ view: view,
306
+ template: {
307
+ format: "pdf",
308
+ layout: "letter-ansi-a-landscape",
309
+ layoutOptions: {
310
+ titleText: "My Map"
311
+ }
312
+ }
313
+ };
314
+
315
+ const result = await print.execute(
316
+ "https://utility.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task",
317
+ params
318
+ );
319
+
320
+ // Download the PDF
321
+ window.open(result.url);
322
+ ```
323
+
324
+ ### Places Service
325
+
326
+ ```javascript
327
+ import places from "@arcgis/core/rest/places.js";
328
+ import PlacesQueryParameters from "@arcgis/core/rest/support/PlacesQueryParameters.js";
329
+ import FetchPlaceParameters from "@arcgis/core/rest/support/FetchPlaceParameters.js";
330
+
331
+ // Query places near a point
332
+ const queryParams = new PlacesQueryParameters({
333
+ categoryIds: ["4d4b7104d754a06370d81259"], // Arts and Entertainment
334
+ radius: 500, // meters
335
+ point: { type: "point", longitude: -87.626, latitude: 41.882 },
336
+ icon: "png"
337
+ });
338
+
339
+ const results = await places.queryPlacesNearPoint(queryParams);
340
+
341
+ // Process results
342
+ results.results.forEach(place => {
343
+ console.log(place.name, place.location, place.categories[0].label);
344
+ console.log("Distance:", place.distance / 1000, "km");
345
+ });
346
+
347
+ // Fetch detailed information about a place
348
+ const fetchParams = new FetchPlaceParameters({
349
+ placeId: results.results[0].placeId,
350
+ requestedFields: ["all"]
351
+ });
352
+
353
+ const details = await places.fetchPlace(fetchParams);
354
+ const placeDetails = details.placeDetails;
355
+
356
+ console.log("Address:", placeDetails.address.streetAddress);
357
+ console.log("Phone:", placeDetails.contactInfo.telephone);
358
+ console.log("Website:", placeDetails.contactInfo.website);
359
+ ```
360
+
361
+ ### Places Category IDs
362
+
363
+ | Category | ID |
364
+ |----------|-----|
365
+ | Arts and Entertainment | `4d4b7104d754a06370d81259` |
366
+ | Business Services | `4d4b7105d754a06375d81259` |
367
+ | Community and Government | `63be6904847c3692a84b9b9a` |
368
+ | Dining and Drinking | `63be6904847c3692a84b9bb5` |
369
+ | Health and Medicine | `63be6904847c3692a84b9bb9` |
370
+ | Landmarks and Outdoors | `4d4b7105d754a06377d81259` |
371
+ | Retail | `4d4b7105d754a06378d81259` |
372
+ | Sports and Recreation | `4f4528bc4b90abdf24c9de85` |
373
+ | Travel and Transportation | `4d4b7105d754a06379d81259` |
374
+
375
+ ## Feature Queries with Statistics
376
+
377
+ ### Basic Statistics
378
+ ```javascript
379
+ const query = featureLayer.createQuery();
380
+ query.outStatistics = [
381
+ {
382
+ statisticType: "sum",
383
+ onStatisticField: "population",
384
+ outStatisticFieldName: "totalPop"
385
+ },
386
+ {
387
+ statisticType: "avg",
388
+ onStatisticField: "population",
389
+ outStatisticFieldName: "avgPop"
390
+ },
391
+ {
392
+ statisticType: "max",
393
+ onStatisticField: "population",
394
+ outStatisticFieldName: "maxPop"
395
+ },
396
+ {
397
+ statisticType: "min",
398
+ onStatisticField: "population",
399
+ outStatisticFieldName: "minPop"
400
+ },
401
+ {
402
+ statisticType: "count",
403
+ onStatisticField: "population",
404
+ outStatisticFieldName: "count"
405
+ },
406
+ {
407
+ statisticType: "stddev",
408
+ onStatisticField: "population",
409
+ outStatisticFieldName: "stdDev"
410
+ }
411
+ ];
412
+
413
+ const result = await featureLayer.queryFeatures(query);
414
+ console.log(result.features[0].attributes);
415
+ ```
416
+
417
+ ### Group By Statistics
418
+ ```javascript
419
+ const query = featureLayer.createQuery();
420
+ query.groupByFieldsForStatistics = ["state"];
421
+ query.outStatistics = [{
422
+ statisticType: "sum",
423
+ onStatisticField: "population",
424
+ outStatisticFieldName: "totalPop"
425
+ }];
426
+ query.orderByFields = ["totalPop DESC"];
427
+
428
+ const result = await featureLayer.queryFeatures(query);
429
+ // Returns one feature per state with total population
430
+ ```
431
+
432
+ ### Spatial Statistics Query
433
+ ```javascript
434
+ const query = featureLayer.createQuery();
435
+ query.geometry = view.extent;
436
+ query.spatialRelationship = "intersects";
437
+ query.outStatistics = [{
438
+ statisticType: "count",
439
+ onStatisticField: "ObjectID",
440
+ outStatisticFieldName: "featureCount"
441
+ }];
442
+
443
+ const result = await featureLayer.queryFeatures(query);
444
+ console.log("Features in view:", result.features[0].attributes.featureCount);
445
+ ```
446
+
447
+ ## Feature Reduction
448
+
449
+ ### Clustering
450
+
451
+ ```javascript
452
+ const clusterConfig = {
453
+ type: "cluster",
454
+ clusterRadius: "100px",
455
+ clusterMinSize: "24px",
456
+ clusterMaxSize: "60px",
457
+ popupTemplate: {
458
+ title: "Cluster summary",
459
+ content: "This cluster represents {cluster_count} features.",
460
+ fieldInfos: [{
461
+ fieldName: "cluster_count",
462
+ format: { digitSeparator: true, places: 0 }
463
+ }]
464
+ },
465
+ labelingInfo: [{
466
+ deconflictionStrategy: "none",
467
+ labelExpressionInfo: {
468
+ expression: "Text($feature.cluster_count, '#,###')"
469
+ },
470
+ symbol: {
471
+ type: "text",
472
+ color: "white",
473
+ font: { size: "12px", weight: "bold" }
474
+ },
475
+ labelPlacement: "center-center"
476
+ }]
477
+ };
478
+
479
+ featureLayer.featureReduction = clusterConfig;
480
+
481
+ // Toggle clustering
482
+ featureLayer.featureReduction = null; // Disable
483
+ featureLayer.featureReduction = clusterConfig; // Enable
484
+ ```
485
+
486
+ ### Cluster with Aggregated Fields
487
+ ```javascript
488
+ const clusterConfig = {
489
+ type: "cluster",
490
+ clusterRadius: "100px",
491
+ fields: [{
492
+ name: "avg_magnitude",
493
+ statisticType: "avg",
494
+ onStatisticField: "magnitude"
495
+ }, {
496
+ name: "total_count",
497
+ statisticType: "count",
498
+ onStatisticField: "ObjectID"
499
+ }],
500
+ renderer: {
501
+ type: "simple",
502
+ symbol: {
503
+ type: "simple-marker",
504
+ style: "circle",
505
+ color: "#69dcff"
506
+ },
507
+ visualVariables: [{
508
+ type: "size",
509
+ field: "total_count",
510
+ stops: [
511
+ { value: 1, size: 8 },
512
+ { value: 100, size: 40 }
513
+ ]
514
+ }]
515
+ }
516
+ };
517
+ ```
518
+
519
+ ### Binning
520
+ ```javascript
521
+ const binConfig = {
522
+ type: "binning",
523
+ fixedBinLevel: 4, // Level of detail
524
+ renderer: {
525
+ type: "simple",
526
+ symbol: {
527
+ type: "simple-fill",
528
+ outline: { color: "white", width: 0.5 }
529
+ },
530
+ visualVariables: [{
531
+ type: "color",
532
+ field: "aggregateCount",
533
+ stops: [
534
+ { value: 1, color: "#feebe2" },
535
+ { value: 50, color: "#fbb4b9" },
536
+ { value: 100, color: "#f768a1" },
537
+ { value: 500, color: "#c51b8a" },
538
+ { value: 1000, color: "#7a0177" }
539
+ ]
540
+ }]
541
+ },
542
+ popupTemplate: {
543
+ title: "Bin",
544
+ content: "{aggregateCount} features in this bin"
545
+ }
546
+ };
547
+
548
+ featureLayer.featureReduction = binConfig;
549
+ ```
550
+
551
+ ## Projection
552
+
553
+ ```javascript
554
+ import projectOperator from "@arcgis/core/geometry/operators/projectOperator.js";
555
+ await projectOperator.load();
556
+
557
+ // Project to Web Mercator
558
+ const projected = projectOperator.execute(geometry, { wkid: 3857 });
559
+
560
+ // Project to WGS 84
561
+ const wgs84 = projectOperator.execute(geometry, { wkid: 4326 });
562
+ ```
563
+
564
+ ## TypeScript Usage
565
+
566
+ Feature reduction configurations use autocasting with `type` properties. For TypeScript safety, use `as const`:
567
+
568
+ ```typescript
569
+ // Use 'as const' for type safety
570
+ const clusterConfig = {
571
+ type: "cluster",
572
+ clusterRadius: "100px",
573
+ renderer: {
574
+ type: "simple",
575
+ symbol: {
576
+ type: "simple-marker",
577
+ color: "#69dcff"
578
+ }
579
+ } as const,
580
+ labelingInfo: [{
581
+ labelExpressionInfo: {
582
+ expression: "Text($feature.cluster_count, '#,###')"
583
+ },
584
+ symbol: {
585
+ type: "text",
586
+ color: "white"
587
+ } as const
588
+ }]
589
+ } as const;
590
+
591
+ featureLayer.featureReduction = clusterConfig;
592
+ ```
593
+
594
+ > **Tip:** See [arcgis-core-maps skill](../arcgis-core-maps/SKILL.md) for detailed guidance on autocasting vs explicit classes.
595
+
596
+ ## Common Pitfalls
597
+
598
+ 1. **Operator not loaded**: Most operators require `await operator.load()` before use
599
+
600
+ 2. **API key required**: Some REST services (routing, geocoding) require an API key
601
+
602
+ 3. **Analysis only in SceneView**: Some analyses (viewshed, line of sight) only work in 3D
603
+
604
+ 4. **Cluster fields**: Use `cluster_count` to access feature count in clusters
605
+
606
+ 5. **Statistics query returns features**: Statistics queries return features with calculated attributes, not raw numbers
607
+