ArcGis for js 4.x实现测量,测距,高程的功能

文章目录


前言

ArcGIS for JS广泛应用于需要在Web上展示和分析空间数据的各种场景中,包括教育、科研和商业领域。它特别适合GIS分析师、IT开发人员以及任何需要在Web上分享和利用地理信息的人员‌


一、三维测量,测距,高程是什么?

三维测量‌是指对物体进行全方位测量,确定其三维坐标测量数据。其测量原理包括测距、角位移、扫描和定向四个方面。根据三维技术原理研发的仪器主要有拍照式(结构光)三维扫描仪、激光三维扫描仪和三坐标测量机等‌

‌测距‌是三维测量中的一个重要组成部分,它通过测量物体与测量设备之间的距离来确定物体的位置。测距的方法有多种,包括激光测距、超声波测距、红外测距等。激光测距是最常见的一种,通过发射激光并测量其反射时间来计算距离‌。

‌高程‌指的是某点沿铅垂线方向到绝对基面的距离,称为绝对高程,简称高程。高程是地理测量中的一个重要概念,用于表示地面点的高低。高程系统采用不同的基准面表示地面点的高低,常见的系统包括正高、正常高、力高和大地高程等‌

‌高程测量‌主要有水准测量和三角高程测量等方法。水准测量是利用水平视线来测量两点间的高差,由于其精度较高,因此是高程测量中最主要的方法。三角高程测量则是通过测量两点间的水平距离或斜距和竖直角来计算高差,一般精度较低,仅在适当条件下采用‌

二、使用步骤

1.引入库

代码如下(示例):

c 复制代码
import { Polyline } from '@arcgis/core/geometry';
import Graphic from '@arcgis/core/Graphic';
import Point from '@arcgis/core/geometry/Point';
import * as geometryEngine from '@arcgis/core/geometry/geometryEngine';
import Draw from '@arcgis/core/views/draw/Draw';
import GraphicsLayer from '@arcgis/core/layers/GraphicsLayer';
import Polygon from '@arcgis/core/geometry/Polygon';
import TextSymbol from '@arcgis/core/symbols/TextSymbol';
import ElevationLayer from '@arcgis/core/layers/ElevationLayer';
import SimpleMarkerSymbol from '@arcgis/core/symbols/SimpleMarkerSymbol';

2.初始化Draw

初始化的时候必须保证三维view初始化结束

c 复制代码
 drawBar = new Draw({ view: view3d });

3.初始化图层

必须初始化点线面的图层为的就是好管理地图操作

c 复制代码
 const newLineLayer = new GraphicsLayer({
          id: 'LandQueryDrawLayer',
          elevationInfo: {
            mode: 'on-the-ground',
          },
        });
        view3d.map.add(newLineLayer);
        const newPolygonLayer = new GraphicsLayer({
          id: 'LandQueryPolygonDrawLayer',
          elevationInfo: {
            mode: 'on-the-ground',
          },
        });
        view3d.map.add(newPolygonLayer);
        const newPointLayer = new GraphicsLayer({
          id: 'LandQueryPointDrawLayer',
          elevationInfo: {
            mode: 'on-the-ground',
          },
        });

4.测量距离功能

绘制点成线,利用arcgis的计算模块进行

c 复制代码
测量距离
  const measureDistance = () => {
    clearMeasureActionAndGraphics();
    distanceMeasure = true; //激活距离测量
    let action = drawBar.create('polyline'); //创建画线实例
    view3d.focus();
    action.on(
      [
        'vertex-add', // when a vertex is added  鼠标单击
        'vertex-remove', // when a vertex is removed 移除
        'cursor-update', // when the pointer moves 鼠标移动
        'draw-complete', // when the drawing is completed 鼠标双击
      ],
      function (evt) {
        createLine(evt.vertices);
      },
    );
  };
  const createLine = (vertices) => {
    view3d.map.findLayerById('LandQueryDrawLayer').removeAll(); //清空上次绘制的线
    let symbol = {
      //点样式
      type: 'simple-marker',
      color: [47, 79, 79],
      width: 0.5,
      size: 4,
      outline: {
        color: [0, 0, 0],
        width: 1,
      },
    };
    //将起点添加到地图
    let startGraphics = new Graphic({
      geometry: new Point({
        type: 'point',
        x: vertices[0][0], //当底图是投影坐标系时用x,地理坐标系用longitude
        y: vertices[0][1], //当底图是投影坐标系时用y,地理坐标系用latitude
        spatialReference: view3d.spatialReference, //和底图相同的坐标系
      }),
      symbol: symbol,
    });

    view3d.map.findLayerById('LandQueryDrawLayer').add(startGraphics);
    //将线添加到地图
    let lineGraphics = new Graphic({
      geometry: new Polyline({
        paths: vertices,
        spatialReference: view.spatialReference,
      }),
      symbol: {
        //线样式
        type: 'simple-line', // autocasts as new SimpleFillSymbol
        style: 'dash',
        color: [176, 196, 222],
        width: 2,
      },
    });
    view3d.map.findLayerById('LandQueryDrawLayer').add(lineGraphics);

    //测距
    let linePath = []; //线段坐标集合
    let pointStart = []; //起点
    pointStart.push(vertices[0][0]);
    pointStart.push(vertices[0][1]);
    linePath.push(pointStart);

    for (let i = 1; i < vertices.length; i++) {
      //获得鼠标移动的坐标信息
      let point = {
        type: 'point',
        x: vertices[i][0],
        y: vertices[i][1],
        spatialReference: view3d.spatialReference,
      };
      //鼠标位置
      let mouseGraphics = new Graphic({
        geometry: point,
        symbol: symbol,
      });
      let xy = []; //鼠标当前经纬度
      xy.push(vertices[i][0]);
      xy.push(vertices[i][1]);
      linePath.push(xy);
      let line = new Polyline({
        //起点到当前鼠标的线段
        paths: linePath,
        spatialReference: view3d.spatialReference,
      });
      let length = geometryEngine.geodesicLength(line, 'meters').toFixed(2); //测距
      let lengthText = lengthFormat(length); //单位转换
      let textSymbol = {
        //距离标注
        type: 'text',
        color: 'white',
        haloColor: 'black',
        haloSize: '2px',
        text: lengthText,
        xoffset: '50px',
        yoffset: '-5px',
        font: {
          size: 12,
          family: 'sans-serif',
          weight: 'bold',
        },
      };
      let textGraphics = new Graphic({
        //标注位置为鼠标位置
        geometry: point,
        symbol: textSymbol,
      });
      //将标注和鼠标位置添加到地图
      view3d.map
        .findLayerById('LandQueryDrawLayer')
        .addMany([textGraphics, mouseGraphics]);
    }
  };

5.测量面积

c 复制代码
 /**
   * 面积测量,对外暴露
   */
  const measureArea = () => {
    clearMeasureActionAndGraphics();
    areaMeasure = true;
    let action = drawBar.create('polygon'); //创建画线实例
    view3d.focus();
    action.on(
      [
        'vertex-add', // when a vertex is added  鼠标单击
        'vertex-remove', // when a vertex is removed 移除
        'cursor-update', // when the pointer moves 鼠标移动
        'draw-complete', // when the drawing is completed 鼠标双击
      ],
      function (evt) {
        // 检查在绘制完成时,vertices 是否构成有效的多边形
        let vertices = evt.vertices;
        if (vertices.length < 3) {
          console.error('至少需要三个点来形成有效的多边形!');
          return;
        }
        // 确保多边形是封闭的:将第一个点添加到末尾
        if (!isPolygonClosed(vertices)) {
          vertices.push(vertices[0]); // 添加第一个点到末尾,封闭多边形
        }
        createPolygon(vertices); // 调用函数绘制多边形
      },
    );
  };
  //画面和测量面积
  const createPolygon = (vertices) => {
    view3d.map.findLayerById('LandQueryPolygonDrawLayer').removeAll();
    let symbol = {
      //点样式
      type: 'simple-marker',
      color: [47, 79, 79],
      width: 0.5,
      size: 4,
      outline: {
        color: [0, 0, 0],
        width: 1,
      },
    };
    let fillSymbol = {
      //面样式
      type: 'simple-fill', // autocasts as new SimpleFillSymbol()
      color: [3, 255, 240, 0.1],
      outline: {
        // autocasts as new SimpleLineSymbol()
        color: [255, 116, 3],
        width: 2,
      },
    };

    let polygon = new Polygon({
      rings: vertices,
      spatialReference: view3d.spatialReference,
    });
    let polygonGraphics = new Graphic({
      geometry: polygon,
      symbol: fillSymbol,
    });
    view3d.map.findLayerById('LandQueryPolygonDrawLayer').add(polygonGraphics);
    const area = Math.abs(
      geometryEngine.geodesicArea(polygon, 'square-meters'),
    );
    let areaText = areaFormat(area);
    let center = polygon.centroid;
    let pointCenter = {
      type: 'point',
      longitude: center.longitude,
      latitude: center.latitude,
    };
    let textSymbol = {
      //面积标注
      type: 'text',
      color: 'white',
      haloColor: 'black',
      haloSize: '2px',
      text: areaText,
      //xoffset: '50px',
      //yoffset: '-5px',
      font: {
        size: 12,
        family: 'sans-serif',
        weight: 'bold',
      },
    };
    let textGraphics = new Graphic({
      //标注为面中心位置
      geometry: pointCenter,
      symbol: textSymbol,
    });
    view3d.map.findLayerById('LandQueryPolygonDrawLayer').add(textGraphics);

    for (let i = 0; i < vertices.length; i++) {
      let point = {
        type: 'point',
        x: vertices[i][0],
        y: vertices[i][1],
        spatialReference: view3d.spatialReference,
      };

      let pointGraphics = new Graphic({
        geometry: point,
        symbol: symbol,
      });
      view3d.map.findLayerById('LandQueryPolygonDrawLayer').add(pointGraphics);
    }
  };

5.测量高程

添加地图点击事件

c 复制代码
 view3d.on('click', (event) => {
        const point = event.mapPoint;
        if (heightMeasure) {
          // 查询高程
          getElevation(point);
        }
      });
//获取高程
  const getElevation = (point) => {
    console.log(5555555, point);
    const pointGeometry = new Point({
      longitude: point.longitude,
      latitude: point.latitude,
    });
    displayElevationOnMap(pointGeometry, point.z);

    elevationLayer
      .queryElevation([pointGeometry])
      .then(function (result) {
        const elevation = result[0].z; // 获取返回的第一个样本的高程值
        console.log('Elevation at clicked point:', elevation);
        // 在地图上显示高程
        displayElevationOnMap(pointGeometry, point.z);
      })
      .catch(function (error) {
        console.error('Error fetching elevation:', error);
      });
  };
  // 显示高程信息在地图上
  const displayElevationOnMap = (point, elevation) => {
    if (view3d.map.findLayerById('LandQueryPointDrawLayer')) {
      view3d.map.findLayerById('LandQueryPointDrawLayer').removeAll();
    }
    // 创建文本符号
    const textSymbol = new TextSymbol({
      text: `高程值: ${elevation.toFixed(2)}米`,
      color: 'white',
      haloColor: 'black',
      haloSize: '2px',
      font: {
        size: 12,
        family: 'sans-serif',
        weight: 'bold',
      },
    });
    const markerSymbol = new SimpleMarkerSymbol({
      color: [226, 119, 40], // 设置标记颜色
      size: '10px', // 设置标记大小
      outline: {
        // 设置边框
        color: [255, 0, 0],
        width: 2,
      },
    });

    // 创建图形
    const graphicPoint = new Graphic({
      geometry: point,
      symbol: markerSymbol,
    });
    const graphicText = new Graphic({
      geometry: point,
      symbol: textSymbol,
    });

    // 将图形添加到视图中
    view3d.map.findLayerById('LandQueryPointDrawLayer').add(graphicPoint);
    view3d.map.findLayerById('LandQueryPointDrawLayer').add(graphicText);
  };
  const lengthFormat = (length) => {
    if (length < 2000) {
      return length + '米';
    } else {
      length = (length / 1000).toFixed(2);
      return length + '千米';
    }
  };
  const areaFormat = (area) => {
    if (area < 2000) {
      area = area.toFixed(2);
      return area + '平方米';
    } else {
      area = (area / 10000).toFixed(2);
      return area + '平方千米';
    }
  };
  const clearMeasureActionAndGraphics = () => {
    distanceMeasure = false;
    areaMeasure = false;
    heightMeasure = false;
    drawBar.destroy();
  };

清理地图图层

整个关于ARCGIS的测量功能就完美实现了

c 复制代码
const clearMeasureActionAndGraphicsLine = () => {
    if (view3d.map.findLayerById('LandQueryDrawLayer')) {
      view3d.map.findLayerById('LandQueryDrawLayer').removeAll();
    }
    clearMeasureActionAndGraphics();
  };
  const clearMeasureActionAndGraphicsPolygon = () => {
    if (view3d.map.findLayerById('LandQueryPolygonDrawLayer')) {
      view3d.map.findLayerById('LandQueryPolygonDrawLayer').removeAll();
    }
    clearMeasureActionAndGraphics();
  };
  const clearMeasureActionAndGraphicsPoint = () => {
    if (view3d.map.findLayerById('LandQueryPointDrawLayer')) {
      view3d.map.findLayerById('LandQueryPointDrawLayer').removeAll();
    }
    clearMeasureActionAndGraphics();
  };
相关推荐
shinelord明2 分钟前
【再谈设计模式】访问者模式~操作对象结构的新视角
开发语言·数据结构·算法·设计模式·软件工程
Python私教11 分钟前
Flutter 实现抖音风格底部导航栏
android·开发语言·javascript
y.Ghost15 分钟前
数据结构与算法:均值滤波
c语言·图像处理·人工智能·算法·计算机视觉·均值算法·均值滤波
❆VE❆19 分钟前
vue3: directive自定义指令防止重复点击
前端·javascript·vue.js·自定义指令·directive
布兰妮甜25 分钟前
Fetch API 与 XMLHttpRequest:深入剖析异步请求的利器
前端·javascript·xmlhttprequest·fetch api
程序员南飞40 分钟前
算法-数据结构-图-邻接表构建
java·数据结构·算法·职场和发展
yngsqq41 分钟前
推导二维平面上点绕原点旋转的公式
数学·算法·机器学习·平面
白水先森1 小时前
ArcGIS Pro中创建最低成本路径的详尽教程
经验分享·arcgis·arcgispro
Moring.1 小时前
贪心算法
算法·贪心算法
巴巴博一1 小时前
vue-i18n国际化插件安装教程(Vue3篇)
前端·javascript·vue.js·typescript