Cesium调试技巧

1,108 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情


起因

感觉每次想要去debugger的时候都得查文档,感觉很麻烦,干脆归纳一些到目前为止个人使用较多的一些Cesium查错技巧,方便以后回顾

3dTiles

属性查询

针对3dTiles的封装,其实Cesium已经封装得很齐全了,直接调用即可

viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin);

如下图所示 img 右侧则是启用了该扩展后会出现的面板,在该面板上,可以拾取到3dTiles中每一个的tile,只要初始化的时候infoBox为true(默认为true),那么点击的时候也会默认查出该tiles内部中所有的属性,并显示在列表中(在项目中,如果要快速查到3dTiles中的属性,这个方法会很管用也很便捷,省去了创建左键监听,遍历feature中所有属性的这个过程)

const viewer = new Cesium.Viewer("cesiumContainer", {
  infoBox: true,//增加属性弹窗
});

img

查看数据包围体、线框模式等等

查看3dTiles的这些数据也都是直接调用这句代码中的Display

viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin);

img

当然cesium还封装了好多,具体其他的读者可以自行探索,但常用的一般都是那几个

绘制

在项目中一般都需要绘制,但是一般来说都是绘制一整块的,但是其中有时候会需要确认自己的传参有没有问题,例如做点光源、聚光灯的时候,要模拟这个点的位置,确保位置正确,或者说有些BUG需要确认点、线、面的位置,这个时候就需要一个方法来尽快的进行绘制,来查看自己画的对不对。

PS: 这个时候只是为了求快,就别在意性能了,只是为了快速绘制(所以这里都是用Entity绘制,Entity绘制Cesium封装过,所以更快)

绘制点

这里补充一点关于点的高度相对的知识
heightReference默认是为Cesium.HeightReference.NONE,也就是绝对高程。

heightReference为Cesium.HeightReference.CLAMP_TO_GROUND---可使点贴地 Cesium.HeightReference.RELATIVE_TO_GROUND----是设置距离地形的相对高度

初始化三维球时不指定其他地形的话等同于viewer.terrainProvider=new Cesium.EllipsoidTerrainProvider(),该地形构建了球的基本骨架,各处高度全为0。

如果设置了Cesium.HeightReference.NONE,就得留意点的高度了,如果高度低于该位置地形的高度,点将位于地下,这个时候如果没有设置深度检测,即viewer.scene.globe.depthTestAgainstTerrain = true,那么当移动摄像机的时候,点的位置就会发生偏移。

点不像面一样可以真正地贴地,除非设置了绝对高度或者开启深度检测,否侧移动摄像机点是无法固定的。Cesium的地形是异步请求的,因此一般通过鼠标点击地球上的位置获取高层,否则地形可能还没加载完,获取的高程就不准了。

viewer.entities.add({
    name: "点几何对象",
    position: Cesium.Cartesian3.fromDegrees(lat, lon, height),
    point: {
      color: Cesium.Color.SKYBLUE,
      pixelSize: 10,
      outlineColor: Cesium.Color.YELLOW,
      outlineWidth: 3,
      //disableDepthTestDistance: Number.POSITIVE_INFINITY,
      //heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
    },
  });

绘制线

这里需要留意的点是,传给线的点的方法,若一系列的点中存在高程数据,则使用Cesium.Cartesian3.fromDegreesArrayHeights;若一系列点中不存在高程数据则直接使用Cesium.Cartesian3.fromDegreesArray即可。

viewer.entities.add({
        name: "polyline",
        polyline: {
            show: true, //是否显示,默认显示
            positions: Cesium.Cartesian3.fromDegreesArrayHeights([
                70, 40, 600000, 
                75, 30, 400000,
                120, 25, 200000
            ]),
            width: 2, //线的宽度(像素),默认为1
            granularity: Cesium.Math.RADIANS_PER_DEGREE,
            material: Cesium.Color.BLUE, //线的颜色,默认为白色
            // depthFailMaterial: Cesium.Color.RED, //线被遮挡部分的颜色,默认为空(不显示被遮挡的部分),设置后可显示被遮挡的部分
            arcType: Cesium.ArcType.NONE, //线的地理类型,NONE表示纯直线,GEODESIC表示为测地线,RHUMB表示等角航线,默认为测地线
            // arcType: Cesium.ArcType.GEODESIC,
            // arcType: Cesium.ArcType.RHUMB,
            clampToGround: false, //是否贴地,默认为否
            shadows: Cesium.ShadowMode.DISABLED, //是否显示光照阴影,默认为否
            // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(100.0, 2000000.0), //显示的视角距离条件,在该范围内显示,范围不显示,默认为空
            classificationType: Cesium.ClassificationType.BOTH,
            zIndex: 0, //显示深度,越大表示图层在上
        }
    })

绘制面

viewer.entities.add({
        name: "绘制面",
        polygon: {
            show: true,
            hierarchy: Cesium.Cartesian3.fromDegreesArray([
                110.0,
                30.0,
                120.0,
                30.0,
                115.0,
                40.0,
            ]),
            height: 100000,
            material: Cesium.Color.CYAN.withAlpha(0.5),
            outline: true,
            outlineColor: Cesium.Color.BLACK,
        }
    })

绘制矩形

前几天加载WMS到Cesium中的时候,获取的范围一直有问题,只能绘制出来看看实际范围对不对了

viewer.entities.add({
        name: '绘制矩阵',
        rectangle: {
            coordinates: Cesium.Rectangle.fromDegrees(west, south, east, north, result),
            material: Cesium.Color.WHITE.withAlpha(0.5),
        }
    })

相机

这个做离屏渲染的时候,一般还需要多绘制一个相机的,获取这个相机的相应信息,但是你得保证你获取的相机的位置是否正确,这时候就需要把相机的视锥体绘制出来

// 绘制视锥
function updateFrustumOutline(camera) {
  const scratchRight = new Cesium.Cartesian3();
  const scratchRotation = new Cesium.Matrix3();
  const scratchOrientation = new Cesium.Quaternion();
  const position = camera.positionWC;
  const direction = camera.directionWC;
  const up = camera.upWC;
  const left = Cesium.Cartesian3.negate(camera.rightWC, scratchRight);
  Cesium.Matrix3.setColumn(scratchRotation, 0, left, scratchRotation);
  Cesium.Matrix3.setColumn(scratchRotation, 1, up, scratchRotation);
  Cesium.Matrix3.setColumn(
    scratchRotation,
    2,
    direction,
    scratchRotation
  );
  const orientation = Cesium.Quaternion.fromRotationMatrix(
    scratchRotation,
    scratchOrientation
  );

  const instance = new Cesium.GeometryInstance({
    geometry: new Cesium.FrustumOutlineGeometry({
      frustum: camera.frustum,
      origin: position,
      orientation: orientation,
    }),
    attributes: {
      color: Cesium.ColorGeometryInstanceAttribute.fromColor(
        Cesium.Color.WHITE
      ),
    },
  });

  viewer.scene.primitives.add(
    new Cesium.Primitive({
      geometryInstances: instance,
      appearance: new Cesium.PerInstanceColorAppearance({
        flat: true,
        translucent: false,
      }),
      asynchronous: false,
    })
  );
}