Cesium(九) 角度量算工具 (一)

之前在用超图的进行现在开发,现在用原生的Cesium之后发现量算工具还是个小麻烦。。。关于距离,面积,高度网上都有例子了,但是现在有个角度测量的需求,就自己写了一下。这个是在正北方向做一条辅助线,然后求与正北方向的夹角,过几天做自己画两条线夹角的。

———tool工具类:
———— graphic.js

效果图:
在这里插入图片描述

const radiansPerDegree = Math.PI / 180.0;//角度转化为弧度(rad) 
const degreesPerRadian = 180.0 / Math.PI;//弧度转化为角度
const color=Cesium.Color.fromCssColorString('rgba(247,224,32,0.6)')
const pointStyle={
    pixelSize: 8,
    color:color
}
const labelStyle={
    font: '36px sans-serif',
    fillColor: Cesium.Color.WHITE,
    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    // outlineWidth: 2,
    showBackground:true,
    scale:0.5,
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    pixelOffset: new Cesium.Cartesian2(20, -20),
    heightReference: Cesium.HeightReference.NONE
}
const AngleGraphic=(function(){
        function _(viewer,options){
            this.viewer = viewer
            viewer.scene.postProcessStages.fxaa.enabled = false;
            this.options = {
                polyline: options
            }
            this.positions = options.positions || [];
            this.entity = this._init();
            this.idDestroyed=false
            this._depthTestAgainstTerrain=this.viewer.scene.globe.depthTestAgainstTerrain,
            this.nodes=[]
        }
        _.prototype._init = function () {
            this.viewer.scene.globe.depthTestAgainstTerrain=true
            const _self = this;
            const _update = function () {
                return _self.positions;
            };
            //实时更新polyline.positions
            this.options.polyline.positions = new Cesium.CallbackProperty(_update, false);
            const entity = this.viewer.entities.add(this.options);
            return entity
        }
        _.prototype.remove = function () {
            this.viewer.entities.remove(this.entity)
            if(this.tmpPolyline){
                this.viewer.entities.remove(this.tmpPolyline)
            }
            for(let p of this.nodes){
                this.viewer.entities.remove(p)
            }
        }
        _.prototype.pushNode=function(cartesian){
            this.positions.push(cartesian)
            const p=this.viewer.entities.add({
                position:cartesian,
                point:pointStyle
            })
            this.nodes.push(p)
        }
        _.prototype.popNode=function(){
            this.positions.pop()
            const p=this.nodes.pop()
            this.viewer.entities.remove(p)
        }
        _.prototype.destroy=function(){
            this.options={}
            this.positions=[]
            this.entity=undefined
            this.viewer=undefined
            this.idDestroyed=true
            this.tmpPolyline=undefined
        }
        _.prototype.stopEdit=function(){
            this.viewer.scene.globe.depthTestAgainstTerrain=this._depthTestAgainstTerrain
            this.options.label = this.createLabel()
            this.options.polyline.positions=this.positions
            this.options.position=this.positions[this.positions.length-1]
            this.remove()
            this.tmpPolyline=this.createAssitGraphic()        
            this.entity=this.viewer.entities.add(this.options)
        }
        /**
         * 创建辅助线
         */
        _.prototype.createAssitGraphic=function(){
            if(this.positions.length!==2){
                return
            }
            const startC=Cesium.Cartographic.fromCartesian(this.positions[0])
            console.log(startC);
            const distance = this.getDistance();
            console.log(distance);//单位m
            
            // const endC=Cesium.Cartographic.fromCartesian(this.positions[1])
            const tmp=Cesium.Cartesian3.fromRadians(
                startC.longitude,
                startC.latitude+distance/111000*radiansPerDegree,
                startC.height
            )
            const pts=[this.positions[0],tmp]
            return this.viewer.entities.add({
                polyline:{
                    positions:pts,
                    material:new Cesium.PolylineDashMaterialProperty({color:color}),
                    width:10
                }
            })
    
        }
        _.prototype.getDistance = function () {
            let distance = 0;
            const positions = this.positions
            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;
                //console.log(Math.sqrt(Math.pow(distance, 2) + Math.pow(endheight, 2)));
                //返回两点之间的距离
                s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2));
                distance = distance + s;
            }
            return distance.toFixed(2);
        }
        _.prototype.createLabel = function () {
            const label = labelStyle
            label.text='角度'+this.getAngle().toFixed(2)+'°'
            +'长度'+this.getDistance()+'米'
            return label
        }
        _.prototype.getAngle=function(){
            if(this.positions.length!==2){
                return 'Nan'
            }
            const startC=Cesium.Cartographic.fromCartesian(this.positions[0])
            const endC=Cesium.Cartographic.fromCartesian(this.positions[1])
            const distance = this.getDistance();
            
            if(startC&&endC){
                const l = parseFloat(this.getDistance())//边长
                const topPoint=Cesium.Cartesian3.fromRadians(//北上点的Cartesian3
                    Cesium.Cartographic.fromCartesian(this.positions[0]).longitude,
                    Cesium.Cartographic.fromCartesian(this.positions[0]).latitude+distance/111000*radiansPerDegree,
                    Cesium.Cartographic.fromCartesian(this.positions[0]).height
                )
                const newPoint =Cesium.Cartesian3.fromRadians(
                    Cesium.Cartographic.fromCartesian(this.positions[1]).longitude,
                    Cesium.Cartographic.fromCartesian(this.positions[1]).latitude,
                    Cesium.Cartographic.fromCartesian(this.positions[1]).height
                )
                const d = Cesium.Cartesian3.distance(topPoint,newPoint);
                console.log(Math.acos((2*l*l-d*d)/(2*l*l)))
                console.log(l)
                console.log(d)
                return Cesium.Cartographic.fromCartesian(this.positions[1]).longitude>Cesium.Cartographic.fromCartesian(this.positions[0]).longitude?
                Math.acos((2*l*l-d*d)/(2*l*l))*degreesPerRadian:-Math.acos((2*l*l-d*d)/(2*l*l))*degreesPerRadian
            }else{
                return 'NaN'
            }
        }
        return _
})();
export AngleGraphic 

调用方法
这里只附带了部分方法,其他的可以看这个博主的:
github地址

toggleClick(mode) {
      if(!viewer){
        this.init(window.viewer)
      }
      this.mode=mode
      if (window.graphicManager) {
        this.stopDraw();
        return;
      }
      this.tipVisible(true);
      this.curMeasureStatus = "结束测量";
      const color = Cesium.Color.fromCssColorString("rgba(247,224,32,1)");
      window.graphicManager = new AngleGraphic(viewer, {
            positions: this.positions,
            material: color,
            width: 3
          });
      this.updateTipText("请单击地图确定起点.");
}
init(cesiumViewer) {
      const self = this;
      viewer=cesiumViewer;
      console.log(viewer);
      const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
      const tooltip = this.createTip();
      this.tipVisible(false);
      handler.setInputAction(e => {
        if (!Cesium.defined(window.graphicManager)) {
          return;
        }
        const pixel = e.position;
        const ray = viewer.camera.getPickRay(pixel);
        const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
        //高度和角度只需要一条线段
        if (self.mode === "height"||self.mode === "angle") {
        ......
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值