mcpField
A
arcgis-rest-services

arcgis-rest-services

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

关于 arcgis-rest-services

arcgis-rest-services 是面向开发者的技能,介绍如何通过 @arcgis/core/rest 模块调用 ArcGIS Server REST 端点。内容覆盖空间查询,以及路径规划、地理编码、地点搜索、地理处理和地图打印等服务。

主要功能

  1. 01直接与动态 ESM 导入
  2. 02路径规划和服务区分析
  3. 03地理编码与地点搜索
  4. 04要素查询与识别
  5. 05地理处理和几何操作
  6. 06服务端地图导出

适用场景

  1. 01查找多个停靠点之间的路线
  2. 02对地址进行地理编码或搜索附近地点
  3. 03查询要素并识别地图位置
  4. 04运行地理处理任务或导出地图

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/saschabrunnerch/arcgis-maps-sdk-js-ai-context --skill arcgis-rest-services

安装后在 Claude Code 中输入/arcgis-rest-services确认已加载。

详细介绍

ArcGIS REST 服务

通过 @arcgis/core/rest/* 命名空间调用 ArcGIS Server REST 端点时使用此技能。涵盖路径规划、地理编码、空间查询、地理处理、打印、地点搜索及其他服务器端操作。

导入模式

直接 ESM 导入
import * as route from "@arcgis/core/rest/route.js";
import * as locator from "@arcgis/core/rest/locator.js";
import * as query from "@arcgis/core/rest/query.js";
import RouteParameters from "@arcgis/core/rest/support/RouteParameters.js";
import FeatureSet from "@arcgis/core/rest/support/FeatureSet.js";
import Query from "@arcgis/core/rest/support/Query.js";
动态导入(CDN)
const route = await $arcgis.import("@arcgis/core/rest/route.js");
const locator = await $arcgis.import("@arcgis/core/rest/locator.js");
const [query, Query] = await $arcgis.import([
  "@arcgis/core/rest/query.js",
  "@arcgis/core/rest/support/Query.js",
]);

所有 REST 服务函数都将服务 URL 作为第一个参数,并将参数对象作为第二个参数:

const result = await serviceName.methodName(serviceUrl, params);

路径规划

规划途经多个停靠点的路径,并可选择设置障碍物和路线指引。

import * as route from "@arcgis/core/rest/route.js";
import RouteParameters from "@arcgis/core/rest/support/RouteParameters.js";
import FeatureSet from "@arcgis/core/rest/support/FeatureSet.js";
import Graphic from "@arcgis/core/Graphic.js";

const stops = new FeatureSet({
  features: [
    new Graphic({
      geometry: { type: "point", longitude: -117.195, latitude: 34.057 },
      attributes: { Name: "Start" },
    }),
    new Graphic({
      geometry: { type: "point", longitude: -117.918, latitude: 33.812 },
      attributes: { Name: "End" },
    }),
  ],
});

const routeParams = new RouteParameters({
  stops,
  outSpatialReference: { wkid: 4326 },
  returnDirections: true,
  returnRoutes: true,
  directionsLanguage: "en",
});

const routeUrl =
  "https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World";
const result = await route.solve(routeUrl, routeParams);

const routeResult = result.routeResults[0];
const routeGeometry = routeResult.route.geometry;

// Display directions
routeResult.directions.features.forEach((feature) => {
  console.log(
    feature.attributes.text,
    feature.attributes.length.toFixed(2),
    "miles",
  );
});
带障碍物的路径规划
const pointBarriers = new FeatureSet({
  features: [
    new Graphic({
      geometry: { type: "point", longitude: -117.5, latitude: 33.9 },
    }),
  ],
});

const routeParams = new RouteParameters({
  stops,
  pointBarriers,
  outSpatialReference: { wkid: 4326 },
  returnDirections: true,
});

const result = await route.solve(routeUrl, routeParams);

最近设施

查找距离一组事件点最近的设施。

import * as closestFacility from "@arcgis/core/rest/closestFacility.js";
import ClosestFacilityParameters from "@arcgis/core/rest/support/ClosestFacilityParameters.js";
import FeatureSet from "@arcgis/core/rest/support/FeatureSet.js";

const facilities = new FeatureSet({
  features: [
    new Graphic({
      geometry: { type: "point", longitude: -117.2, latitude: 34.06 },
    }),
    new Graphic({
      geometry: { type: "point", longitude: -117.3, latitude: 34.1 },
    }),
  ],
});

const incidents = new FeatureSet({
  features: [
    new Graphic({
      geometry: { type: "point", longitude: -117.19, latitude: 34.05 },
    }),
  ],
});

const params = new ClosestFacilityParameters({
  facilities,
  incidents,
  defaultTargetFacilityCount: 1,
  returnRoutes: true,
  returnDirections: true,
  outSpatialReference: { wkid: 4326 },
});

const cfUrl =
  "https://route-api.arcgis.com/arcgis/rest/services/World/ClosestFacility/NAServer/ClosestFacility_World";
const result = await closestFacility.solve(cfUrl, params);

const closestRoute = result.routes[0];
console.log("Distance:", closestRoute.attributes.Total_Kilometers, "km");

服务区

根据行驶时间或距离,生成设施周围的服务区多边形。

import * as serviceArea from "@arcgis/core/rest/serviceArea.js";
import ServiceAreaParameters from "@arcgis/core/rest/support/ServiceAreaParameters.js";

const params = new ServiceAreaParameters({
  facilities: facilitiesFeatureSet,
  defaultBreaks: [5, 10, 15], // minutes
  trimOuterPolygon: true,
  outSpatialReference: { wkid: 4326 },
});

const saUrl =
  "https://route-api.arcgis.com/arcgis/rest/services/World/ServiceAreas/NAServer/ServiceArea_World";
const result = await serviceArea.solve(saUrl, params);

result.serviceAreaPolygons.forEach((polygon) => {
  console.log(
    "Break:",
    polygon.attributes.FromBreak,
    "-",
    polygon.attributes.ToBreak,
    "min",
  );
});

定位器(地理编码)

地址转位置
import * as locator from "@arcgis/core/rest/locator.js";

const geocodeUrl =
  "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer";

const results = await locator.addressToLocations(geocodeUrl, {
  address: { SingleLine: "380 New York St, Redlands, CA" },
  outFields: ["Addr_type", "Match_addr", "StAddr", "City"],
  maxLocations: 5,
});

results.forEach((result) => {
  console.log(result.address); // Matched address
  console.log(result.location); // Point geometry
  console.log(result.score); // Match score (0-100)
});
位置转地址(反向地理编码)
const result = await locator.locationToAddress(geocodeUrl, {
  location: { type: "point", longitude: -117.195, latitude: 34.057 },
});

console.log(result.address);
console.log(result.attributes);
位置建议(自动补全)
const suggestions = await locator.suggestLocations(geocodeUrl, {
  text: "380 New York",
  location: { type: "point", longitude: -117.195, latitude: 34.057 },
});

suggestions.forEach((suggestion) => {
  console.log(suggestion.text);
  console.log(suggestion.magicKey);
});

// Use magicKey to get the full result
const results = await locator.addressToLocations(geocodeUrl, {
  address: { SingleLine: suggestions[0].text },
  magicKey: suggestions[0].magicKey,
  outFields: ["*"],
});

查询(REST)

无需使用 FeatureLayer,直接查询要素服务端点中的要素。

import * as query from "@arcgis/core/rest/query.js";
import Query from "@arcgis/core/rest/support/Query.js";

const featureServiceUrl =
  "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0";

const queryParams = new Query({
  where: "Height > 50",
  outFields: ["*"],
  returnGeometry: true,
  outSpatialReference: { wkid: 4326 },
});

// JSON result
const result = await query.executeQueryJSON(featureServiceUrl, queryParams);
console.log("Features found:", result.features.length);

// Count only
const count = await query.executeForCount(featureServiceUrl, queryParams);

// Extent only
const extentResult = await query.executeForExtent(
  featureServiceUrl,
  queryParams,
);

// Object IDs only
const ids = await query.executeForIds(featureServiceUrl, queryParams);
查询方法
方法返回值使用场景
executeQueryJSON(url, query)FeatureSet完整要素数据
executeQueryPBF(url, query)FeatureSet载荷更小(PBF 格式)
executeForCount(url, query)number仅要素计数
executeForExtent(url, query){ count, extent }边界框 + 计数
executeForIds(url, query)number[]仅对象 ID

查找

根据属性值查找地图服务中的要素。

import * as find from "@arcgis/core/rest/find.js";
import FindParameters from "@arcgis/core/rest/support/FindParameters.js";

const params = new FindParameters({
  searchText: "Los Angeles",
  layerIds: [0, 1, 2],
  searchFields: ["Name", "City"],
  returnGeometry: true,
  outSpatialReference: { wkid: 4326 },
});

const mapServiceUrl =
  "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer";
const result = await find.find(mapServiceUrl, params);

result.results.forEach((findResult) => {
  console.log("Layer:", findResult.layerId, "Value:", findResult.value);
});

识别

识别地图服务中特定位置的要素。

import * as identify from "@arcgis/core/rest/identify.js";
import IdentifyParameters from "@arcgis/core/rest/support/IdentifyParameters.js";

const params = new IdentifyParameters({
  geometry: view.toMap(screenPoint),
  mapExtent: view.extent,
  tolerance: 3,
  width: view.width,
  height: view.height,
  layerOption: "all",
  returnGeometry: true,
  spatialReference: view.spatialReference,
});

const mapServiceUrl =
  "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer";
const result = await identify.identify(mapServiceUrl, params);

result.results.forEach((identifyResult) => {
  console.log("Layer:", identifyResult.layerName);
  console.log("Attributes:", identifyResult.feature.attributes);
});

打印

通过服务器端打印服务将地图导出为 PDF、PNG 或其他格式。

import * as print from "@arcgis/core/rest/print.js";
import PrintTemplate from "@arcgis/core/rest/support/PrintTemplate.js";
import PrintParameters from "@arcgis/core/rest/support/PrintParameters.js";

const template = new PrintTemplate({
  format: "pdf",
  layout: "letter-ansi-a-landscape",
  layoutOptions: {
    titleText: "My Map Export",
    authorText: "Map Author",
    scalebarUnit: "Miles",
  },
  exportOptions: {
    dpi: 300,
    width: 800,
    height: 1100,
  },
});

const params = new PrintParameters({
  view,
  template,
});

const printUrl =
  "https://utility.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task";
const result = await print.execute(printUrl, params);

window.open(result.url);

地点

使用 ArcGIS Places 服务搜索兴趣点(POI)。

查询点附近的地点
import * as places from "@arcgis/core/rest/places.js";
import PlacesQueryParameters from "@arcgis/core/rest/support/PlacesQueryParameters.js";

const queryParams = new PlacesQueryParameters({
  categoryIds: ["13065"], // Restaurants
  radius: 500, // meters
  point: { type: "point", longitude: -87.626, latitude: 41.882 },
  pageSize: 20,
});

const results = await places.queryPlacesNearPoint(queryParams);

results.results.forEach((place) => {
  console.log(place.name, place.categories[0].label);
  console.log("Distance:", place.distance, "m");
});

// Pagination
if (results.nextPage) {
  const nextResults = await results.nextPage();
}
查询范围内的地点
const queryParams = new PlacesQueryParameters({
  categoryIds: ["16000"], // Landmarks and Outdoors
  xmin: -87.65,
  ymin: 41.87,
  xmax: -87.6,
  ymax: 41.9,
});

const results = await places.queryPlacesWithinExtent(queryParams);
获取地点详情
import FetchPlaceParameters from "@arcgis/core/rest/support/FetchPlaceParameters.js";

const fetchParams = new FetchPlaceParameters({
  placeId: results.results[0].placeId,
  requestedFields: ["all"],
});

const details = await places.fetchPlace(fetchParams);
const placeDetails = details.placeDetails;

console.log("Name:", placeDetails.name);
console.log("Address:", placeDetails.address.streetAddress);
console.log("Phone:", placeDetails.contactInfo?.telephone);
console.log("Hours:", placeDetails.hours?.opening);
console.log("Rating:", placeDetails.rating?.user);
地点类别 ID
类别ID
艺术与娱乐10000
商业与专业服务11000
社区与政府12000
餐饮13000
医疗与健康15000
地标与户外16000
零售17000
体育与休闲18000
旅行与交通19000

地理处理器

在 ArcGIS Server 上运行自定义地理处理任务。

同步执行
import * as geoprocessor from "@arcgis/core/rest/geoprocessor.js";

const gpUrl =
  "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed";

const params = {
  Input_Observation_Point: new FeatureSet({ features: [pointGraphic] }),
  Viewshed_Distance: 15000,
};

const result = await geoprocessor.execute(gpUrl, params);

const outputFeatures = result.results[0].value;
outputFeatures.features.forEach((feature) => {
  graphicsLayer.add(
    new Graphic({ geometry: feature.geometry, symbol: fillSymbol }),
  );
});
异步执行(长时间运行)
const jobInfo = await geoprocessor.submitJob(gpUrl, params);

// Wait for completion
const completedJobInfo = await jobInfo.waitForJobCompletion({
  interval: 2000,
  statusCallback: (info) => {
    console.log("Status:", info.jobStatus);
  },
});

// Fetch results
const resultData = await completedJobInfo.fetchResultData("Result_Layer");

几何服务

执行服务器端几何操作。

import * as geometryService from "@arcgis/core/rest/geometryService.js";

const geomServiceUrl =
  "https://utility.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer";

// Project geometries
const projected = await geometryService.project(geomServiceUrl, {
  geometries: [point1, point2],
  inSpatialReference: { wkid: 4326 },
  outSpatialReference: { wkid: 3857 },
});

// Buffer geometries
const buffered = await geometryService.buffer(geomServiceUrl, {
  geometries: [point],
  distances: [1000],
  unit: "meters",
  outSpatialReference: { wkid: 4326 },
});

// Areas and lengths
const result = await geometryService.areasAndLengths(geomServiceUrl, {
  polygons: [polygon],
  lengthUnit: "meters",
  areaUnit: "square-meters",
});

影像服务

import * as imageService from "@arcgis/core/rest/imageService.js";
import ImageIdentifyParameters from "@arcgis/core/rest/support/ImageIdentifyParameters.js";

const params = new ImageIdentifyParameters({
  geometry: clickPoint,
  returnGeometry: true,
  returnCatalogItems: true,
});

const result = await imageService.identify(imageServiceUrl, params);
console.log("Pixel value:", result.value);

REST 服务身份验证

高级服务(路径规划、地理编码、地点搜索)需要身份验证。

import esriConfig from "@arcgis/core/config.js";

// Set API key globally
esriConfig.apiKey = "YOUR_API_KEY";

// Or register a token for a specific server
import esriId from "@arcgis/core/identity/IdentityManager.js";

esriId.registerToken({
  server: "https://route-api.arcgis.com",
  token: "YOUR_TOKEN",
});

常见问题

  1. 高级服务缺少身份验证:路径规划、地点搜索和地理编码服务需要 API 密钥或 OAuth 令牌。发出请求前请设置 esriConfig.apiKey。

  2. 使用了错误的参数类:每种 REST 服务都有自己的参数类(例如,路径规划使用 RouteParameters,最近设施使用 ClosestFacilityParameters)。使用错误的类会导致静默失败。

  3. 忘记设置 outSpatialReference:结果默认采用服务的空间参考。请始终在参数中设置 outSpatialReference,使其与视图匹配:

    const params = new RouteParameters({
      stops,
      outSpatialReference: view.spatialReference,
    });
    
  4. 未处理服务错误:请始终使用 try/catch 包装 REST 调用:

    try {
      const result = await route.solve(routeUrl, routeParams);
    } catch (error) {
      if (error.name === "AbortError") {
        console.log("Request was cancelled");
      } else {
        console.error("Service error:", error.message);
      }
    }
    
  5. 使用旧版任务模式:esri/tasks/* 模式已被移除。请使用 @arcgis/core/rest/* 模块及其静态函数调用。

最后一公里配送

求解包含取货和配送约束的车辆路径问题。

import * as lastMileDelivery from "@arcgis/core/rest/lastMileDelivery.js";

// Get service description
const serviceDescription =
  await lastMileDelivery.getServiceDescription(serviceUrl);

// Solve a vehicle routing problem
const result = await lastMileDelivery.solve(serviceUrl, params);

参考示例

  • route - 停靠点之间的路线查找
  • directions-routelayer - 包含路线指引的路线图层
  • basemap-places - 用于发现兴趣点的地点服务
  • places - 地点查询和详情获取
  • geoprocessing-viewshed - 使用视域分析进行地理处理
  • geoprocessing-hotspot - 通过地理处理进行热点分析
  • widgets-print - 服务端地图打印
  • tasks-route - 路线规划任务
  • tasks-find - 在地图服务中查找要素
  • tasks-identify - 识别指定位置的要素
  • tasks-query - 从服务中查询要素
  • find - 按属性查找要素
  • identify - 识别指定位置的要素
  • query - 针对要素服务的 REST 查询

相关技能

  • OAuth 和 API 密钥设置,请参阅 arcgis-authentication。
  • FeatureLayer 查询(服务端和客户端),请参阅 arcgis-layers。
  • 客户端几何操作,请参阅 arcgis-geometry-operations。
  • 分析对象和要素缩减,请参阅 arcgis-spatial-analysis。

评论

支持 Markdown