cesium(四)3D Tiles

361 阅读2分钟

1. 前言

3D Tiles 常用于城市规划、建筑设计和基础设施管理,可以直观地展示城市的三维模型。通过加载和渲染大规模三维场景,支持VR和AR应用的开发。在GIS中,3D Tiles可用于展示地形和其他地理数据,增强空间分析和可视化能力。

先看下官网给出的案例效果图,能更直观的了解3D Tile的作用。

image.png

2. 使用Cesium3DTileset

Cesium ionAsset Depot中找到纽约3D Tile,添加到My Assets中。 image.png

在项目中添加代码。

const tileset = viewer.scene.primitives.add(
  await Cesium.Cesium3DTileset.fromIonAssetId(75343),
);

由于是纽约的建筑效果原型,则需要定位到纽约去观察效果。

  viewer.zoomTo(tileset);

该方法用于将相机平滑地移动到指定的 3D Tiles 数据集(tileset)的边界,使其完全可见。这是一个非常方便的功能,可以帮助用户快速聚焦于特定的 3D 模型或场景。

我们来看下效果:

image.png

嗯,不咋地,与期望的第一个图的视角有偏差。这里八青妹给出自己的视角值,仅供参考:

 let initialPosition = Cesium.Cartesian3.fromDegrees(
    -74.01881302800248,
    40.69114333714821,
    1200
  );

  viewer.camera.setView({
    destination: initialPosition,
    orientation: {
      // 水平方向的角度,以弧度表示
      heading: Cesium.Math.toRadians(20.0),
      // 垂直方向的角度,以弧度表示
      pitch: Cesium.Math.toRadians(-30.0),
    },
  });

image.png

3. 定义3D Tiles数据集的样式

通过Cesium.Cesium3DTileStyle(style)来设置样式,通过样式折纸来修改颜色、透明度、可见性等。主要可设置的属性:

  • color:用于设置单个模型或多个模型的颜色,可以使用表达式。
  • show:控制模型的可见性。

示例:

  tileset.style = new Cesium.Cesium3DTileStyle({
    color: {
      conditions: [
        ["${Height} >= 100", 'color("purple", 0.5)'],
        ["${Height} >= 50", 'color("red")'],
        ["true", 'color("blue")'],
      ],
    },
    show: "${Height} > 10",
  });

这里颜色显示的条件是,建筑物高度大于等于100的时候,显示透明度0.5的紫色;高度在大于等于50并小于100的时候显示红色,其他情况下显示蓝色;建筑物高度大于10的才显示。

image.png

这里给出最上面示例图的颜色参考值,颜色按照此配置,就可以得到接近效果图的颜色。

color: {
      conditions: [
        ["${Height} >= 300", "rgba(45, 0, 75, 0.5)"],
        ["${Height} >= 200", "rgb(102, 71, 151)"],
        ["${Height} >= 100", "rgb(170, 162, 204)"],
        ["${Height} >= 50", "rgb(224, 226, 238)"],
        ["${Height} >= 25", "rgb(252, 230, 200)"],
        ["${Height} >= 10", "rgb(248, 176, 87)"],
        ["${Height} >= 5", "rgb(198, 106, 11)"],
        ["true", "rgb(127, 59, 8)"],
      ],
    },

当然,在控制是否显示的属性当中,也可以用表达式去写,例如:

 show: {
      conditions: [
        ["${Height} >= 200", "true"],
        ["${Height} >= 25", "false"],
        ["true", "true"],
      ],
    },

通过该表达式,可以显示的建筑为高度小于25的和高度大于200。

4. 调整偏移高度

建筑物没有正确的定位在地平面上,看起来有偏差,例如下图所示的柯林顿城堡,没有贴合上。

image.png

😖处女座忍不了一点。但是这题是有解的,我们可以通过修改模型矩阵modelMatrix来调整tileset的位置。

  const heightOffset = 30;
  await tileset.readyPromise;
  // Position tileset
  const boundingSphere = tileset.boundingSphere;
  const cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center);
  const surface = Cesium.Cartesian3.fromRadians(
    cartographic.longitude,
    cartographic.latitude,
    0.0
  );
  const offset = Cesium.Cartesian3.fromRadians(
    cartographic.longitude,
    cartographic.latitude,
    heightOffset
  );
  const translation = Cesium.Cartesian3.subtract(
    offset,
    surface,
    new Cesium.Cartesian3()
  );
  tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);

八青妹这里设置的偏移量是30,依据不同的3D Tile可调试设置。这里的效果如下:

image.png

嗯,舒服了。