使用Cesium加载3DTiles数据—以香港三维实景模型为例

2,149 阅读3分钟

前言

最近在研究Cesium,首先就需要有个可以加载的三维模型。发现香港提供了可下载的三维实景模型,故下载后加载到Cesium中。现将这个过程分享一下,最后有几个疑问也想请看到的友友解答一下。

一、获取模型

下载链接是:Planning Department Hong Kong 3D Photo-realistic Model 規劃署 香港三維實景模型 规划署 香港三维实景模型 (pland.gov.hk)

如图所示:

image.png 因为要加载到Cesium中,选择了3D Tiles,在左侧点击想要的窗格,最多可以选择六个,然后点击download,后发现报错,错误原因见下图,该ppgis的域名失效了。

image.png 后来找到一个可以正确下载的链接,具体见文档: 以https://pdmap.pland.gov.hk/PLANDWEB/public/3d_photo_realistic_models/cesium/tile_20_27_CESIUM.zip为例,只要对照上面下载链接中窗口的序号,将上面的20、27替换成想要序号的就可以下载了。这里可以借用下面简单的脚本简化下载过程,在开发者工具中运行即可

function downloadFile (url, fileName) {
      const link = document.createElement('a')
      link.href = url
      link.download = fileName
      link.target = "_blank" // 可选,如果希望在新窗口中下载文件,请取消注释此行
      link.click()
    }
    async function fn () {
      let arri = [21,22,23], arrj = [24,25,26,27]
      for (let i = 0; i < arri.length; i++) {
        for (let j = 0; j < arrj.length; j++) {
          let url = `https://pdmap.pland.gov.hk/PLANDWEB/public/3d_photo_realistic_models/cesium/tile_${arri[i]}_${arrj[j]}_CESIUM.zip`
          await downloadFile(url, `tile_${arri[i]}_${arrj[j]}_CESIUM.zip`)
        }
      }
    }
    fn();

二、加载模型

我是在Vue中使用Cesium,将解压后的3DTiles文件放入public中

image.png

通过以下代码加载模型

    // 初始化Cesium
    this.initMap();
    // 加载3dTiles
    let arri = [21, 22, 23, 24, 25, 26, 27, 28], arrj = [24, 25, 26, 27]
    for (let i = 0; i < arri.length; i++) {
      for (let j = 0; j < arrj.length; j++) {
        let url = `/nine/tile_${arri[i]}_${arrj[j]}_CESIUM/tileset.json`  // 这个就是public中的模型地址
        this.add3DTiles(url);
      }
    }
    
    initMap () {
      this.viewer = new Cesium.Viewer('cesiumContainer', {
        infoBox: false,
        animation: false,    //左下角的动画仪表盘。这个仪表盘实在太大,并不怎么好看。
        baseLayerPicker: false,  //右上角的图层选择按钮
        geocoder: false,  //搜索框
        homeButton: false,  //home按钮
        sceneModePicker: false, //模式切换按钮
        timeline: false,    //底部的时间轴
        navigationHelpButton: false,  //右上角的帮助按钮,
        fullscreenButton: false   //右下角的全屏按钮。我们可以自己实现全屏按钮
      })
      // 初始化场景位置
      this.viewer.scene.camera.setView({
        // 初始化相机经纬度
        destination: new Cesium.Cartesian3.fromDegrees(119.2, 34.6, 500),
        orientation: {
          heading: Cesium.Math.toRadians(0),
          pitch: Cesium.Math.toRadians(-90),
          roll: Cesium.Math.toRadians(0)
        }
      });
      // 清除原有的建筑模型
      this.viewer.imageryLayers.removeAll()
      // 去掉cesium的logo
      this.viewer._cesiumWidget._creditContainer.style.display = "none";
      // 显示帧率
      this.viewer.scene.debugShowFramesPerSecond = true;
      // 加载高德地图
      var layer = new Cesium.UrlTemplateImageryProvider({
        url: "http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
        minimumLevel: 4,
        maximumLevel: 18
      })
      this.viewer.imageryLayers.addImageryProvider(layer);
    }
    
    async add3DTiles (url) {
      const tileset = await Cesium.Cesium3DTileset.fromUrl(url)
      this.viewer.scene.primitives.add(tileset); // 将倾斜摄影实体加载到地图上
      this.viewer.zoomTo(tileset)
    }
注意:我看好多博客写加载3DTiles用的方法是:new Cesium.Cesium3DTileset({url:""}),但是我用了这个方法会报错,可能是版本的问题,查阅文档改用了现在的方法。

三、加载效果

image.png

image.png

四、疑问

上面就是我这段时间看了好多博客得来的成果,希望能对大家有所帮助。但是我有几个疑问,希望能得到解答。

  1. 该模型放大后发现细节很模糊,不知道是我加载的问题,还是提供的模型就很模糊
  2. 我把下载的模型都引入到public中,发现文件数量很多且很大。实际开发项目中,是如何处理3Dtiles文件的,总不能就是放到public中和项目一起打包吧?是用服务器发布服务吗?
  3. 如果是用服务器发布服务的形式,前端通过url调用,那么这么多文件也要调用这么多次吗?我也想过使用cesiumLab的合并模型功能,但是它恰恰不支持本模型,遂作罢。

image.png

望解答。