vue+cusium测距以及测面积功能

div页面

<div id="cesiumDemo"></div>
<button @click="draw('Polyline')">标点测距</button>
<button @click="draw('Polygon')">标点测面</button>
<button @click="clearAllDrawn()">清空数据</button>

script页面

import {   getLength,getMidpoint,addLabel,Bearing,drawPolyline,drawPolygon,drawPoint,addArea,drawPointLabel
  } from '../../assets/js/MeasureManager.js'//引入公用组件
export default {
    data() {
      return {
        viewer: undefined,
        tempEntities: [],
        pointNum: 0,
        floatingPoint: undefined,
        activeShape: undefined,
        }
     },
    mounted() {
       this.getCesiumDem()
    },
    methods: {
      // 角度
      pointAngle (point1, point2, point3) {
        let bearing21 = Bearing(point2, point1)
        let bearing23 = Bearing(point2, point3)
        let angle = bearing21 - bearing23
        if (angle < 0) {
          angle += Math.PI * 2.0
        }
        return angle
      },
      getArea(positions) {
        let res = 0
        for (let i = 0; i < positions.length - 2; i++) {
          let j = (i + 1) % positions.length
          let k = (i + 2) % positions.length
          let totalAngle = this.pointAngle(positions[i], positions[j], positions[k])
          let tempLength1 = getLength(positions[j], positions[0])
          let tempLength2 = getLength(positions[k], positions[0])
          res += tempLength1 * tempLength2 * Math.sin(totalAngle) / 2
        }
        res = res.toFixed(2)
        // console.log(res)
        res = parseFloat(res)
        // console.log(Math.abs(res))
        return Math.abs(res)
      },
      /* 清除实体 */
      clearAllDrawn () {
        this.tempEntities = []
        this.pointNum = 0
        viewer.entities.removeAll()
       
      },
      /* 根据类型绘制对象
      * @param type point polyline polygon */
      draw (type) {
        let that = this
        // let viewer = viewer
        // let pointNum = this.pointNum
        // console.log(pointNum)
        let tempEntities = this.tempEntities
        let floatingPoint = this.floatingPoint
        let activeShape = this.activeShape
        let position = []
        let tempPoints = []
        let activeShapePoints = []
        // 开启深度检测
        viewer.scene.globe.depthTestAgainstTerrain = true
        // 创建场景的HTML canvas元素
        let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
        switch (type) {
          // 绘制线
          case 'Polyline':
            // 取消鼠标双击事件
            viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK)
            // 监听鼠标移动
            handler.setInputAction(function (movement) {
              if (Cesium.defined(floatingPoint)) {
                let newPosition = viewer.scene.pickPosition(movement.endPosition)
                if (Cesium.defined(newPosition)) {
                  floatingPoint.position.setValue(newPosition)
                  activeShapePoints.pop()
                  activeShapePoints.push(newPosition)
                }
              }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
            // 左键单击开始画线
            handler.setInputAction(function (click) {
              let earthPosition = viewer.scene.pickPosition(click.position)
              if (Cesium.defined(earthPosition)) {
                floatingPoint = drawPoint(viewer,earthPosition)
              }
              // 获取位置信息
              // 从相机位置创建一条射线,这条射线通过世界中movement.position像素所在的坐标,返回Cartesian3坐标
              let ray = viewer.camera.getPickRay(click.position)
              // 找到射线与渲染的地球表面之间的交点。射线必须以世界坐标给出。返回Cartesian3坐标
              position = viewer.scene.globe.pick(ray, viewer.scene)
              tempPoints.push(position) // 记录点位
              that.pointNum += 1
              let tempLength = tempPoints.length // 记录点数
              // 调用绘制点的接口
              let point = drawPointLabel(viewer,tempPoints[tempPoints.length - 1], JSON.stringify(that.pointNum))
              tempEntities.push(point)
              // 存在超过一个点时
              if (tempLength > 1) {
                // 绘制线
                let pointLength = getLength(tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1])
                let midPosition = getMidpoint(tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1])
                let pointline = drawPolyline(viewer,[tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]])
                let pointLabel = addLabel(viewer,midPosition, pointLength)
                tempEntities.push(pointline) // 保存记录
                tempEntities.push(pointLabel)
              }
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
            // 右键单击结束画线
            handler.setInputAction(function (click) {
              // console.log(that.pointNum)
              activeShapePoints.pop()
              viewer.entities.remove(activeShapePoints)
              viewer.entities.remove(floatingPoint)
              tempPoints = [] // 清空点位记录
              handler.destroy()
              handler = null
              floatingPoint = undefined
              activeShape = undefined
              activeShapePoints = []
              // console.log(that.pointNum)
            }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
            break
          // 绘制面
          case 'Polygon':
            // 取消鼠标双击事件
            viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK)
            // 监听鼠标移动
            handler.setInputAction(function (movement) {
              if (Cesium.defined(floatingPoint)) {
                let newPosition = viewer.scene.pickPosition(movement.endPosition)
                if (Cesium.defined(newPosition)) {
                  floatingPoint.position.setValue(newPosition)
                  activeShapePoints.pop()
                  activeShapePoints.push(newPosition)
                }
              }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
            // 左键单击开始画线
            handler.setInputAction(function (click) {
              let earthPosition = viewer.scene.pickPosition(click.position)
              if (Cesium.defined(earthPosition)) {
                if (activeShapePoints.length === 0) {
                  floatingPoint = drawPoint(viewer,earthPosition)
                  activeShapePoints.push(earthPosition)
                  const dynamicPositions = new Cesium.CallbackProperty(function () {
                    return new Cesium.PolygonHierarchy(activeShapePoints)
                  }, false)
                  activeShape = drawPolygon(viewer,dynamicPositions)
                }
                activeShapePoints.push(earthPosition)
              }
              // 获取位置信息
              let ray = viewer.camera.getPickRay(click.position)
              position = viewer.scene.globe.pick(ray, viewer.scene)
              tempPoints.push(position) // 记录点位
              let tempLength = tempPoints.length // 记录点数
              that.pointNum += 1
              // 调用绘制点的接口
              let point = drawPointLabel(viewer,tempPoints[tempPoints.length - 1], JSON.stringify(that.pointNum))
              tempEntities.push(point)
              // 存在超过一个点时
              if (tempLength > 1) {
                // 绘制线
                let pointline = drawPolyline(viewer,[tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]])
                tempEntities.push(pointline) // 保存记录
              }
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
            // 右键单击结束画面
            handler.setInputAction(function (click) {
              // 选择一个椭球或地图
              let cartesian = viewer.camera.pickEllipsoid(click.position, viewer.scene.globe.ellipsoid)
              if (cartesian) {
                let tempLength = tempPoints.length
                if (tempLength < 3) {
                  alert('闭合操作需要至少3个点嗷')
                } else {
                  // 闭合最后一条线
                  let pointline = drawPolyline(viewer,[tempPoints[0], tempPoints[tempPoints.length - 1]])
                  tempEntities.push(pointline)
                  drawPolygon(viewer,tempPoints)
                  let pointArea = that.getArea(tempPoints)
                  addArea(viewer,JSON.stringify(pointArea), tempPoints)
                  tempEntities.push(tempPoints)
                  handler.destroy()
                  handler = null
                }
              }
              activeShapePoints.pop()
              viewer.entities.remove(activeShapePoints)
              viewer.entities.remove(floatingPoint)
              floatingPoint = undefined
              activeShapePoints = []
            }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
            break
        }
      },
       // 实例cesium
      getCesiumDem() {
        let self = this
        Cesium.Ion.defaultAccessToken ='你的token'
        viewer = new Cesium.Viewer('cesiumDemo', {
          animation: false, // 是否显示动画控件
          baseLayerPicker: false, // 是否显示图层选择控件
          geocoder: false, // 是否显示地名查找控件
          timeline: false, // 是否显示时间线控件
          sceneModePicker: true, // 是否显示投影方式控件
          navigationHelpButton: false, // 是否显示帮助信息控件
          infoBox: true, // 是否显示点击要素之后显示的信息
          fullscreenButton: false, // 是否显示全屏按钮
          selectionIndicator: false, // 是否显示选中指示框
          scene3DOnly: true,
          homeButton: false,
          terrainProvider: new Cesium.EllipsoidTerrainProvider({}),
          //加载高德/百度影像地图,UrlTemplateImageryProvider该接口是加载谷歌地图服务的接口
          // imageryProvider: new BaiduImageryProvider({
          //   url: "http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&p=1"
          // })
    }
  }

公用组件的封装

/* 空间两点距离计算函数 */
 export function getLength(start, end) {
   // 将起点与终点位置信息从笛卡尔坐标形式转换为Cartographic形式
   let startCartographic = Cesium.Cartographic.fromCartesian(start)
   let endCartographic = Cesium.Cartographic.fromCartesian(end)
   // 初始化测地线
   let geodesic = new Cesium.EllipsoidGeodesic()
   // 设置测地线起点和终点,EllipsoidGeodesic中setEndPoints常与surfaceDistance搭配使用
   geodesic.setEndPoints(startCartographic, endCartographic)
   // 获取起点和终点之间的表面距离,单位为km,规定四舍五入保留两位小数
   // surfaceDistance返回number 单位为m,带小数
   // console.log((geodesic.surfaceDistance / 1000).toFixed(2))
   return (geodesic.surfaceDistance / 1000).toFixed(2)
 }
 /* 空间两点计算中点函数 */
 export function getMidpoint(start, end) {
   let startPoint = Cesium.Cartographic.fromCartesian(start)
   let endPoint = Cesium.Cartographic.fromCartesian(end)
   let geodesic = new Cesium.EllipsoidGeodesic()
   geodesic.setEndPoints(startPoint, endPoint)
   let geoPoint = geodesic.interpolateUsingFraction(0.5)
   console.log(Cesium.Ellipsoid.WGS84.cartographicToCartesian(geoPoint))
   return Cesium.Ellipsoid.WGS84.cartographicToCartesian(geoPoint)
 }
 export function addLabel(viewer,midPoint, labelLength) {
   // let viewer = this.viewer

   return viewer.entities.add({
     name: '中点',
     position: midPoint,
     label: {
       text: labelLength + 'km',
       font: '20px sans-serif',
       fillColor: Cesium.Color.WHITE,
       outlineWidth: 2,
       backgroundColor: Cesium.Color.BLACK,
       showBackground: true,
       style: Cesium.LabelStyle.FILL,
       verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
       horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
       heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
       disableDepthTestDistance: Number.POSITIVE_INFINITY
     }
   })
 }
 export function Bearing(from, to) {
   let fromCartographic = Cesium.Cartographic.fromCartesian(from)
   let toCartographic = Cesium.Cartographic.fromCartesian(to)
   let lat1 = fromCartographic.latitude
   let lon1 = fromCartographic.longitude
   let lat2 = toCartographic.latitude
   let lon2 = toCartographic.longitude
   let 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
   }
   return angle
 }
 export function addArea(viewer,area, positions) {
   // let viewer = this.viewer
   return viewer.entities.add({
     name: '多边形面积',
     position: positions[positions.length - 1],
     label: {
       text: area + '平方公里',
       font: '20px sans-serif',
       fillColor: Cesium.Color.WHITE,
       outlineWidth: 2,
       backgroundColor: Cesium.Color.BLACK,
       showBackground: true,
       style: Cesium.LabelStyle.FILL,
       pixelOffset: new Cesium.Cartesian2(60, -60),
       verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
       horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
       heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
       disableDepthTestDistance: Number.POSITIVE_INFINITY
     }
   })
 }
 /* 绘制函数 */
 export function drawPointLabel(viewer,position, pointNum) {
   // let viewer = this.viewer
   // 本质上就是添加一个点的实体
   return viewer.entities.add({
     name: '点几何对象',
     position: position,
     point: {
       color: Cesium.Color.WHEAT,
       pixelSize: 5,
       outlineWidth: 3,
       disableDepthTestDistance: Number.POSITIVE_INFINITY, //
       heightReference: Cesium.HeightReference.CLAMP_TO_GROUND // 规定贴地
     },
     label: {
       text: pointNum,
       font: '30px sans-serif',
       fillColor: Cesium.Color.WHITE,
       outlineWidth: 2,
       backgroundColor: Cesium.Color.BLACK,
       showBackground: true,
       style: Cesium.LabelStyle.FILL,
       verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
       horizontalOrigin: Cesium.HorizontalOrigin.CENTER
     }
   })
 }
 export function drawPoint(viewer,position) {
   // let viewer = this.viewer
   // 本质上就是添加一个点的实体
   return viewer.entities.add({
     position: position,
     point: {
       color: Cesium.Color.WHEAT,
       pixelSize: 5,
       outlineWidth: 3,
       disableDepthTestDistance: Number.POSITIVE_INFINITY,
       heightReference: Cesium.HeightReference.CLAMP_TO_GROUND // 规定贴地
     }
   })
 }
 export function drawPolyline(viewer,positions) {
   // let viewer = this.viewer
   if (positions.length < 1) return
   return viewer.entities.add({
     name: '线几何对象',
     polyline: {
       positions: positions,
       width: 5.0,
       material: new Cesium.PolylineGlowMaterialProperty({
         // eslint-disable-next-line new-cap
         color: Cesium.Color.WHEAT
       }),
       depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({
         // eslint-disable-next-line new-cap
         color: Cesium.Color.WHEAT
       }),
       clampToGround: true
     }
   })
 }
 export function drawPolygon(viewer,positions) {
   // let viewer = this.viewer
   if (positions.length < 2) return
   return viewer.entities.add({
     name: '面几何对象',
     polygon: {
       hierarchy: positions,
       // eslint-disable-next-line new-cap
       material: new Cesium.ColorMaterialProperty(
         Cesium.Color.WHEAT.withAlpha(0.4)
       )
     }
   })
 }

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值