cesium之地图贴地量算工具效果篇

本篇实现cesium地图量算工具功能,效果图如下:

实现的思路如下:

1.初始化工具函数:

//量算工具
var html='<div id="toolTip" class="measure-mouse-tip" style="display:none;color:rgb(236, 159, 30);border: 1px solid rgb(236, 159, 30);position:absolute;font-size:12px;color:#fff">单击开始,双击结束</div>';
$('.cesium-viewer').append(html);
$("#measureDistance").click(function(){
            new measureDistance(cesium);
});
$("#measureArea").click(function(){
            new measureArea(cesium);
});

2.核心函数:

(1)测距:

//测量距离
var measureDistance=function(cesium){
  ……
    	handler.setInputAction(function(movement) {
            var position1;
            var cartographic;
            var ray = cesium.cesiumViewer.scene.camera.getPickRay(movement.endPosition);
            if(ray)
               position1 = cesium.cesiumViewer.scene.globe.pick(ray,cesium.cesiumViewer.scene);
            if(position1)
               cartographic= Cesium.Ellipsoid.WGS84.cartesianToCartographic(position1);
            if(cartographic) {
                //海拔
                var height = cesium.cesiumViewer.scene.globe.getHeight(cartographic);
                //地理坐标(弧度)转经纬度坐标
                var point = Cesium.Cartesian3.fromDegrees(cartographic.longitude / Math.PI * 180, cartographic.latitude / Math.PI * 180, height);
                if (isDraw) {
                    tooltip.style.left = movement.endPosition.x + 10 + "px";
                    tooltip.style.top = movement.endPosition.y + 20 + "px";
                    tooltip.style.display = "block";
                    if (polylinePath.length < 1) {
                        return;
                    }
                    if (!Cesium.defined(polyline)) {
                        polylinePath.push(point);
                        polyline = new CreatePolyline(polylinePath,cesium);
                    } else {
                        polyline.path.pop();
                        polyline.path.push(point);
                    }
                    if(polylinePath.length>=1){
                        if(polyline && polyline.path){
                            var distance=getDistance(polyline.path);
                            tooltip.innerHTML='<p>长度:'+distance+'</p><p>双击确定终点</p>';
                        }
                    }
                }
            }

        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        handler.setInputAction(function(movement) {
            var position1;
            var cartographic;
            var ray = cesium.cesiumViewer.scene.camera.getPickRay(movement.position);
            if(ray)
                position1 = cesium.cesiumViewer.scene.globe.pick(ray,cesium.cesiumViewer.scene);
            if(position1)
                cartographic= Cesium.Ellipsoid.WGS84.cartesianToCartographic(position1);
            //世界坐标转地理坐标(弧度)
            //var cartographic = cesium.cesiumViewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian);
            if(cartographic){
                //海拔
                var height = cesium.cesiumViewer.scene.globe.getHeight(cartographic);
                //地理坐标(弧度)转经纬度坐标
                var point = Cesium.Cartesian3.fromDegrees(cartographic.longitude / Math.PI * 180,cartographic.latitude / Math.PI * 180,height);
               // var point = Cesium.Cartesian3.fromDegrees(currentLon,currentLat,height);
                if (isDraw) {
                    //polylinePath.push(cartographic);
                    //polylinePath.push(point);
                    if(polyline)
                       polyline.path.pop();
                    SurfaceLine(cartographic);
                    var text="起点";
                    if(polyline){
                        text=getDistance(polyline.path);
                    }
                    entities.push(cesium.cesiumViewer.entities.add({
                        position: point,
                        point: {
                            heightReference:Cesium.HeightReference.CLAMP_TO_GROUND,
                            show: true,
                            color: Cesium.Color.SKYBLUE,
                            pixelSize: 3,
                            outlineColor: Cesium.Color.YELLOW,
                            outlineWidth: 1
                        },
                        label: {
                            text: text,
                            font: '12px sans-serif',
                            style : Cesium.LabelStyle.FILL,
                            outlineWidth : 1,
                            fillColor:Cesium.Color.WHITE,
                            showBackground:false,
                            backgroundColor:Cesium.Color.ORANGE.withAlpha(0.6),
                            horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
                            pixelOffset: new Cesium.Cartesian2(5.0,-20.0),
                        }
                    }));
                }
            }

        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
        handler.setInputAction(function() {
        	handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
            handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
            //handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
        	//cesium.cesiumViewer.zoomTo(polyline.lineEntity);
            cesium.cesiumViewer.trackedEntity = undefined;
            isDraw = false;
            //cesium.cesiumViewer.scene.globe.depthTestAgainstTerrain = false;
            billboard=billboards.add({
            	show : true,
                id:"measureTool",
                position : polylinePath[polylinePath.length-1],
                pixelOffset : new Cesium.Cartesian2(0.0, 20),
                eyeOffset : new Cesium.Cartesian3(0.0, 0.0, 0.0),
                horizontalOrigin : Cesium.HorizontalOrigin.CENTER,
                verticalOrigin : Cesium.VerticalOrigin.CENTER,
                scale : 1.0,
                image: GLOBAL.domainResource+'/systems/common-bx-gis/models/cesium/images/close.png',
                color : new Cesium.Color(1.0, 1.0, 1.0, 1.0),
            });
            
            tooltip.style.display = "none";
          //关闭按钮执行事件
            handler.setInputAction(function(movement){
            	var pickedObjects ={};
            	pickedObjects=scene.drillPick(movement.position);
                if (Cesium.defined(pickedObjects)) {
                    for (var i = 0; i < pickedObjects.length; i++)
                        if (pickedObjects[i].primitive == billboard){
                        	cesium.cesiumViewer.entities.remove(polyline.lineEntity);
                        	for(var j=0;j<entities.length;j++){
                        		cesium.cesiumViewer.entities.remove(entities[j]);
                        	}
                        	entities=[];
                        	billboards.remove(billboard);
                        	polylinePath = [];
                            polyline = undefined;
                            handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
                        }
                }
            },Cesium.ScreenSpaceEventType.LEFT_CLICK);
            
        }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

  ……
}

(2)测面:

//测量面积
var measureArea=function(cesium){
……
    handler.setInputAction(function(movement) {
        //var cartesian = cesium.cesiumViewer.camera.pickEllipsoid(movement.endPosition, ellipsoid);
        //新增部分
        var position1;
        var cartographic;
        var ray = cesium.cesiumViewer.scene.camera.getPickRay(movement.endPosition);
        if(ray)
            position1 = cesium.cesiumViewer.scene.globe.pick(ray,cesium.cesiumViewer.scene);
        if(position1)
            cartographic= Cesium.Ellipsoid.WGS84.cartesianToCartographic(position1);
        if(cartographic){
            //海拔
            var height = cesium.cesiumViewer.scene.globe.getHeight(cartographic);
            var point = Cesium.Cartesian3.fromDegrees(cartographic.longitude / Math.PI * 180,cartographic.latitude / Math.PI * 180,height);
            if (isDraw) {
                tooltip.style.left = movement.endPosition.x + 10 + "px";
                tooltip.style.top = movement.endPosition.y + 20 + "px";
                tooltip.style.display = "block";

                if (polygonPath.length < 2) {
                    return;
                }
                if (!Cesium.defined(polygon)) {
                    polygonPath.push(point);
                    polygon = new CreatePolygon(polygonPath,cesium);
                } else {
                    polygon.path.pop();
                    polygon.path.push(point);
                }
                if(polygonPath.length>=2){
                    var label = String(countAreaInCartesian3(polygon.path));
                    label = label.substr(0, label.indexOf(".", 0));
                    var text;
                    if (label.length < 6)
                        text = label + "平方米";
                    else {
                        label = String(label / 1000000);
                        label = label.substr(0, label.indexOf(".", 0) + 3);
                        text = label + "平方公里"
                    }
                    measureDisplayLabel.text=text;
                    measureDisplayLabel.position = countCenter(polygon.path);
                    tooltip.innerHTML='<p>双击确定终点</p>';
                }
            }
        }

    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    handler.setInputAction(function(movement) {
        //var cartesian = cesium.cesiumViewer.camera.pickEllipsoid(movement.position, ellipsoid);
        //新增部分
        //cesium.cesiumViewer.scene.globe.depthTestAgainstTerrain = true;
        var position1;
        var cartographic;
        var ray = cesium.cesiumViewer.scene.camera.getPickRay(movement.position);
        if(ray)
            position1 = cesium.cesiumViewer.scene.globe.pick(ray,cesium.cesiumViewer.scene);
        if(position1)
            cartographic= Cesium.Ellipsoid.WGS84.cartesianToCartographic(position1);
        if(cartographic){
            //海拔
            var height = cesium.cesiumViewer.scene.globe.getHeight(cartographic);
            var point = Cesium.Cartesian3.fromDegrees(cartographic.longitude / Math.PI * 180,cartographic.latitude / Math.PI * 180,height);
            if (isDraw) {
                polygonPath.push(point);
                entities.push(cesium.cesiumViewer.entities.add({
                    position: point,
                    point: {
                        show: true,
                        color: Cesium.Color.SKYBLUE,
                        pixelSize: 3,
                        outlineColor: Cesium.Color.YELLOW,
                        outlineWidth: 1
                    },
                }));
            }
        }
        //cesium.cesiumViewer.scene.globe.depthTestAgainstTerrain = false;

    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    handler.setInputAction(function() {
    	handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
        handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
    	//cesium.cesiumViewer.zoomTo(polygon.polygonEntity);
        //cesium.cesiumViewer.flyTo(polygon.polygonEntity);
        cesium.cesiumViewer.trackedEntity = undefined;
        isDraw = false;
    	billboard=billboards.add({
        	show : true,
            id:"measureTool",
            position : polygonPath[polygonPath.length-1],
            pixelOffset : new Cesium.Cartesian2(0.0, 20),
            eyeOffset : new Cesium.Cartesian3(0.0, 0.0, 0.0),
            horizontalOrigin : Cesium.HorizontalOrigin.CENTER,
            verticalOrigin : Cesium.VerticalOrigin.CENTER,
            scale : 1.0,
            image: GLOBAL.domainResource+'/systems/common-bx-gis/models/cesium/images/close.png',
            color : new Cesium.Color(1.0, 1.0, 1.0, 1.0),
        });
    	//关闭按钮执行事件
        handler.setInputAction(function(movement){
        	var pickedObjects ={};
        	pickedObjects=scene.drillPick(movement.position);
            if (Cesium.defined(pickedObjects)) {
                for (var i = 0; i < pickedObjects.length; i++)
                    if (pickedObjects[i].primitive == billboard){
                    	cesium.cesiumViewer.entities.remove(polygon.polygonEntity);
                    	for(var j=0;j<entities.length;j++){
                    		cesium.cesiumViewer.entities.remove(entities[j]);
                    	}
                    	entities=[];
                    	billboards.remove(billboard);
                    	tempLabelCollection.remove(measureDisplayLabel);
                    	polygonPath = [];
                        polygon = undefined;
                        handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
                    }
            }
        },Cesium.ScreenSpaceEventType.LEFT_CLICK);
        tooltip.style.display='none';
    }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
……
}

 

作者: GIS之家

GIS之家微信号:gishome;GIS之家拥有自己的GIS开发团队,均是高校GIS研究生,具备丰富的webgis开发项目工作经验,专注以及热爱研究webgis技术的团队

《cesium之地图贴地量算工具效果篇》有10个想法

    1. 博客贴出来的是部分核心代码,没有完整公开出来的;isDraw只是个判断标识,ture或者false的

  1. 请问一下你们的算法是具体到地形表面积的算法吗,还是说只是一个计算’加上弧度的几何面积’的算法

    1. 这几个函数没公开呢,countAreaInCartesian3函数的算面积,核心是这样的:
      var countArea=function(ps) {
      var s = 0;
      for (var i = 0; i < ps.length; i++) { var p1 = ps[i]; var p2; if (i < ps.length - 1) p2 = ps[i + 1]; else p2 = ps[0]; s += p1.x * p2.y - p2.x * p1.y } return s / 2 }

      1. 谢谢。距离测量为什么不直接用 Cesium.EllipsoidGeodesic().surfaceDistance呢?能否简单说一下CreatePolygon()函数用到了什么

        1. CreatePolygon函数不是绘制多边形嘛,构造就行了:
          function _(positons,cesium) {
          if (!Cesium.defined(positons)) {
          throw new Cesium.DeveloperError(‘positions is required!’);
          }
          if (positons.length < 3) { throw new Cesium.DeveloperError('positions 的长度必须大于等于3'); } this.options = { polygon : { show : true, hierarchy : undefined, outline:true, outlineColor:Cesium.Color.WHITE, outlineWidth:2, material : Cesium.Color.YELLOW.withAlpha(0.4) } }; this.path = positons; this._init(cesium); } 测距量算方法很多,不一定用我这种

发表评论

电子邮件地址不会被公开。