arcgis-spatial-analysis について
ArcGIS 開発者向けに、3D 空間分析、フィーチャ統計、フィーチャの簡略化を扱うスキルです。分析オブジェクトの設定、クエリ、クラスタリング、ビニングと API の注意点を説明します。
主な機能
- 013D 分析オブジェクトの設定
- 02統計付きフィーチャクエリの実行
- 03フィーチャのクラスタリングとフィールド集計
- 04フィーチャビニングの設定
- 05API の注意点と正しいプロパティの説明
活用シーン
- 01可視領域や標高プロファイルの分析
- 023D の面積、距離、体積の測定
- 03グループ別または空間範囲別のフィーチャ集計
- 04クラスタリングやビニングによる密集フィーチャの簡略化
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ saschabrunnerch/ arcgis-maps-sdk-js-ai-context --skill arcgis-spatial-analysisインストール後、Claude Code で/arcgis-spatial-analysisを入力して読み込まれたか確認します。
詳細
ArcGIS 空間解析
空間解析オブジェクト(3D 解析)、統計情報を含むフィーチャクエリ、フィーチャのリダクション(クラスタリング/ビニング)にこのスキルを使用します。
ジオメトリ演算子(バッファー、ユニオン、インターセクト、クリップ、オフセットなど)については、
arcgis-geometry-operationsを参照してください。 ルーティング、ジオコーディング、ジオプロセシング REST サービスについては、arcgis-rest-servicesを参照してください。
インポートパターン
ESM の直接インポート
import ViewshedAnalysis from "@arcgis/core/analysis/ViewshedAnalysis.js";
import Viewshed from "@arcgis/core/analysis/Viewshed.js";
import LineOfSightAnalysis from "@arcgis/core/analysis/LineOfSightAnalysis.js";
import ElevationProfileAnalysis from "@arcgis/core/analysis/ElevationProfileAnalysis.js";
import SliceAnalysis from "@arcgis/core/analysis/SliceAnalysis.js";
import ShadowCastAnalysis from "@arcgis/core/analysis/ShadowCastAnalysis.js";
動的インポート(CDN)
const [ViewshedAnalysis, Viewshed] = await $arcgis.import([
"@arcgis/core/analysis/ViewshedAnalysis.js",
"@arcgis/core/analysis/Viewshed.js",
]);
解析オブジェクト(3D)
解析オブジェクトは SceneView の analyses コレクションに追加します。すべての解析タイプで MapView ではなく SceneView が必要です。
ElevationProfileAnalysis
import ElevationProfileAnalysis from "@arcgis/core/analysis/ElevationProfileAnalysis.js";
import * as reactiveUtils from "@arcgis/core/core/reactiveUtils.js";
const analysis = new ElevationProfileAnalysis({
profiles: [
{ type: "ground", color: "brown" },
{ type: "input", color: "blue" },
],
displayUnits: {
distance: "meters",
elevation: "meters",
},
});
view.analyses.add(analysis);
analysis.geometry = polyline;
// Get analysis view for results
const analysisView = await view.whenAnalysisView(analysis);
reactiveUtils.watch(
() => analysisView.progress,
(progress) => {
if (progress === 1) {
console.log("Results:", analysisView.results);
}
},
);
解析のインタラクティブな配置
解析ビューでは、place() メソッドを使ってインタラクティブに配置できます。
import * as promiseUtils from "@arcgis/core/core/promiseUtils.js";
const analysisView = await view.whenAnalysisView(analysis);
const abortController = new AbortController();
try {
await analysisView.place({ signal: abortController.signal });
} catch (error) {
if (!promiseUtils.isAbortError(error)) throw error;
}
// To cancel placement
abortController.abort();
ViewshedAnalysis
Viewshed オブジェクトの viewsheds コレクションを使用します(observer プロパティを直接指定するのではありません)。
import ViewshedAnalysis from "@arcgis/core/analysis/ViewshedAnalysis.js";
import Viewshed from "@arcgis/core/analysis/Viewshed.js";
const viewshed = new Viewshed({
observer: {
type: "point",
x: -122.4,
y: 37.8,
z: 100,
spatialReference: { wkid: 4326 },
},
farDistance: 1000,
heading: 45,
tilt: 90,
horizontalFieldOfView: 120,
verticalFieldOfView: 90,
});
const analysis = new ViewshedAnalysis({
viewsheds: [viewshed],
});
view.analyses.add(analysis);
// Add more viewsheds dynamically
analysis.viewsheds.add(
new Viewshed({
observer: {
type: "point",
x: -122.41,
y: 37.79,
z: 80,
spatialReference: { wkid: 4326 },
},
farDistance: 500,
heading: 0,
tilt: 90,
horizontalFieldOfView: 360,
verticalFieldOfView: 90,
}),
);
// Clear all viewsheds
analysis.clear();
LineOfSightAnalysis
LineOfSightAnalysisObserver と LineOfSightAnalysisTarget のラッパーオブジェクトを使用します。
import LineOfSightAnalysis from "@arcgis/core/analysis/LineOfSightAnalysis.js";
import LineOfSightAnalysisObserver from "@arcgis/core/analysis/LineOfSightAnalysisObserver.js";
import LineOfSightAnalysisTarget from "@arcgis/core/analysis/LineOfSightAnalysisTarget.js";
const analysis = new LineOfSightAnalysis({
observer: new LineOfSightAnalysisObserver({
position: {
type: "point",
x: -122.4,
y: 37.8,
z: 100,
spatialReference: { wkid: 4326 },
},
}),
targets: [
new LineOfSightAnalysisTarget({
position: {
type: "point",
x: -122.41,
y: 37.81,
z: 50,
spatialReference: { wkid: 4326 },
},
}),
new LineOfSightAnalysisTarget({
position: {
type: "point",
x: -122.42,
y: 37.79,
z: 75,
spatialReference: { wkid: 4326 },
},
}),
],
});
view.analyses.add(analysis);
ShadowCastAnalysis
date、startTimeOfDay、endTimeOfDay、mode の各プロパティを使用します。
import ShadowCastAnalysis from "@arcgis/core/analysis/ShadowCastAnalysis.js";
const analysis = new ShadowCastAnalysis({
date: new Date("2025-06-21"),
startTimeOfDay: 21600000, // 6:00 AM (milliseconds from midnight)
endTimeOfDay: 57600000, // 4:00 PM
mode: "total-duration", // "total-duration", "discrete", "min-duration"
utcOffset: -7, // UTC offset in hours
});
view.analyses.add(analysis);
SliceAnalysis
plane ではなく、SlicePlane 型の shape プロパティを使用します。
import SliceAnalysis from "@arcgis/core/analysis/SliceAnalysis.js";
import SlicePlane from "@arcgis/core/analysis/SlicePlane.js";
const analysis = new SliceAnalysis({
shape: new SlicePlane({
position: {
type: "point",
x: -122.4,
y: 37.8,
z: 50,
spatialReference: { wkid: 4326 },
},
heading: 0,
tilt: 0,
width: 200,
height: 200,
}),
tiltEnabled: false,
excludeGroundSurface: false,
});
view.analyses.add(analysis);
AreaMeasurementAnalysis
import AreaMeasurementAnalysis from "@arcgis/core/analysis/AreaMeasurementAnalysis.js";
const analysis = new AreaMeasurementAnalysis();
view.analyses.add(analysis);
// Set geometry after user draws or programmatically
analysis.geometry = polygon;
// Watch for results
const analysisView = await view.whenAnalysisView(analysis);
reactiveUtils.watch(
() => analysisView.result,
(result) => {
if (result) {
console.log("Area:", result.area?.value, result.area?.unit);
console.log(
"Perimeter:",
result.perimeterLength?.value,
result.perimeterLength?.unit,
);
}
},
{ initial: true },
);
DistanceMeasurementAnalysis
startPoint/endPoint ではなく、geometry プロパティ(Polyline)を使用します。
import DistanceMeasurementAnalysis from "@arcgis/core/analysis/DistanceMeasurementAnalysis.js";
const analysis = new DistanceMeasurementAnalysis({
geometry: {
type: "polyline",
paths: [
[
[-122.4, 37.8, 0],
[-122.41, 37.81, 0],
],
],
spatialReference: { wkid: 4326 },
},
});
view.analyses.add(analysis);
VolumeMeasurementAnalysis
import VolumeMeasurementAnalysis from "@arcgis/core/analysis/VolumeMeasurementAnalysis.js";
const analysis = new VolumeMeasurementAnalysis();
view.analyses.add(analysis);
analysis.geometry = polygon;
// Watch for results
const analysisView = await view.whenAnalysisView(analysis);
reactiveUtils.watch(
() => analysisView.result,
(result) => {
if (result) {
console.log(
"Cut volume:",
result.cutVolume?.value,
result.cutVolume?.unit,
);
console.log(
"Fill volume:",
result.fillVolume?.value,
result.fillVolume?.unit,
);
}
},
{ initial: true },
);
DimensionAnalysis
import DimensionAnalysis from "@arcgis/core/analysis/DimensionAnalysis.js";
import LengthDimension from "@arcgis/core/analysis/LengthDimension.js";
const dimension = new LengthDimension({
startPoint: {
type: "point",
x: -122.4,
y: 37.8,
z: 0,
spatialReference: { wkid: 4326 },
},
endPoint: {
type: "point",
x: -122.41,
y: 37.81,
z: 0,
spatialReference: { wkid: 4326 },
},
});
const analysis = new DimensionAnalysis({
dimensions: [dimension],
});
view.analyses.add(analysis);
解析タイプの概要
| 解析 | 用途 | コンストラクターキー |
|---|---|---|
| ViewshedAnalysis | 観測者から見える範囲 | viewsheds(Viewshed の Collection) |
| LineOfSightAnalysis | 2 点間の可視性 | observer、targets(ラッパーオブジェクト) |
| ShadowCastAnalysis | 影の可視化 | date、startTimeOfDay、endTimeOfDay、mode |
| SliceAnalysis | 3D コンテンツの断面 | shape(SlicePlane) |
| ElevationProfileAnalysis | 線に沿った地形プロファイル | profiles、geometry(Polyline) |
| AreaMeasurementAnalysis | 3D 面積の計測 | geometry(Polygon) |
| DistanceMeasurementAnalysis | 3D 距離の計測 | geometry(Polyline) |
| VolumeMeasurementAnalysis | 切土/盛土の体積 | geometry(Polygon) |
| DimensionAnalysis | 3D の長さ寸法 | dimensions(LengthDimension[]) |
統計情報を含むフィーチャクエリ
基本統計
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);
グループ化統計
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
空間統計
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);
フィーチャのリダクション
クラスタリング
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
集計フィールドを含むクラスタ
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 },
],
},
],
},
};
ビニング
const binConfig = {
type: "binning",
fixedBinLevel: 4,
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;
よくある落とし穴
-
解析オブジェクトは SceneView 専用です:すべての解析タイプ(ビューシェッド、見通し線、シャドウキャストなど)には、3D SceneView が必要です。MapView では動作しません。
-
ViewshedAnalysis は viewsheds コレクションを使用します:ViewshedAnalysis に
observerを直接設定しないでください。Viewshedオブジェクトを作成し、viewshedsコレクションに追加します。// Anti-pattern new ViewshedAnalysis({ observer: point, farDistance: 1000 }); // Correct new ViewshedAnalysis({ viewsheds: [new Viewshed({ observer: point, farDistance: 1000 })], }); -
クラスターフィールド名:クラスターのポップアップとラベルでフィーチャ数を取得するには、
clusterCountではなくcluster_countを使用します。 -
統計クエリはフィーチャを返します:統計クエリは計算済み属性を含むフィーチャを返し、生の数値は返しません。
result.features[0].attributesで結果にアクセスします。 -
解析の進行状況:解析結果の準備完了を確認するには、
analysisView.progress === 1を確認するか、analysisView.resultを監視します。計算前に結果を読み取らないでください。 -
SliceAnalysis では
planeではなくshapeを使用します:このプロパティはplaneではなく、SlicePlane型のshapeです。// Anti-pattern new SliceAnalysis({ plane: slicePlane }); // Correct new SliceAnalysis({ shape: slicePlane });
参照サンプル
analysis-viewshed- 3D での対話型可視領域解析analysis-objects- 1 つのシーンで複数の解析タイプを使用analysis-elevation-profile- ラインに沿った標高プロファイルanalysis-shadow-cast- 影の継続時間の可視化analysis-area-measurement- 3D サーフェス上の面積計測analysis-volume-measurement- 切土・盛土量の計測line-of-sight- 視線の可視性解析featurereduction-cluster- フィーチャのクラスタリングfeaturereduction-binning- 集計用のフィーチャのビニングfeaturereduction-cluster-aggregate-fields- 集計統計を含むクラスター
関連スキル
- クライアント側のジオメトリー操作(バッファー、ユニオン、インターセクトなど)については、
arcgis-geometry-operationsを参照してください。 - サーバー側の REST サービス(ルーティング、ジオコーディング、ジオプロセシング)については、
arcgis-rest-servicesを参照してください。 - 座標投影とフォーマットについては、
arcgis-coordinates-projectionを参照してください。 - FeatureLayer のクエリとレイヤー設定については、
arcgis-layersを参照してください。