Cesium开发工具篇 | 04量测工具与调试面板

本节我们讲一下Cesium中常用的测量工具和针对开发人员使用的调试工具。

量测工具

量测工具可以说,不管是二维GIS还是三维GIS中都必须具备的功能,只不过是在空间上是否有贴地、是否有高度上的距离差别之分。Cesium是三维GIS引擎,所以距离量测支持直线距离、水平距离、垂直距离以及地表距离,面积量测支持水平面积、地表面积以及模型表面积等。不管是哪种类型的距离测量还是面积测量,实现思路基本是一样的,都是按照如下思路实现的。
1)点击按钮开始测量,侦听鼠标LEFT_CLICK事件,记录坐标,绘制节点和折线(多边形);
2)侦听鼠标移动事件,鼠标点击后即复制一个浮动点,在MOUSE_MOVE事件中不断更新最后一个浮动点,动态更新折线(多边形)绘制;
3)侦听鼠标右击事件,RIGHT_CLICK触发时销毁测量相关事件句柄(ScreenSpaceEventHandler),删除多余的浮动点;
4)折线(多边形)的动态绘制通过CallbackProperty属性绑定positions属性实现。

如下为实现距离量测部分核心代码:

var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
      handler.setInputAction(function (movement) {
        let ray = viewer.camera.getPickRay(movement.position);
        cartesian = viewer.scene.globe.pick(ray, viewer.scene);
        if (positions.length == 0) {
          positions.push(cartesian.clone());
        }
        positions.push(cartesian);
        //在三维场景中添加Label
        var textDisance = distance + "米";
        floatingPoint = viewer.entities.add({
          name: "空间直线距离",
          position: positions[positions.length - 1],
          point: {
            pixelSize: 5,
            color: Cesium.Color.RED,
            outlineColor: Cesium.Color.WHITE,
            outlineWidth: 2,
          },
          label: {
            text: textDisance,
            font: "18px sans-serif",
            fillColor: Cesium.Color.GOLD,
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            outlineWidth: 2,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            pixelOffset: new Cesium.Cartesian2(20, -20),
          },
        });
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

      handler.setInputAction(function (movement) {
        let ray = viewer.camera.getPickRay(movement.endPosition);
        cartesian = viewer.scene.globe.pick(ray, viewer.scene);
        if (positions.length >= 2) {
          if (!Cesium.defined(poly)) {
            poly = new PolyLinePrimitive(positions);
          } else {
            positions.pop();
            positions.push(cartesian);
          }
          distance = getSpaceDistance(positions);
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

      handler.setInputAction(function (movement) {
        handler.destroy(); //关闭事件句柄
        positions.pop(); //最后一个点无效
        // viewer.entities.remove(floatingPoint);
        // tooltip.style.display = "none";
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
      //空间两点距离计算函数
      function getSpaceDistance(positions) {
        var distance = 0;
        for (var i = 0; i < positions.length - 1; i++) {
          var point1cartographic = Cesium.Cartographic.fromCartesian(
            positions[i]
          );
          var point2cartographic = Cesium.Cartographic.fromCartesian(
            positions[i + 1]
          );
          /**根据经纬度计算出距离**/
          var geodesic = new Cesium.EllipsoidGeodesic();
          geodesic.setEndPoints(point1cartographic, point2cartographic);
          var s = geodesic.surfaceDistance;
          //返回两点之间的距离
          s = Math.sqrt(
            Math.pow(s, 2) +
              Math.pow(point2cartographic.height - point1cartographic.height, 2)
          );
          distance = distance + s;
        }
        return distance.toFixed(2);
      }

如下为实现面积测量的部分核心代码:

handler.setInputAction(function (movement) {
        let ray = viewer.camera.getPickRay(movement.position);
        cartesian = viewer.scene.globe.pick(ray, viewer.scene);
        if (positions.length == 0) {
          positions.push(cartesian.clone());
        }
        positions.push(cartesian);
        //在三维场景中添加点
        var cartographic = Cesium.Cartographic.fromCartesian(
          positions[positions.length - 1]
        );
        var longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
        var latitudeString = Cesium.Math.toDegrees(cartographic.latitude);
        var heightString = cartographic.height;
        tempPoints.push({
          lon: longitudeString,
          lat: latitudeString,
          hei: heightString,
        });
        floatingPoint = viewer.entities.add({
          name: "多边形面积",
          position: positions[positions.length - 1],
          point: {
            pixelSize: 5,
            color: Cesium.Color.RED,
            outlineColor: Cesium.Color.WHITE,
            outlineWidth: 2,
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
          },
        });
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
 handler.setInputAction(function (movement) {
        handler.destroy();
        positions.pop();
        var textArea = getArea(tempPoints) + "平方公里";
        viewer.entities.add({
          name: "多边形面积",
          position: positions[positions.length - 1],
          label: {
            text: textArea,
            font: "18px sans-serif",
            fillColor: Cesium.Color.GOLD,
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            outlineWidth: 2,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            pixelOffset: new Cesium.Cartesian2(20, -40),
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
          },
        });
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
      //计算多边形面积
      function 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 = Angle(points[i], points[j], points[k]);

          var dis_temp1 = distance(positions[i], positions[j]);
          var dis_temp2 = distance(positions[j], positions[k]);
          res += dis_temp1 * dis_temp2 * Math.abs(Math.sin(totalAngle));
          console.log(res);
        }
        return (res / 1000000.0).toFixed(4);
      }

完整代码请查看gitHub地址https://github.com/ls870061011/cesium_training/blob/main/examples/3_4_1measure.html,实现的示意图如下所示。

距离测量

面积测量

调试面板

Cesium中比较常用的调试面板是用于了解Cesium渲染效果以及性能调优的CesiumInspector和用于监视3D Tiles数据的监视器Cesium3DTilesInspector。
CesiumInspector
该控件是针对开发人员来说,虽然不能提供功能的实现,但对于了解渲染效果和性能调优是非常有帮助的,特别是解决一些渲染状态下的问题时非常的有价值。使用该控件非常的简单,只需如下一行代码就能实现该控件的加载。

viewer.extend(Cesium.viewerCesiumInspectorMixin);

控件里面有很多的功能,每一个都很专业,包括渲染帧数、Primitive外包围球、Primitive参考框架、线框模式等等,这里就不一一给大家介绍了,感兴趣的同学可以自己尝试一下。

Cesium3DTilesInspector
面对大场景下的大规模、大体量的3D Tiles数据,Cesium提供了一个监视3D Tiles数据的监视器,用于监视、观察3D Tiles数据的效果。加载该空间也非常的简单,只需一行简单代码即可,结果控件展示如下:

viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin);

包括3D Tiles瓦片是否可拾取;显示颜色、线框、瓦片边界范围框、瓦片内容边界范围框、观察者请求体、点云渲染等;还包括一些动态屏幕误差设置、最大屏幕误差设置、样式修改等。对3D Tiles不熟悉的可阅读3D Tiles介绍及加载这篇文章。感兴趣的同学,可以亲自尝试此控件,体验一下控件的强大。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容