【Cesium系列】实现测距的一个类

638 阅读1分钟

  一般在gis开发中,像Openlayers, Leaflet等二维地图库,都提供测距的功能。但是在Cesium三维地图库中,支持测距,测面和测高。

实现一个如下图的测距功能

Dingtalk_20221227143036.jpg

💡实现思路

  1. 在地图上绘制点与线;2. 计算点与点之间距离, 每条段线添加长度提示标签;3. 起点与终点添加标识

一.绘制点

绘制点分为两类:一类为起始点和终点,是需要添加图标的,一类是普通的添加点

 // 创建排除起点/终点的点
  private createVertex() {
    let vertexEntity = this.options.viewer.entities.add({
      position: this.positions[this.positions.length - 1],
      id: 'MeasureDistanceVertex' + this.positions[this.positions.length - 1],
      type: 'MeasureDistanceVertex',
      label: {
        text: this.spaceDistance(this.positions) + '米',
        scale: 0.5,
        font: 'normal 24px MicroSoft YaHei',
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        pixelOffset: new Cesium.Cartesian2(0, -30),
        outlineWidth: 9,
        outlineColor: Cesium.Color.WHITE
      },
      point: {
        color: Cesium.Color.FUCHSIA,
        pixelSize: 8,
        disableDepthTestDistance: 500
      }
    })
    this.vertexEntities.push(vertexEntity)
  }
  // 创建起点实体
  private createStartEntity() {
    let vertexEntity = this.options.viewer.entities.add({
      position: this.positions[0],
      type: 'MeasureDistanceVertex',
      billboard: {
        image: startPoint,
        width: 36,
        height: 36,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        disableDepthTestDistance: Number.POSITIVE_INFINITY
      },
      point: {
        color: Cesium.Color.FUCHSIA,
        pixelSize: 6
      }
    })
    this.vertexEntities.push(vertexEntity)
  }

二.绘制线

  private createLineEntity() {
    this.lineEntities = viewer.entities.add({
      polyline: {
        positions: new Cesium.CallbackProperty((e: Event) => {
          return this.tempPositions
        }, false),
        width: 2,
        material: this.options.lineColor,
        depthFailMaterial: this.options.lineColor,
        disableDepthTestDistance: 500,
        clampToGround: true
      }
    })
  }

三.计算点与点之间距离

  private spaceDistance(positions: IPosition[]) {
    let distance = 0
    for (let i = 0; i < positions.length - 1; i++) {
      let point1cartographic = Cesium.Cartographic.fromCartesian(positions[i])
      let point2cartographic = Cesium.Cartographic.fromCartesian(positions[i + 1])
      // 根据经纬度计算出距离
      let geodesic = new Cesium.EllipsoidGeodesic()
      geodesic.setEndPoints(point1cartographic, point2cartographic)
      let s = geodesic.surfaceDistance
      // 返回两点之间的距离
      s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2))
      distance = distance + s
    }
    return distance.toFixed(2)
  }

四.Cesium中鼠标事件的注册

  在添加完绘制的所有事件后,需要注册Cesium中的鼠标点击事件,鼠标右键结束绘制事件,以及记录鼠标移动过程中移动事件。

this.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
    this.handler.setInputAction((e: any) => {
     // 点的创建的相关处理
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
    this.handler.setInputAction((e: any) => {
    // 绘制结束的相关处理
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
    this.handler.setInputAction((e: any) => {
      // 鼠标移动过程中,点的相关记录
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)

五.Cesium中鼠标事件的移除

  private unRegisterEvents() {
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK)
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
  }