在vue上使用cesium开发三维地图-加载三维数据
以前端webGIS开发工程师的角度,讲述关于GIS的知识,带大家快速了解下webGIS的知识。

推荐使用NSDT 3DConvert进行3D模型格式转换,支持glb、obj、stp、fbx、ifc等多种3D模型格式之间进行互相转换,在转换过程中,能够很好的保留模型原有的颜色、材质等信息。
准备工作
模型数据
下载模型。

3d tiles简介
3DTiles数据集是cesium小组AnalyticlGraphics与2016年3月定义的一种数据集,3DTiles数据集以分块、分级渲染,将大数据量三维数据以分块,分层的形式组织起来,可以大量减轻浏览器和GPU的负担是一个优秀的,并且格式公开的数据格式。
3D Tiles是用于流式传输大规模异构3D地理空间数据集的开放规范。为了扩展Cesium的地形和图像流,3D Tiles将用于流式传输3D内容,包括建筑物,树木,点云和矢量数据。
模型数据加载
我把下载的模型放在public/DemoData
下,新建一个文件夹Scene
,存放模型数据。


因为之前 在 vue.config.js
中配置过本地数据的代理。

加载模型方法代码如下:
methods: {
// 加载3d模型 3D Tiles
// 数据来源 https://gitee.com/HQCode/Cesium-test/blob/master/lesson02/Scene/testm3DTiles.json
load3DTiles() {
const Cesium = this.cesium;
let tilesetModel = this.viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: "LocalDemoApi/Scene/testm3DTiles.json",
}));
tilesetModel.readyPromise.then((currentModel) => {
// 定位到模型
this.viewer.zoomTo(currentModel, new Cesium.HeadingPitchRange(0.5, -0.2, currentModel.boundingSphere.radius * 1.0));
}).otherwise((error) => {
console.log(error);
});
},
...
}
调用上面的方法加载:

模型加载效果:

模型是加载出来了,但是位置不太对,模型出现在了空中,这是为什么?
理由如下:
1、3d tiles文件生成时本身就具有位置和高度, 生成的数据不一定是落在地面上,有可能是浮在空中的,这并不是我们想要的,我们希望拍摄的成果能贴到地面上。
2、单个瓦片的位置信息是写到了数据中的(.b3dm和对应的json文件中),如果能整体调整加载后的tileset,就会是最好的选择
3、生成3dtiles文件时使用的底图和地形和cesium加载的可能不同,再加上人工调整模型位置具有一定的偏差,所以3dtiles模型加载到数字地球上之后,大部分概率是需要再次调整位置
调整3dtiles位置,本质是通过 矩阵运算 来实现的,快速了解下矩阵运算。

// 创建平移矩阵方法一
// m = Cesium.Matrix4.fromArray([
// 1.0, 0.0, 0.0, 0.0,
// 0.0, 1.0, 0.0, 0.0,
// 0.0, 0.0, 1.0, 0.0,
// x, y, z, 1.0
// ]);
//创建平移矩阵方法二
var translation = Cesium.Cartesian3.fromArray([x, y, z]);
m = Cesium.Matrix4.fromTranslation(translation);
tilesetModel.modelMatrix = m;
我们只要不断的修改 x,y,z ,就可以调整物体的位置了。
得到合适的 x,y,z ,在加载3d tiles 的时候,将modelMatrix 设置成 刚刚的x,y,z 值,就可以了。
还有一种方法就是计算偏移量(高度为例)。
// 设置指定高度
function changeHeight(height) {
height = Number(height);
if (isNaN(height)) {
return;
}
var cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude,height);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
}
在vue上使用cesium开发三维地图 - 索引
在vue上使用cesium开发三维地图-坐标系、webGIS简介