Cesium结合GIS天地图 加载倾斜摄影3dtile + vue3

实现思路

  1. 将倾斜摄影OSGB数据转换为3dtile(转换方式很多,可以利用第三方工具cesiumlab)
  2. 利用Cesium加载GIS地图,我这里使用的是天地图,可以加载其他地图都行
  3. 加载3dtile数据到地图中展示

安装插件

npm install cesium

加载地图

以加载天地图为例,需要先到天地图官网去申请开发者,获取一个token,以下代码直接粘贴就行,注释中已说明

     //初始化地图
    let viewer;

    function initMap() {
      const tianDiTuToken = '天地图token'
      const mapOption = {
        url: `http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${tianDiTuToken}`,
        layer: "tdtBasicLayer",
        style: "default",
        format: "image/jpeg",
        tileMatrixSetID: "GoogleMapsCompatible",
        maximumLevel: 18
      };
      const imgProvider = new WebMapTileServiceImageryProvider(mapOption);

      const viewerOption = {
        animation: false,//是否创建动画小器件,左下角仪表
        baseLayerPicker: false,//是否显示图层选择器
        fullscreenButton: false,//是否显示全屏按钮
        geocoder: false,//是否显示geocoder小器件,右上角查询按钮
        homeButton: false,//是否显示Home按钮
        infoBox: false,//是否显示信息框
        sceneModePicker: false,//是否显示3D/2D选择器
        scene3DOnly: false,//如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源
        selectionIndicator: false,//是否显示选取指示器组件
        timeline: false,//是否显示时间轴
        navigationHelpButton: false,//是否显示右上角的帮助按钮
        baselLayerPicker: false,// 将图层选择的控件关掉,才能添加其他影像数据
        shadows: true,//是否显示背影
        shouldAnimate: true,
        imageryProvider: imgProvider,
      }

      viewer = new Viewer("map", viewerOption);
      // 添加中文注记图层
      viewer.imageryLayers.addImageryProvider(
          new WebMapTileServiceImageryProvider({
            url: `http://t0.tianditu.com/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default.jpg&tk=${tianDiTuToken}`,
            layer: "tdtAnnoLayer",
            style: "default",
            format: "image/jpeg",
            tileMatrixSetID: "GoogleMapsCompatible",
            show: false,
          }));
      //优化项--关闭相关特效
      viewer.scene.debugShowFramesPerSecond = true;//显示fps
      viewer.scene.moon.show = false;//月亮
      viewer.scene.fog.enabled = false;//雾
      viewer.scene.sun.show = false;//太阳
      viewer.scene.skyBox.show = false;//天空盒
      viewer.resolutionScale = 1.0;//画面细度,默认值为1.0
      //去除版权信息
      viewer._cesiumWidget._creditContainer.style.display = "none";
    }
初始化地图效果

加载倾斜摄影3dtitle

3Dtitle文件我这里是以nginx代理的方式访问的,也可以直接放到项目文件夹中引用

    //加载倾斜摄影图像
    function init3Dtiles() {
      const tileSet = new Cesium3DTileset({
        url: "http://127.0.0.1/data/tileset.json",
        maximumMemoryUsage: 100,//不可设置太高,目标机子空闲内存值以内,防止浏览器过于卡
        maximumScreenSpaceError: 32,//用于驱动细节细化级别的最大屏幕空间错误;较高的值可提供更好的性能,但视觉质量较低。
        maximumNumberOfLoadedTiles: 1000,  //最大加载瓦片个数
        shadows: false,//是否显示阴影
        skipLevelOfDetail: true,// 确定是否应在遍历期间应用详细级别跳过(默认false)
        baseScreenSpaceError: 1024,//When skipLevelOfDetailis true,在跳过详细级别之前必须达到的屏幕空间错误(默认1024)
        skipScreenSpaceErrorFactor: 16,// 定义要跳过的最小屏幕空间错误的乘数。与 一起使用skipLevels来确定要加载哪些图块(默认16)
        skipLevels: 1,//skipLevelOfDetail是true 一个常量,定义了加载图块时要跳过的最小级别数。为 0 时,不跳过任何级别。与 一起使用skipScreenSpaceErrorFactor来确定要加载哪些图块。(默认1)
        immediatelyLoadDesiredLevelOfDetail: false,//当skipLevelOfDetail是时true,只会下载满足最大屏幕空间错误的图块。忽略跳过因素,只加载所需的图块(默认false)
        loadSiblings: false,// 如果为true则不会在已加载完概况房屋后,自动从中心开始超清化房屋 --- 何时确定在遍历期间skipLevelOfDetail是否true始终下载可见瓦片的兄弟姐妹(默认false)
        cullWithChildrenBounds: true,//是否使用子边界体积的并集来剔除瓦片(默认true)
        dynamicScreenSpaceError: true,//减少距离相机较远的图块的屏幕空间错误(默认false)
        dynamicScreenSpaceErrorDensity: 0.00278,//数值加大,能让周边加载变快 --- 用于调整动态屏幕空间误差的密度,类似于雾密度(默认0.00278)
        dynamicScreenSpaceErrorFactor: 4.0,// 用于增加计算的动态屏幕空间误差的因素(默认4.0)
        dynamicScreenSpaceErrorHeightFalloff: 0.25//密度开始下降的瓦片集高度的比率(默认0.25)
      });

      viewer.scene.primitives.add(tileSet);
      viewer.zoomTo(tileSet);

    }
加载倾斜摄影图像效果

加载后发现倾斜图像与地图存在一定位置和高度的偏差,这里我们需要再调整一下图像的位置以及高度,调整代码如下

    //更新倾斜摄影位置
    function update3dtilesMaxtrix(tileSet) {
      //调整参数
      let params = {
        tx: 113.06265738392063, //模型中心X轴坐标(经度,单位:十进制度)
        ty: 22.646803971034342,  //模型中心Y轴坐标(纬度,单位:十进制度)
        tz: 40,  //模型中心Z轴坐标(高程,单位:米)
        rx: 0,  //X轴(经度)方向旋转角度(单位:度)
        ry: 0,  //Y轴(纬度)方向旋转角度(单位:度)
        rz: 2,   //Z轴(高程)方向旋转角度(单位:度)
        scale: 1.30//缩放比例
      };
      //旋转
      const mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(params.rx));
      const my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(params.ry));
      const mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(params.rz));
      const rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
      const rotationY = Cesium.Matrix4.fromRotationTranslation(my);
      const rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
      //平移
      const position = Cesium.Cartesian3.fromDegrees(params.tx, params.ty, params.tz);
      const m = Cesium.Transforms.eastNorthUpToFixedFrame(position);
      //旋转、平移矩阵相乘
      Cesium.Matrix4.multiply(m, rotationX, m);
      Cesium.Matrix4.multiply(m, rotationY, m);
      Cesium.Matrix4.multiply(m, rotationZ, m);
      //比例缩放
      const scale = Cesium.Matrix4.fromUniformScale(params.scale)
      Cesium.Matrix4.multiply(m, scale, m)
      console.log("矩阵m:", m);
      //赋值给tileset
      tileSet._root.transform = m;
    }

在加载倾斜摄影成功后调用以上方法:

    //加载倾斜摄影图像
    function init3Dtiles() {
      const tileSet = new Cesium3DTileset({
        url: "http://127.0.0.1/data/tileset.json"
        //...代码省略,同上
        });

      viewer.scene.primitives.add(tileSet);
      viewer.zoomTo(tileSet);

      //调用方法
      //加载后调整倾斜摄影的位置、角度等参数
      tileSet.readyPromise.then((tileset) => {
        update3dtilesMaxtrix(tileset);
      });
    }
调整后的展示效果

 完整代码如下:

<template>
  <div id="map" style='z-index:100;position: absolute;top: 0; bottom: 0;right: 0;left: 0;'></div>
</template>

<script>
import * as Cesium from "cesium";
import  {Cesium3DTileset, Viewer, WebMapTileServiceImageryProvider} from "cesium";
import {onMounted} from 'vue'

export default {
  name: "MapComponent",
  setup() {
    //初始化地图
    let viewer;

    function initMap() {
      const tianDiTuToken = '天地图token'
      const mapOption = {
        url: `http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${tianDiTuToken}`,
        layer: "tdtBasicLayer",
        style: "default",
        format: "image/jpeg",
        tileMatrixSetID: "GoogleMapsCompatible",
        maximumLevel: 18
      };
      const imgProvider = new WebMapTileServiceImageryProvider(mapOption);

      const viewerOption = {
        animation: false,//是否创建动画小器件,左下角仪表
        baseLayerPicker: false,//是否显示图层选择器
        fullscreenButton: false,//是否显示全屏按钮
        geocoder: false,//是否显示geocoder小器件,右上角查询按钮
        homeButton: false,//是否显示Home按钮
        infoBox: false,//是否显示信息框
        sceneModePicker: false,//是否显示3D/2D选择器
        scene3DOnly: false,//如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源
        selectionIndicator: false,//是否显示选取指示器组件
        timeline: false,//是否显示时间轴
        navigationHelpButton: false,//是否显示右上角的帮助按钮
        baselLayerPicker: false,// 将图层选择的控件关掉,才能添加其他影像数据
        shadows: true,//是否显示背影
        shouldAnimate: true,
        imageryProvider: imgProvider,
      }

      viewer = new Viewer("map", viewerOption);
      // 添加中文注记图层
      viewer.imageryLayers.addImageryProvider(
          new WebMapTileServiceImageryProvider({
            url: `http://t0.tianditu.com/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default.jpg&tk=${tianDiTuToken}`,
            layer: "tdtAnnoLayer",
            style: "default",
            format: "image/jpeg",
            tileMatrixSetID: "GoogleMapsCompatible",
            show: false,
          }));
      //优化项--关闭相关特效
      viewer.scene.debugShowFramesPerSecond = true;//显示fps
      viewer.scene.moon.show = false;//月亮
      viewer.scene.fog.enabled = false;//雾
      viewer.scene.sun.show = false;//太阳
      viewer.scene.skyBox.show = false;//天空盒
      viewer.resolutionScale = 1.0;//画面细度,默认值为1.0
      //去除版权信息
      viewer._cesiumWidget._creditContainer.style.display = "none";
    }

    //加载倾斜摄影图像
    function init3Dtiles() {
      const tileSet = new Cesium3DTileset({
        url: "http://127.0.0.1/data/tileset.json",
        maximumMemoryUsage: 100,//不可设置太高,目标机子空闲内存值以内,防止浏览器过于卡
        maximumScreenSpaceError: 32,//用于驱动细节细化级别的最大屏幕空间错误;较高的值可提供更好的性能,但视觉质量较低。
        maximumNumberOfLoadedTiles: 1000,  //最大加载瓦片个数
        shadows: false,//是否显示阴影
        skipLevelOfDetail: true,// 确定是否应在遍历期间应用详细级别跳过(默认false)
        baseScreenSpaceError: 1024,//When skipLevelOfDetailis true,在跳过详细级别之前必须达到的屏幕空间错误(默认1024)
        skipScreenSpaceErrorFactor: 16,// 定义要跳过的最小屏幕空间错误的乘数。与 一起使用skipLevels来确定要加载哪些图块(默认16)
        skipLevels: 1,//skipLevelOfDetail是true 一个常量,定义了加载图块时要跳过的最小级别数。为 0 时,不跳过任何级别。与 一起使用skipScreenSpaceErrorFactor来确定要加载哪些图块。(默认1)
        immediatelyLoadDesiredLevelOfDetail: false,//当skipLevelOfDetail是时true,只会下载满足最大屏幕空间错误的图块。忽略跳过因素,只加载所需的图块(默认false)
        loadSiblings: false,// 如果为true则不会在已加载完概况房屋后,自动从中心开始超清化房屋 --- 何时确定在遍历期间skipLevelOfDetail是否true始终下载可见瓦片的兄弟姐妹(默认false)
        cullWithChildrenBounds: true,//是否使用子边界体积的并集来剔除瓦片(默认true)
        dynamicScreenSpaceError: true,//减少距离相机较远的图块的屏幕空间错误(默认false)
        dynamicScreenSpaceErrorDensity: 0.00278,//数值加大,能让周边加载变快 --- 用于调整动态屏幕空间误差的密度,类似于雾密度(默认0.00278)
        dynamicScreenSpaceErrorFactor: 4.0,// 用于增加计算的动态屏幕空间误差的因素(默认4.0)
        dynamicScreenSpaceErrorHeightFalloff: 0.25//密度开始下降的瓦片集高度的比率(默认0.25)
      });

      viewer.scene.primitives.add(tileSet);
      viewer.zoomTo(tileSet);

      //加载后调整倾斜摄影的位置、角度等参数
      tileSet.readyPromise.then((tileset) => {
        update3dtilesMaxtrix(tileset);
      });
    }

    //更新倾斜摄影位置
    function update3dtilesMaxtrix(tileSet) {
      //调整参数
      let params = {
        tx: 113.06265738392063, //模型中心X轴坐标(经度,单位:十进制度)
        ty: 22.646803971034342,  //模型中心Y轴坐标(纬度,单位:十进制度)
        tz: 40,  //模型中心Z轴坐标(高程,单位:米)
        rx: 0,  //X轴(经度)方向旋转角度(单位:度)
        ry: 0,  //Y轴(纬度)方向旋转角度(单位:度)
        rz: 2,   //Z轴(高程)方向旋转角度(单位:度)
        scale: 1.30//缩放比例
      };
      //旋转
      const mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(params.rx));
      const my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(params.ry));
      const mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(params.rz));
      const rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
      const rotationY = Cesium.Matrix4.fromRotationTranslation(my);
      const rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
      //平移
      const position = Cesium.Cartesian3.fromDegrees(params.tx, params.ty, params.tz);
      const m = Cesium.Transforms.eastNorthUpToFixedFrame(position);
      //旋转、平移矩阵相乘
      Cesium.Matrix4.multiply(m, rotationX, m);
      Cesium.Matrix4.multiply(m, rotationY, m);
      Cesium.Matrix4.multiply(m, rotationZ, m);
      //比例缩放
      const scale = Cesium.Matrix4.fromUniformScale(params.scale)
      Cesium.Matrix4.multiply(m, scale, m)
      console.log("矩阵m:", m);
      //赋值给tileset
      tileSet._root.transform = m;
    }

    onMounted(() => {
      initMap();
      init3Dtiles()
    })
  }
}
</script>

<style scoped>
@import url('../../node_modules/cesium/Source/Widgets/widgets.css');

html,
body,
#map {
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
}
</style>

以上是学习Cesium加载倾斜摄影的过程,中间踩过很多坑,下一篇将踩坑的过程记录下,希望对有遇到同样问题的小伙伴有所帮助

### 使用 CSS 实现文字在容器内垂直居中的方法 #### 方法一:通过 `line-height` 设置高度一致 当单行文本需要垂直居中时,可以将父容器的高度设置为与 `line-height` 相同。这种方式简单有效,适用于已知固定高度的情况。 ```css .parent { height: 100px; line-height: 100px; /* 高度和行高相同 */ } .child { vertical-align: middle; } ``` 这种方法仅限于单行文本,并且要求父容器有固定的像素高度[^1]。 #### 方法二:利用 Flexbox 布局模型 Flexbox 是一种强大的布局工具,可以通过简单的属性组合轻松实现多场景下的垂直居中效果: ```css .container { display: flex; align-items: center; /* 子项沿交叉轴居中对齐 */ justify-content: center; /* 主轴方向也居中 */ min-height: 100vh; /* 或者其他指定高度 */ } .text { /* 文字样式 */ } ``` 此方案不仅支持多行文本,还兼容不同尺寸的内容自动调整位置[^2]。 #### 方法三:模仿表格行为 对于更复杂的嵌套结构或特定情况下希望保持传统表格的行为,则可借助 CSS 的 table 显示模式来达到目的: ```html <div class="table"> <div class="cell">这里是内容</div> </div> ``` 对应的 CSS 如下所示: ```css .table { display: table; width: 100%; height: 100%; /* 可能需要根据实际情况设定具体数值 */ } .cell { display: table-cell; vertical-align: middle; text-align: center; /* 如果还需要水平居中 */ } ``` 这种做法特别适合处理未知数量的子元素以及跨浏览器一致性问题[^3]。
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值