mcpField
A
arcgis-spatial-analysis

arcgis-spatial-analysis

github.com/saschabrunnerchデータ・データベース2357 回インストール29 週間前に更新
リポジトリ

arcgis-spatial-analysis について

ArcGIS 開発者向けに、3D 空間分析、フィーチャ統計、フィーチャの簡略化を扱うスキルです。分析オブジェクトの設定、クエリ、クラスタリング、ビニングと API の注意点を説明します。

主な機能

  1. 013D 分析オブジェクトの設定
  2. 02統計付きフィーチャクエリの実行
  3. 03フィーチャのクラスタリングとフィールド集計
  4. 04フィーチャビニングの設定
  5. 05API の注意点と正しいプロパティの説明

活用シーン

  1. 01可視領域や標高プロファイルの分析
  2. 023D の面積、距離、体積の測定
  3. 03グループ別または空間範囲別のフィーチャ集計
  4. 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)
LineOfSightAnalysis2 点間の可視性observer、targets(ラッパーオブジェクト)
ShadowCastAnalysis影の可視化date、startTimeOfDay、endTimeOfDay、mode
SliceAnalysis3D コンテンツの断面shape(SlicePlane)
ElevationProfileAnalysis線に沿った地形プロファイルprofiles、geometry(Polyline)
AreaMeasurementAnalysis3D 面積の計測geometry(Polygon)
DistanceMeasurementAnalysis3D 距離の計測geometry(Polyline)
VolumeMeasurementAnalysis切土/盛土の体積geometry(Polygon)
DimensionAnalysis3D の長さ寸法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;

よくある落とし穴

  1. 解析オブジェクトは SceneView 専用です:すべての解析タイプ(ビューシェッド、見通し線、シャドウキャストなど)には、3D SceneView が必要です。MapView では動作しません。

  2. ViewshedAnalysis は viewsheds コレクションを使用します:ViewshedAnalysis に observer を直接設定しないでください。Viewshed オブジェクトを作成し、viewsheds コレクションに追加します。

    // Anti-pattern
    new ViewshedAnalysis({ observer: point, farDistance: 1000 });
    
    // Correct
    new ViewshedAnalysis({
      viewsheds: [new Viewshed({ observer: point, farDistance: 1000 })],
    });
    
  3. クラスターフィールド名:クラスターのポップアップとラベルでフィーチャ数を取得するには、clusterCount ではなく cluster_count を使用します。

  4. 統計クエリはフィーチャを返します:統計クエリは計算済み属性を含むフィーチャを返し、生の数値は返しません。result.features[0].attributes で結果にアクセスします。

  5. 解析の進行状況:解析結果の準備完了を確認するには、analysisView.progress === 1 を確認するか、analysisView.result を監視します。計算前に結果を読み取らないでください。

  6. 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 を参照してください。

コメント