• cesium入门示例-测量工具


    作为cesium入门示例级别的最后一篇,参考cesium-长度测量和面积测量实现测量工具封装,修改了其中的距离测量函数,计算贴地距离,并对事件内部处理做了调整。包括贴地距离测量、面积测量、结果清除。

    实现思路(以距离测量为例):

    1、点击按钮开始测量,侦听鼠标LEFT_CLICK事件,记录坐标,绘制节点和折线;

    2、侦听鼠标移动事件,鼠标点击后即复制一个浮动点,在MOUSE_MOVE事件中不断更新最后一个浮动点,动态更新折线绘制;

    3、侦听鼠标右击事件,RIGHT_CLICK触发时销毁测量相关事件句柄(ScreenSpaceEventHandler),删除多余的浮动点;

    4、折线的动态绘制通过CallbackProperty属性绑定positions属性实现。

    封装代码如下:

     1 /*
     2  * params:
     3  *     viewer:required,三维视图
     4  *     target:required,测量工具放置的div的id
     5  * */
     6 
     7 var MeasureTool = (function() {
     8     function _(option) {
     9         this.viewer = option.viewer;
    10         this.dom = document.getElementById(option.target);
    11         this.options = option;
    12 
    13         var me = this;
    14         var btnDistance = document.createElement('button');
    15         btnDistance.innerHTML = '测量距离';
    16         btnDistance.onclick = function() {
    17             if(me.bMeasuring)
    18                 return;
    19 
    20             me.bMeasuring = true;
    21             me._measureLineSpace();
    22         };
    23         this.dom.appendChild(btnDistance);
    24 
    25         var btnArea = document.createElement('button');
    26         btnArea.innerHTML = '测量面积';
    27         btnArea.onclick = function() {
    28             if(me.bMeasuring)
    29                 return;
    30 
    31             me.bMeasuring = true;
    32             me._measureAreaSpace();
    33         };
    34         this.dom.appendChild(btnArea);
    35 
    36         var btnClear = document.createElement('button');
    37         btnClear.innerHTML = '清除结果';
    38         btnClear.onclick = function() {
    39             //删除事先记录的id
    40             for(var jj = 0; jj < me.measureIds.length; jj++) {
    41                 me.viewer.entities.removeById(me.measureIds[jj]);
    42             }
    43             me.measureIds.length = 0;
    44         };
    45         this.dom.appendChild(btnClear);
    46 
    47         this.bMeasuring = false;
    48         this.measureIds = [];
    49     }
    50 
    51     _.prototype._finishMeasure = function() {
    52         this.bMeasuring = false;
    53     }
    54 
    55     //内部测量距离函数
    56     _.prototype._measureLineSpace = function() {}
    57     //内部测量面积函数
    58     _.prototype._measureAreaSpace = function() {}
    59 
    60     return _;
    61 })();

    调用方法:

    1 <div style="position:absolute; 350px;height: 30px; top: 25px; left: 10px;">
    2     <div id="measure"> </div>
    3 </div>
    4 
    5 //创建测量工具
    6 new MeasureTool({
    7     viewer: viewer,
    8     target: 'measure'
    9 })

    计算贴地距离时,对折线按距离或按比例切分成小线段,通过SampleTerrain函数统一获取各点的高度,分段计算空间距离叠加即为贴地距离,因该过程稍费时异步计算后再显示计算结果,测量折线贴地距离的代码如下:

      1     //内部测量距离函数
      2     _.prototype._measureLineSpace = function() {
      3         var me = this;
      4         var viewer = this.viewer;
      5         // 取消双击事件-追踪该位置
      6         viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
      7 
      8         var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene._imageryLayerCollection);
      9         var positions = [];
     10         var poly = null;
     11         var distance = 0;
     12         var cartesian = null;
     13         var floatingPoint;
     14         var labelPt;
     15 
     16         handler.setInputAction(function(movement) {
     17             let ray = viewer.camera.getPickRay(movement.endPosition);
     18             cartesian = viewer.scene.globe.pick(ray, viewer.scene);
     19             if(!Cesium.defined(cartesian)) //跳出地球时异常
     20                 return;
     21             if(positions.length >= 2) {
     22                 if(!Cesium.defined(poly)) {
     23                     poly = new PolyLinePrimitive(positions);
     24                 } else {
     25                     positions.pop();
     26                     positions.push(cartesian);
     27                 }
     28             }
     29         }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
     30 
     31         handler.setInputAction(function(movement) {
     32             let ray = viewer.camera.getPickRay(movement.position);
     33             cartesian = viewer.scene.globe.pick(ray, viewer.scene);
     34             if(!Cesium.defined(cartesian)) //跳出地球时异常
     35                 return;
     36 
     37             if(positions.length == 0) {
     38                 positions.push(cartesian.clone());
     39             }
     40             positions.push(cartesian);
     41             //记录鼠标单击时的节点位置,异步计算贴地距离
     42             labelPt = positions[positions.length - 1];
     43             if(positions.length > 2) {
     44                 getSpaceDistance(positions);
     45             } else if(positions.length == 2) {
     46                 //在三维场景中添加Label
     47                 floatingPoint = viewer.entities.add({
     48                     name: '空间距离',
     49                     position: labelPt,
     50                     point: {
     51                         pixelSize: 5,
     52                         color: Cesium.Color.RED,
     53                         outlineColor: Cesium.Color.WHITE,
     54                         outlineWidth: 2,
     55                     }
     56                 });
     57                 me.measureIds.push(floatingPoint.id);
     58             }
     59 
     60         }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
     61 
     62         handler.setInputAction(function(movement) {
     63             handler.destroy(); //关闭事件句柄
     64             handler = undefined;
     65             positions.pop(); //最后一个点无效
     66             if(positions.length == 1)
     67                 viewer.entities.remove(floatingPoint);
     68             //记录测量工具状态
     69             me._finishMeasure();
     70 
     71         }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
     72 
     73         var PolyLinePrimitive = (function() {
     74             function _(positions) {
     75                 this.options = {
     76                     name: '直线',
     77                     polyline: {
     78                         show: true,
     79                         positions: [],
     80                         material: Cesium.Color.CHARTREUSE,
     81                          5,
     82                         clampToGround: true
     83                     }
     84                 };
     85                 this.positions = positions;
     86                 this._init();
     87             }
     88 
     89             _.prototype._init = function() {
     90                 var _self = this;
     91                 var _update = function() {
     92                     return _self.positions;
     93                 };
     94                 //实时更新polyline.positions
     95                 this.options.polyline.positions = new Cesium.CallbackProperty(_update, false);
     96                 var addedEntity = viewer.entities.add(this.options);
     97                 me.measureIds.push(addedEntity.id);
     98             };
     99 
    100             return _;
    101         })();
    102 
    103         //空间两点距离计算函数
    104         function getSpaceDistance(positions) {
    105             //只计算最后一截,与前面累加
    106             //因move和鼠标左击事件,最后两个点坐标重复
    107             var i = positions.length - 3;
    108             var point1cartographic = Cesium.Cartographic.fromCartesian(positions[i]);
    109             var point2cartographic = Cesium.Cartographic.fromCartesian(positions[i + 1]);
    110             getTerrainDistance(point1cartographic, point2cartographic);
    111         }
    112 
    113         function getTerrainDistance(point1cartographic, point2cartographic) {
    114             var geodesic = new Cesium.EllipsoidGeodesic();
    115             geodesic.setEndPoints(point1cartographic, point2cartographic);
    116             var s = geodesic.surfaceDistance;
    117             var cartoPts = [point1cartographic];
    118             for(var jj = 1000; jj < s; jj += 1000) {  //分段采样计算距离
    119                 var cartoPt = geodesic.interpolateUsingSurfaceDistance(jj);
    120                 //                console.log(cartoPt);
    121                 cartoPts.push(cartoPt);
    122             }
    123             cartoPts.push(point2cartographic);
    124             //返回两点之间的距离
    125             var promise = Cesium.sampleTerrain(viewer.terrainProvider, 8, cartoPts);
    126             Cesium.when(promise, function(updatedPositions) {
    127                 // positions height have been updated.
    128                 // updatedPositions is just a reference to positions.
    129                 for(var jj = 0; jj < updatedPositions.length - 1; jj++) {
    130                     var geoD = new Cesium.EllipsoidGeodesic();
    131                     geoD.setEndPoints(updatedPositions[jj], updatedPositions[jj + 1]);
    132                     var innerS = geoD.surfaceDistance;
    133                     innerS = Math.sqrt(Math.pow(innerS, 2) + Math.pow(updatedPositions[jj + 1].height - updatedPositions[jj].height, 2));
    134                     distance += innerS;
    135                 }
    136 
    137                 //在三维场景中添加Label
    138                 var textDisance = distance.toFixed(2) + "米";
    139                 if(distance > 10000)
    140                     textDisance = (distance / 1000.0).toFixed(2) + "千米";
    141                 floatingPoint = viewer.entities.add({
    142                     name: '贴地距离',
    143                     position: labelPt,
    144                     point: {
    145                         pixelSize: 5,
    146                         color: Cesium.Color.RED,
    147                         outlineColor: Cesium.Color.WHITE,
    148                         outlineWidth: 2,
    149                     },
    150                     label: {
    151                         text: textDisance,
    152                         font: '18px sans-serif',
    153                         fillColor: Cesium.Color.GOLD,
    154                         style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    155                         outlineWidth: 2,
    156                         verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    157                         pixelOffset: new Cesium.Cartesian2(20, -20),
    158                     }
    159                 });
    160                 me.measureIds.push(floatingPoint.id);
    161             });
    162         }
    163 
    164     }

    测量面积实现方式与折线类似,可参考cesium-长度测量和面积测量自行实现,无需计算贴地距离。细节处还可优化。

     最后实现的效果如下:

  • 相关阅读:
    第六课样式表
    jsp传递参数的四种方法
    Data truncated for column 'Sex' at row 1
    写方法时try,catch 的好处
    访问报错The origin server did not find a current representation for the target resou
    tomcat启动报错Failed to start component [StandardEngine[Catalina].StandardHost[localhost].
    Win10鼠标右键如何添加快捷关机、注销等功能?
    idea tomcat部署
    html如何将图片盖住整个网页
    如果要在标签中显示"<"或者">"等特殊字符,可以使用“&”开头,“;”结尾,中间加上字符对应的编码就可以啦。
  • 原文地址:https://www.cnblogs.com/HandyLi/p/11125326.html
Copyright © 2020-2023  润新知