cesium面积测量

该博客介绍了一个在Cesium地图上实现面积测量的JavaScript类`measureArea`。这个类支持绘制面、计算面积并提供开始绘制、加载面、销毁等方法。用户可以通过鼠标操作来创建和编辑多边形,测量完成后会显示面积值,并可以通过回调函数获取测量结果。
摘要由CSDN通过智能技术生成

使用方法新建一个文件measureArea.js将下面代码贴上去

// DrawPolygon
/*
绘制面(面积测量)
 */

class measureArea {
  constructor(arg) {
    this.objId = Number(
      new Date().getTime() + "" + Number(Math.random() * 1000).toFixed(0)
    );
    this.viewer = arg.viewer;
    this.Cesium = arg.Cesium;
    this.callback = arg.callback;
    this._polygon = null; //活动面
    this._polygonLast = null; //最后一个面
    this._positions = []; //活动点
    this._entities_point = []; //脏数据
    this._entities_polygon = []; //脏数据
    this._polygonData = null; //用户构造面
  }

  //返回最后活动面
  get polygon() {
    return this._polygonLast;
  }

  //返回面数据用于加载面
  getData() {
    return this._polygonData;
  }

  //加载面
  loadPolygon(data) {
    var $this = this;
    return this.viewer.entities.add({
      polygon: {
        hierarchy: new $this.Cesium.PolygonHierarchy(data),
        clampToGround: true,
        show: true,
        fill: true,
        material: $this.Cesium.Color.RED.withAlpha(0.5),
        width: 3,
        outlineColor: $this.Cesium.Color.BLACK,
        outlineWidth: 1,
        outline: false,
        classificationType: Cesium.ClassificationType.BOTH // 支持类型: 地形、3DTile、或者在地面上
      }
    });
  }

  //开始绘制
  startCreate() {
    var $this = this;
    this.handler = new this.Cesium.ScreenSpaceEventHandler(
      this.viewer.scene.canvas
    );
    this.handler.setInputAction(function(evt) {
      //单机开始绘制
      var cartesian = $this.getCatesian3FromPX(evt.position);
      if ($this._positions.length == 0) {
        $this._positions.push(cartesian.clone());
      }
      if (cartesian) {
        $this.createPoint(cartesian);
        $this._positions.push(cartesian);
      }
    }, $this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
    this.handler.setInputAction(function(evt) {
      //移动时绘制面
      if ($this._positions.length < 1) return;
      var cartesian = $this.getCatesian3FromPX(evt.endPosition);
      if ($this._positions.length == 3) {
        if (!$this.Cesium.defined($this._polygon)) {
          $this._polygon = $this.createPolygon();
        }
      }

      if (cartesian) {
        $this._positions.pop();
        $this._positions.push(cartesian);
      }
    }, $this.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    this.handler.setInputAction(function(evt) {
      if (!$this._polygon) return;
      var cartesian = $this.getCatesian3FromPX(evt.position);
      $this._positions.pop();
      $this._positions.push(cartesian);
      $this.createPoint(cartesian);
      $this._polygonData = $this._positions.concat();
      $this.viewer.entities.remove($this._positions); //移除
      $this._positions = null;
      $this._positions = [];
      var Polygon = $this.loadPolygon($this._polygonData);
      $this._entities_polygon.push(Polygon);
      $this._polygonLast = Polygon;
      var textArea = $this.getArea($this._polygonData) + "平方米";
      $this.createPointLabel(
        $this._polygonData[$this._polygonData.length - 1],
        textArea
      );
      $this.destroy();
      if (typeof $this.callback == "function") {
        $this.callback(cartesian);
      }
    }, $this.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }

  //创建面
  createPolygon() {
    var $this = this;
    var polygon = this.viewer.entities.add({
      polygon: {
        hierarchy: new $this.Cesium.CallbackProperty(function() {
          return new $this.Cesium.PolygonHierarchy($this._positions);
        }, false),
        clampToGround: true,
        show: true,
        fill: true,
        material: $this.Cesium.Color.RED.withAlpha(0.5),
        width: 3,
        outlineColor: $this.Cesium.Color.BLACK,
        outlineWidth: 1,
        outline: false
      }
    });
    $this._entities_polygon.push(polygon);
    return polygon;
  }

  //创建点
  createPoint(cartesian) {
    var $this = this;
    var point = this.viewer.entities.add({
      position: cartesian,
      point: {
        pixelSize: 10,
        color: $this.Cesium.Color.YELLOW,
        disableDepthTestDistance: Number.POSITIVE_INFINITY, //被遮罩
        classificationType: Cesium.ClassificationType.BOTTOM
      }
    });
    point.objId = this.objId;
    $this._entities_point.push(point);
    return point;
  }

  //创建点
  createPointLabel(cartesian, textArea) {
    var $this = this;
    var point = this.viewer.entities.add({
      position: cartesian,
      label: {
        text: textArea,
        font: "18px sans-serif",
        fillColor: $this.Cesium.Color.GOLD,
        style: $this.Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth: 2,
        disableDepthTestDistance: Number.POSITIVE_INFINITY, //被遮罩
        classificationType: Cesium.ClassificationType.BOTTOM,
        verticalOrigin: $this.Cesium.VerticalOrigin.BOTTOM,
        pixelOffset: new $this.Cesium.Cartesian2(20, -40),
        heightReference: $this.Cesium.HeightReference.CLAMP_TO_GROUND
      }
    });
    point.objId = this.objId;
    $this._entities_point.push(point);
    return point;
  }

  //销毁事件
  destroy() {
    if (this.handler) {
      this.handler.destroy();
      this.handler = null;
    }
  }

  //清空实体对象
  clear() {
    for (var i = 0; i < this._entities_point.length; i++) {
      this.viewer.entities.remove(this._entities_point[i]);
    }
    for (var i = 0; i < this._entities_polygon.length; i++) {
      this.viewer.entities.remove(this._entities_polygon[i]);
    }
    this._polygon = null; //活动面
    this._polygonLast = null; //最后一个面
    this._positions = []; //活动点
    this._entities_point = []; //脏数据
    this._entities_polygon = []; //脏数据
    this._polygonData = null; //用户构造面
  }

  getCatesian3FromPX(px) {
    var cartesian;
    cartesian = this.viewer.scene.pickPosition(px);
    return cartesian;
  }

  //计算多边形面积
  getArea(points) {
    var res = 0;
    //拆分三角曲面
    for (var i = 0; i < points.length - 2; i++) {
      var j = (i + 1) % points.length;
      var k = (i + 2) % points.length;
      var totalAngle = this.Angle(points[i], points[j], points[k]);

      var dis_temp1 = this.distance(points[i], points[j]);
      var dis_temp2 = this.distance(points[j], points[k]);
      res += dis_temp1 * dis_temp2 * Math.abs(Math.sin(totalAngle));
    }

    return res;
  }

  /*角度*/
  Angle(p1, p2, p3) {
    var bearing21 = this.Bearing(p2, p1);
    var bearing23 = this.Bearing(p2, p3);
    var angle = bearing21 - bearing23;
    if (angle < 0) {
      angle += 360;
    }
    return angle;
  }

  /*方向*/
  Bearing(from, to) {
    var radiansPerDegree = Math.PI / 180.0; //角度转化为弧度(rad)
    var degreesPerRadian = 180.0 / Math.PI; //弧度转化为角度
    var cartographic_from = this.Cesium.Cartographic.fromCartesian(from);
    var cartographic_to = this.Cesium.Cartographic.fromCartesian(to);
    var lon_from = this.Cesium.Math.toDegrees(cartographic_from.longitude);
    var lat_from = this.Cesium.Math.toDegrees(cartographic_from.latitude);

    var lon_to = this.Cesium.Math.toDegrees(cartographic_to.longitude);
    var lat_to = this.Cesium.Math.toDegrees(cartographic_to.latitude);

    var lat1 = lat_from * radiansPerDegree;
    var lon1 = lon_from * radiansPerDegree;
    var lat2 = lat_to * radiansPerDegree;
    var lon2 = lon_to * radiansPerDegree;
    var angle = -Math.atan2(
      Math.sin(lon1 - lon2) * Math.cos(lat2),
      Math.cos(lat1) * Math.sin(lat2) -
        Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2)
    );
    if (angle < 0) {
      angle += Math.PI * 2.0;
    }
    angle = angle * degreesPerRadian; //角度
    return angle;
  }

  distance(point1, point2) {
    var point1cartographic = this.Cesium.Cartographic.fromCartesian(point1);
    var point2cartographic = this.Cesium.Cartographic.fromCartesian(point2);
    /**根据经纬度计算出距离**/
    var geodesic = new this.Cesium.EllipsoidGeodesic();
    geodesic.setEndPoints(point1cartographic, point2cartographic);
    var s = geodesic.surfaceDistance;
    //返回两点之间的距离
    s = Math.sqrt(
      Math.pow(s, 2) +
        Math.pow(point2cartographic.height - point1cartographic.height, 2)
    );
    return s;
  }
}

export default measureArea;

使用方法如下:

import measureArea from "@/assets/js/measureArea.js";
let measureAreas = new measureArea({
        viewer: window.viewer,
        Cesium: Cesium
      });
      measureAreas.startCreate();

效果图

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白学过的代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值