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

news/2025/2/26 5:16:01

文章目录

  • 前言
  • 一、三维测量,测距,高程是什么?
  • 二、使用步骤
    • 1.引入库
    • 2.初始化Draw
    • 3.初始化图层
    • 4.测量距离功能
    • 5.测量面积
    • 5.测量高程
  • 清理地图图层


前言

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


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

三维测量‌是指对物体进行全方位测量,确定其三维坐标测量数据。其测量原理包括测距、角位移、扫描和定向四个方面。根据三维技术原理研发的仪器主要有拍照式(结构光)三维扫描仪、激光三维扫描仪和三坐标测量机等‌
‌测距‌是三维测量中的一个重要组成部分,它通过测量物体与测量设备之间的距离来确定物体的位置。测距的方法有多种,包括激光测距、超声波测距、红外测距等。激光测距是最常见的一种,通过发射激光并测量其反射时间来计算距离‌。
‌高程‌指的是某点沿铅垂线方向到绝对基面的距离,称为绝对高程,简称高程。高程是地理测量中的一个重要概念,用于表示地面点的高低。高程系统采用不同的基准面表示地面点的高低,常见的系统包括正高、正常高、力高和大地高程等‌
‌高程测量‌主要有水准测量和三角高程测量等方法。水准测量是利用水平视线来测量两点间的高差,由于其精度较高,因此是高程测量中最主要的方法。三角高程测量则是通过测量两点间的水平距离或斜距和竖直角来计算高差,一般精度较低,仅在适当条件下采用‌

二、使用步骤

1.引入库

代码如下(示例):

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初始化结束

 drawBar = new Draw({ view: view3d });

3.初始化图层

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

 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的计算模块进行

测量距离
  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.测量面积

 /**
   * 面积测量,对外暴露
   */
  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.测量高程

添加地图点击事件

 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的测量功能就完美实现了

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();
  };

http://www.niftyadmin.cn/n/5868007.html

相关文章

C++ QT 6.6.1 QCustomPlot的导入及使用注意事项和示例 | 关于高版本QT使用QCustomPlot报错问题解决的办法

C QT 6.6.1 QCustomPlot的导入及使用注意事项和示例 | 关于高版本QT使用QCustomPlot报错问题解决的办法 记录一下 qmake .pro文件的配置 QT core gui printsupportgreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c17# You can make your code fail to compil…

反向代理模块kfj

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当于…

ros面试准备

ROS中的通信方式有哪些&#xff1f; topic service action topic:发布-订阅模型&#xff0c;适合持续的数据流&#xff0c;如传感器 service:请求-响应模型&#xff0c;适合即时操作&#xff0c;如开关控制 如何调试一个无法通信的话题&#xff1f; 第一、rostopic list检查话…

TDengine 产品组件:taosKeeper

taosKeeper 是 TDengine 3.0 版本监控指标的导出工具&#xff0c;通过简单的几项配置即可获取 TDengine 的运行状态。taosKeeper 使用 TDengine RESTful 接口&#xff0c;所以不需要安装 TDengine 客户端即可使用。 安装 taosKeeper 有两种安装方式&#xff1a; 安装 TDengin…

java23种设计模式-抽象工厂模式

抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;学习笔记 &#x1f31f; 定义 抽象工厂模式属于创建型设计模式&#xff0c;提供一个创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类。是工厂方法模式的升级版&#xff0c;支持多个产品…

【idea问题排查技巧】

以下是针对 IDEA 中 日志打标(动态标记) 和 全链路追踪 功能的分步详解,结合具体场景和操作截图说明,帮助快速掌握实战技巧。 一、动态日志打标:不修改代码输出关键信息 1. 断点日志打印(非侵入式打标) 场景:在调试时,需要临时查看某个变量的值,但不想修改代码添加…

在Spring Boot中如何使用Freemaker模板引擎

在 Spring Boot 中使用 FreeMarker 模板引擎可以帮助你创建动态的 Web 页面。以下是详细的步骤和示例代码,介绍如何在 Spring Boot 项目里集成和使用 FreeMarker。 1. 添加依赖 如果你使用的是 Maven 项目,需要在 pom.xml 文件中添加 FreeMarker 相关依赖。Spring Boot 提供…

Elasticsearch索引设计与分片策略深度优化-手记

一、索引设计的黄金法则&#xff08;从踩坑到精通的必经之路&#xff09; 1. 字段类型显式声明原则 动态映射是新手最易踩的坑&#xff0c;某金融平台曾因金额字段被自动识别为text类型&#xff0c;导致聚合查询时触发OOM。正确做法应显式声明核心字段&#xff1a; PUT /fin…