GIS数据处理-cesium中模型位置设置

介绍

最近我收到不少人私信询问我,在cesium中加载3dtiles模型后如何调整模型位置,这里我就统一的介绍一下,我是怎么处理的以供大家参考。

常见模型分类:

  1. 倾斜摄影模型:由于模型带地理位置,基本上不需要调整模型位置。
  2. 人工模型:模型是没有坐标信息的,这个时候就需要我们调整模型位置。

还有点云等数据,这里就不介绍了。

我在这里推荐两个方法,一个是使用cesiumlab来操作(可视化操作),另一个是使用代码操作

代码原理

cesium中加载3dtiles模型代码如下:

viewer.scene.primitives.add(new Cesium.Cesium3DTileset({url: 'http://localhost:8080/data/testModel/tileset.json',modelMatrix: Cesium.Matrix4.fromArray([0.9972458032561666, 0.04372029028528979, 0.05991113506964879, 0,-0.03623787897545647, 0.9920229449104262, -0.12073646051879428, 0,-0.06471185374661931, 0.11823287609043515, 0.9908750491338749, 0,-663.0794944260269, 1211.490494620055, 2974.1003134818748, 1]),}));

new Cesium.Cesium3DTileset(options)

用于流式传输海量异构 3D 地理空间数据集

options选项

名称 类型 默认 描述
url 网络资源,字符串 瓦片集 JSON 文件的 url
modelMatrix 矩阵4(Matrix4) Matrix4.IDENTITY 转换瓦片集的根瓦片的 4x4 转换矩阵

这里我们要详细讲述一下矩阵的用处,cesium中所有的坐标最后都会转换成空间笛卡尔坐标也就是我们常说的三维空间坐标系。在笛卡尔坐标系中模型进行坐标系转换,这里就涉及到转换矩阵了。

tileset.modelMatrix,使用这个属性就可以在数据基础上进行坐标转换了

平移思路

  1. 获取当前瓦片数据集的包裹范围(boundingSphere)中心(此时参考系是三维笛卡尔坐标系)
  2. 计算当参考系是局部坐标(局部坐标系的原点为模型包围范围的中心)时,此位置为原点的局部坐标系,到世界坐标的转换矩阵(eastNorthUpToFixedFrame)
  3. 利用上一步的转换矩阵,左乘一个局部平移向量,得到此平移向量在世界坐标系下的平移目标位置(矩阵×向量,结果是向量)
  4. 向量相减:世界坐标系下,指向平移目标点位的目标向量 - 指向数据集中心的向量,得到世界坐标系下的平移向量。
  5. 将世界坐标系下的平移向量转换成平移矩阵,赋予 tileset.modelMatrix

代码实现

tileset.readyPromise.then(tileset => {// Cartesian3 三维笛卡儿坐标系中的瓦片中心点const tileset_center = tileset.boundingSphere.center; // Matrix4(四阶矩阵)局部参考系到世界参考系下的转换矩阵const frompoint_to_world_matrix = Cesium.Transforms.eastNorthUpToFixedFrame(tileset_center);// 向模型中心为原点,正北为y,正东为x,地心朝上为z分别平移 310、-140、10米const local_translation = new Cesium.Cartesian3(310, -140, 10); const result = new Cesium.Cartesian3(0,0,0);// 转换矩阵左乘局部平移向量,结果存储在 result 中,结果是世界坐标下的平移终点向量Cesium.Matrix4.multiplyByPoint(frompoint_to_world_matrix, local_translation, result); const targetpoint_to_world_matrix = Cesium.Transforms.eastNorthUpToFixedFrame(result);// 世界坐标系下,指向平移目标点位的目标向量 - 指向数据集中心的向量,得到世界坐标系下的平移向量const world_translation = new Cesium.Cartesian3(targetpoint_to_world_matrix[12] - frompoint_to_world_matrix[12],targetpoint_to_world_matrix[13] - frompoint_to_world_matrix[13],targetpoint_to_world_matrix[14] - frompoint_to_world_matrix[14],); // 构造平移矩阵并赋值tileset.modelMatrix = Cesium.Matrix4.fromTranslation(world_translation); // 相机视角移动到模型位置viewer.zoomTo(tileset);
});

  • 红点:frompoint(模型包围范围中心点,也是局部坐标系原点)
  • 蓝点:targetpoint(frompoint局部坐标向东向北向上偏移各 310、-140、10米 后得到的目标点)
  • 红向量:世界坐标系下的模型包围范围中心点(局部坐标系原点、起始点)向量
  • 蓝向量:世界坐标系下的目标点向量
  • 绿向量:平移向量。如果是局部坐标,那么就是 (310, -140, 10),如果是世界坐标下的,那就是 蓝向量 - 红向量

cesium 的场景数据最终都是世界坐标的,所以要求的是绿向量的世界坐标表达,然后构造平移矩阵。

现在是已知红向量和局部坐标的绿向量,要先求蓝向量,才能得到世界坐标系下的绿向量。

旋转思路

局部旋转,先将模型移动到世界坐标中心,旋转后,再移动到原来的地方,即

tileset.modelMatrix

其中,

是一个平移矩阵,只需使用模型中心向量取个负值即可

则是从世界坐标中心再移动到模型原点

注意,这里是左乘优先顺序,从右往左乘。

代码实现

tileset.readyPromise.then(tileset => {const tileset_center = tileset.boundingSphere.center; // Cartesian3 三维笛卡儿坐标系中的瓦片中心点// Matrix4(四阶矩阵)局部参考系到世界参考系下的转换矩阵const backto_matrix = Cesium.Matrix4.fromTranslation(tileset_center);// 模型向量取负值const moveto_vec = Cesium.Cartesian3.multiplyByScalar(tileset_center, -1, new Cesium.Cartesian3());//移动到世界坐标系原点的矩阵const moveto_matrix = Cesium.Matrix4.fromTranslation(moveto_vec);/* 绕x(即东方轴)转90度 */const cos_rotateX = Math.cos(Math.PI/2);const sin_rotateX = Math.sin(Math.PI/2);const arr = [1,0,0,0,  0, cos_rotateX, sin_rotateX,0,   0,-sin_rotateX,cos_rotateX,0, 0,0,0,1];//旋转矩阵const rotateX_matrix = Cesium.Matrix4.fromArray(arr);/* 计算最终矩阵 */// 获得在世界原点旋转后的矩阵const temp = Cesium.Matrix4.multiply(rotateX_matrix, moveto_matrix, new Cesium.Matrix4());// 获得旋转后移动回原来位置的矩阵const r = Cesium.Matrix4.multiply(backto_matrix, temp, new Cesium.Matrix4());tileset.modelMatrix = r; // 构造平移矩阵并赋值// 相机视角移动到模型位置viewer.zoomTo(tileset);
});

缩放思路

缩放思路和旋转类似,先移动到世界坐标系中心,缩放,然后再移动到原来的地方

tileset.modelMatrix

代码实现

待实现

参考大佬原文

工具使用

上面介绍了代码的实现步骤,现在介绍直接使用工具的方式

cesiumlab

不得不再次推荐,国人良心工具cesiumlab,下载安装即可

步骤

生成3dtiles切片的教程我之前已经写了,这里默认大家都准备好了

我这里使用的是人工建模的模型,没有地理坐标信息,方便给大家演示

加载数据

打开cesiumlab,选择三维可视化

选择瓦片-》在线

填入自己在线的3dtiles地址

右击图层,选择定位,由于人工模型没有坐标信息,cesiumlab会把模型加载到北京天安门

操作数据

右击开启拖拽移动,会在模型包围范围中心出现局部坐标系

我们先确定一下模型真实的地理位置,这里可以通过百度经纬度查询系统来查询一下模型的真实位置(注意:百度的坐标系是在火星坐标系上二次加密的,因此不会太准,不过没关系我们只是参考)

118.704031,32.164824

右击打开属性-》看到扩展(xbsjPosition),将坐标赋值进去

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dnIk9cYZ-1650542433989)(http://qiliu.sunbt.ltd/qiliu_PicGo/image-20220421193827289.png)]

填完后模型会消失,不要担心,它只是去了它该去的地方了

右击定位,我们就能看到它了,如图所示它离真实的地理位置还差一点

这里我们就需要手动调整一下了,我们需要拖拽红、绿、蓝三个方向(红为x轴、绿为y轴、蓝为y轴)

通过拖拽模型已经到了正确的位置了,到这我们已经成功了90%了

获取cesium加载代码

到上面为止,如果模型尺寸和方向没为题,我们就可以获取cesium的加载代码了

cesiumlab提供了两种加载代码:一种cesium原生的加载代码,一种是earthSDK(也是他们家的,一个基于cesium源码二次开发包,很好用帮我们实现了很多功能,后面有机会也要好好介绍一下)

点击查看cesium加载代码

// cesium加载代码
var viewer = earth.czm.viewer;
var tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({url: '../model/tianjie/tileset.json',modelMatrix: Cesium.Matrix4.fromArray([0.9972459143270339,0.043718663325275964,0.05991047350079684,0,-0.03623642613173875,0.9920231602439527,-0.12073512728614089,0,-0.06471095563532905,0.11823167095432924,0.990875251585238,0,-663.0708428965881,1211.4791529159993,2974.063367189374,1]),
}));
viewer.flyTo(tileset);

其中modelMatrix(转换矩阵)已经帮我们计算好了(学习cesium就是这么简单)

我们把它放到自己的代码种就能使用了

参数介绍

扩展种有很多参数,这里介绍一下常用的参数

xbsjPosition:包括经纬度和模型高程

xbsjRotation:这里设置模型在x、y、z轴上旋转的度数

xbsjScale:这里默认是1,表示模型不缩放,修改这三个参数,可以在x、y、z轴上缩放

最好大家都使用一下,就明白怎么做了,太方便了

这些修改好的参数都会计算在转换矩阵中,我们最后只要矩阵参数即可

cesiumlab中还有很多功能,大家可以使用看看

GIS数据处理-cesium中模型位置设置相关推荐

  1. 对比分析OSG与Cesium中模型LOD的异同

    1. LOD 熟悉渲染的读者可能经常听到LOD(Level Of Detail),也就是用不同的细节层次来表达同一个对象.比如下图中的雕像,从左到右精细度越来越低,最后甚至仅剩一个轮廓,已经看不出人形 ...

  2. android button 中文字位置设置,iOS开发-- 设置UIButton的文字显示位置、字体的大小、字体的颜色...

    btn.frame = CGRectMake(x, y, width, height); [btn setTitle: @"search" forState: UIControlS ...

  3. python与GIS数据处理——随机森林算法插值

    背景 这个是我系列插值文章的第三篇,使用机器学习插值(使用随机森林算法插值). 代码链接 代码我已经放在Github上面了,免费分享使用,https://github.com/yuanzhoulvpi ...

  4. 【BIM+GIS】BIM模型导入GIS软件之前的一些处理设置

    文章目录 一.模型位置发生偏移 二.模型对象丢失或增加 三.模型材质发生变化 四.导出过程缓慢 五.模型属性批量丢失 一.模型位置发生偏移 在视图→可见性/图形替换模型类别→场地(VV可见性快捷),勾 ...

  5. cesium获取模型高度_Cesium中地形数据的加载

    Cesium开发中,如果想要看到真实感,地形数据(DEM)不可或缺.但是很多非GIS专业的人,对地形数据的定位不清晰,不明白地形数据如何展示. 最近很多人问我这个问题,综合看下来,主要问题就集中在地形 ...

  6. 【工大SCIR笔记】浅谈Transformer模型中的位置表示

    作者:哈工大SCIR 徐啸 0. 何为位置信息 首先简单谈一下位置信息.一般将位置信息简单分为绝对位置信息和相对位置信息,并且前者对句子语义的影响不大,更为重要的是后者. 以情感分析 (Sentime ...

  7. Cesium中添加entitie模型,实现贴地。

    1.Cesium中添加entitie模型,实现贴地. 2. 添加模型 const createModel = (url) => {const entity = viewer.entities.a ...

  8. Unity-Live2d(模型参数设置,当前参数保存与恢复所保存参数, 部分位置透明度设置,自动眨眼)

    Unity-Live2D 概述:这是我学习Unity中Live2d的相关操作的一个笔记,欢迎各位同好和大牛的指点.(参考siki学院出的视频学的) 模型参数设置 先来说一下这个模型参数是个什么东西,之 ...

  9. 【CSS】盒子模型案例 ( 盒子模型尺寸计算 | 盒子模型水平居中 | 盒子模型内外边距设置 | 背景图片及位置设置 | 盒子嵌套设置 )

    文章目录 一.实现效果 二.基本 HTML 结构 三.设置最外层盒子样式 ( 盒子模型内外边距设置 ) 四.设置标题盒子样式 ( 盒子模型尺寸计算 | 盒子模型水平居中 ) 五.设置列表盒子样式 ( ...

最新文章

  1. inline-block在ie6中的经典bug
  2. 2017年第六届数学中国数学建模国际赛(小美赛)C题解题思路
  3. 代码管理规范_微服务架构下代码管理规范
  4. 注册CSDN帐号的见闻续
  5. oracle 当前年到指定年的年度范围求取
  6. 2015年10月5日 正式启用该博客
  7. oracle 导入sql文件 汉字乱码_将现有的sql脚本导入 Oracle 数据库,中文乱码问题...
  8. ramdisk根文件系统+initramfs
  9. cad中填充的剖面线不能被修剪_CAD常用命令:CHAMFER(倒角)
  10. 力扣206,反转链表(JavaScript)
  11. 一阶倒立摆的输入和输出是什么_了解一阶高通滤波器传递函数
  12. TypeScript手册翻译系列1-基础类型
  13. 带有参数的输出存储过程
  14. 搭建nginx服务器
  15. win7远程桌面怎么关闭计算机,win7系统关闭远程桌面服务的操作方法
  16. ARC083简要题解
  17. C语言程序设计--图书信息管理系统
  18. vue-03-4:vue封装方法到工具类
  19. Linux如何查找域名IP地址
  20. 基于MaxEnt模型的云南红豆杉潜在适宜分布预测

热门文章

  1. TPC-H tools的使用
  2. AI医疗高精尖!基于AI的新药研发!
  3. 重庆计算机上机操作试题,重庆市计算机等级考试C语言上机模拟试题
  4. mysql查询表里的重复数据方法:
  5. 组播MSDP-原理介绍+报文分析+配置示例
  6. 股权智库:增设产业分析板块
  7. 安卓碎片(Fragment)的使用
  8. android studio 碎片,Android studio之碎片学习
  9. android eventbus使用,EventBus使用之基础
  10. Java多线程之间的通信方式