mcpField
A
arcgis-spatial-analysis

arcgis-spatial-analysis

github.com/saschabrunnerch数据与数据库2357 次安装29 周前更新
代码仓库

关于 arcgis-spatial-analysis

面向 ArcGIS 开发者的空间分析技能,涵盖 3D 分析、要素统计查询与要素简化,并说明对象配置及常见 API 陷阱。

主要功能

  1. 01配置 3D 分析对象
  2. 02执行带统计的要素查询
  3. 03聚类要素并汇总字段
  4. 04配置要素分箱
  5. 05说明 API 陷阱及正确属性

适用场景

  1. 01构建可视域或高程分析
  2. 02测量 3D 面积、距离或体积
  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 集合中。所有分析类型都需要 SceneView(而不是 MapView)。

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 集合(而不是直接设置观察者属性)。

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

使用 SlicePlane 类型的 shape 属性(而不是 plane)。

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

使用 geometry 属性(Polyline),而不是 startPoint/endPoint。

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 集合)
LineOfSightAnalysis点之间的可见性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. 聚类字段名称:在聚类弹出窗口和标注中,使用 cluster_count(而不是 clusterCount)获取要素数量。

  4. 统计查询返回要素:统计查询返回带有计算所得属性的要素,而不是原始数值。通过 result.features[0].attributes 访问结果。

  5. 分析进度:检查 analysisView.progress === 1 或监视 analysisView.result,以确定分析结果何时就绪。请勿在结果计算完成前读取结果。

  6. SliceAnalysis 使用 shape,而不是 plane:该属性是 SlicePlane 类型的 shape,而不是 plane:

    // Anti-pattern
    new SliceAnalysis({ plane: slicePlane });
    
    // Correct
    new SliceAnalysis({ shape: slicePlane });
    

参考示例

  • analysis-viewshed - 3D 交互式视域分析
  • analysis-objects - 在单个场景中使用多种分析类型
  • 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。

评论

支持 Markdown