Cesium手动建模模型用Cesiumlab转3D Tiles模型位置不对,调整模型位置至指定经纬度

news2024/11/18 22:48:41

 Cesium加载3Dtiles模型的平移和旋转_3dtiles先旋转再平移示例-CSDN博客

Cesium 平移cesiumlab生产的3Dtiles切片模型到目标经纬度-CSDN博客

【ArcGIS+CityEngine】自行制作Lod1城市大尺度白膜数据_cityengine 生成指定坐标集指定区域的白模-CSDN博客

以上次ArcGIS+CityEngine制作的白膜为例:

 导出至FBX/OBJ

然后在CesiumLab中转化为3D Tiles模型

 但是发现模型位置不正确,默认位置在北京天安门上空,需要将模型调整至指定经纬度位置!!

起初以为只需做平移变化,平移至指定经纬度:

tileset.readyPromise.then(function() {
        // // 获取tileset的中心点坐标
        const boundingSphere = tileset.boundingSphere
        const center = boundingSphere.center

        // 将中心点坐标转换为WGS84坐标系下的经纬度
        const cartographic = Cesium.Cartographic.fromCartesian(center)
        console.log(cartographic)
        const longitude = Cesium.Math.toDegrees(cartographic.longitude)
        const latitude = Cesium.Math.toDegrees(cartographic.latitude)
        const height = Cesium.Math.toDegrees(cartographic.height)

        // const startLon = 116.391005;
        // const startLat = 39.906623
        // 将经纬度调整为研究区域的经纬度
        const areaLongitude = 118.792930
        // const areaLongitude = 114.150301
        const areaLatitude = 31.9707912

        // 计算tileset的平移量,并将其应用到modelMatrix中
        const translation = Cesium.Cartesian3.fromDegrees(areaLongitude, areaLatitude)
        const centerNew = Cesium.Cartesian3.fromDegrees(longitude, latitude)
        const translationVector = Cesium.Cartesian3.subtract(translation, centerNew, new Cesium.Cartesian3())
        const translationMatrix = Cesium.Matrix4.fromTranslation(translationVector);
        console.log(translationMatrix)
        tileset.modelMatrix = translationMatrix
        viewer.zoomTo(tileset)
      })

 但是平移的结果存在问题!!!模型为倾斜的,发生旋转了,未贴地,需要调整!!!

why: 

在Cesium中,当你尝试在全局坐标系下直接平移3D Tiles数据时,可能会遇到模型变得不平(即模型的几何形状在视觉上扭曲或倾斜)的问题。这通常是因为平移操作没有考虑到原始模型与地球表面之间的相对位置关系

How: 

  1. 使用地球表面的局部坐标系
    尝试将平移操作转换为地球表面的局部坐标系中的移动。这通常涉及到计算目标位置与当前位置之间的地球表面距离,并沿着地球表面移动模型。然而,Cesium的API可能不直接支持这种操作,因此你可能需要实现一些自定义的逻辑。

  2. 调整模型矩阵以考虑地球曲率
    如果你直接在模型矩阵中设置平移,你需要确保这个平移是沿着地球表面的切线方向进行的,而不是简单地沿着全局坐标系的X、Y、Z轴。这可能需要你根据目标经纬度计算出一个合适的平移向量,该向量应该考虑到地球表面的曲率

Solution:

  1. 将模型平移回世界坐标系原点(地心)

  2. 将局部坐标Z轴调整到与世界坐标Z轴重合

  3. 将局部坐标X,Y轴调整到与世界坐标X,Y轴重合

  4. 将目标位置的eastNorthUp局部坐标系平移回世界坐标系原点(地心)

  5. 旋转物体坐标系与目标坐标系重合

  6. 平移到目标位置,即为最终变换矩阵

 理论基础:GAMES101 Lecture 04 Transformation Cont._哔哩哔哩_bilibili

Cesium中局部平移、旋转3D Tiles模型Cesium局部平移、缩放、旋转思路及代码实现 - 小专栏

 平移

解释:

  • 红点:frompoint(地表点)
  • 蓝点:targetpoint(frompoint局部坐标向东向北向上偏移各 310、-140、10米 后得到的目标点)
  • 红向量:地表点向量
  • 蓝向量:目标点向量
  • 绿向量:平移向量。如果是局部坐标,那么就是 (310, -140, 10),如果是世界坐标下的,那就是 蓝向量 - 红向量

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

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

tileset.readyPromise.then(function() {
        let params = {
          position: tileset.boundingSphere.center,
          tx: -1974,
          ty: 2433,
          tz: -33.9
        }
        // 重定向坐标
        const m = Cesium.Transforms.eastNorthUpToFixedFrame(params.position);//获取到以模型中心为原点,Z轴垂直地表的局部坐标系,以矩阵表示,此矩阵为将局部坐标系变换到世界坐标系的变换矩阵
        //设置平移向量
        const tempTranslation = new Cesium.Cartesian3(params.tx, params.ty, params.tz);//平移向量
        // 获取平移矩阵
        const offset = Cesium.Matrix4.multiplyByPoint(m, tempTranslation, new Cesium.Cartesian3(0, 0, 0));//局部坐标中(tx,ty,tz)在世界坐标系中位置
        const translation = Cesium.Cartesian3.subtract(offset, params.position, new Cesium.Cartesian3());//终点世界坐标减去原点世界坐标得到世界坐标系下平移向量
        // 重新设置其位置大小
        tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
        viewer.scene.primitives.add(tileset)
        viewer.flyTo(tileset)
      })
    },

旋转

function moveModel(tileset,longitude,latitude,height) {
    //计算世界坐标系中的目标位置offset
    var cartographic = new Cesium.Cartographic.fromCartesian(
      tileset.boundingSphere.center
    );
    var offset = Cesium.Cartesian3.fromDegrees(longitude,latitude,cartographic.height+height);
 
    //将模型位移至地心
    const origin = tileset.boundingSphere.center;
    const originMatrix = tileset.modelMatrix;//模型的初始变换矩阵
    const backToEarthCenter = new Cesium.Cartesian3(-origin.x,-origin.y,-origin.z);//初始位置到地心的位移向量
    let backToEarthCenterMatrix = Cesium.Matrix4.fromTranslation(backToEarthCenter);//初始位置到地心的变换矩阵
    Cesium.Matrix4.multiply(backToEarthCenterMatrix, originMatrix, backToEarthCenterMatrix);//移动模型到地心的矩阵
 
    // 旋转模型使得Z轴与世界坐标Z轴重合
    let arrowX = new Cesium.Cartesian3(1, 0, 0);
    let arrowZ = new Cesium.Cartesian3(0, 0, 1);
    let angleToXZ = Cesium.Cartesian3.angleBetween(arrowX, new Cesium.Cartesian3(origin.x, origin.y, 0));//局部Z轴在世界坐标系XY平面上投影到X轴角度,即绕Z顺时针旋转这个角度可以到XZ平面上
    let angleToZ = Cesium.Cartesian3.angleBetween(origin, arrowZ);//然后绕Y轴顺时针旋转此角度可使得Z轴与世界坐标系Z轴重合
    const rotationAngleToXZ = Cesium.Matrix3.fromRotationZ((origin.y>0?-1:+1)*angleToXZ);//绕Z轴旋转的Matrix3矩阵,正角度逆时针旋转
    const rotationAngleToZ = Cesium.Matrix3.fromRotationY(-angleToZ);//绕Y轴旋转的Matrix3矩阵,负角度顺时针旋转
    let rotationAngleToZMatrix = Cesium.Matrix3.multiply(rotationAngleToZ, rotationAngleToXZ, new Cesium.Matrix3);//连续旋转的Matrix3矩阵,即先绕Z轴旋转,后绕Y旋转的矩阵。
    rotationAngleToZMatrix = Cesium.Matrix4.fromRotationTranslation(rotationAngleToZMatrix);//连续旋转的Matrix4矩阵
    Cesium.Matrix4.multiply(rotationAngleToZMatrix, backToEarthCenterMatrix, rotationAngleToZMatrix);//将移动至地心模型,旋转至Z轴重合的矩阵
 
    // 旋转模型使得X,Y轴与世界坐标X,Y轴重合
    const rotationZ = Cesium.Matrix3.fromRotationZ(-Math.PI/2); // 绕Z轴旋转90°的Matrix3变换矩阵
    let rotationMatrix = Cesium.Matrix4.fromRotationTranslation(rotationZ); // 绕Z轴旋转90°的Matrix4变换矩阵
    Cesium.Matrix4.multiply(rotationMatrix, rotationAngleToZMatrix, rotationMatrix);//将移动至地心模型的物体坐标系,旋转到与世界坐标系重合的矩阵
 
    //在地心位置,旋转物体坐标系和世界坐标系重合的模型,使得与目标坐标系重合
    const offsetToWorldMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(offset);//获取到以目标位置为原点,的eastNorthUp局部坐标系的变换矩阵
    const backToEarthCenterOffset = new Cesium.Cartesian3(-offset.x, -offset.y, -offset.z);//目标位置到地心的位移向量
    let backToEarthCenterMatrixOffset = Cesium.Matrix4.fromTranslation(backToEarthCenterOffset);//目标位置到地心的变换矩阵
    Cesium.Matrix4.multiply(backToEarthCenterMatrixOffset, offsetToWorldMatrix, backToEarthCenterMatrixOffset);//获得从世界坐标系旋转至目标坐标系的旋转矩阵(只有旋转,没有位移)
    Cesium.Matrix4.multiply(backToEarthCenterMatrixOffset, rotationMatrix, backToEarthCenterMatrixOffset);//将移动至地心模型的物体坐标系,旋转到与目标坐标系重合的矩阵(完成模型的最终旋转,没有位移)
 
    //移动到目标位置
    const backToOriginMatrix = Cesium.Matrix4.fromTranslation(offset);//地心到目标位置位移向量
    const lastMatrix = Cesium.Matrix4.multiply(backToOriginMatrix,backToEarthCenterMatrixOffset,new Cesium.Matrix4());//最终矩阵,即将地心位置的模型移动到目标位置(完成模型的最终旋转,最终位移)
    console.log('最终变换矩阵',lastMatrix);
    return lastMatrix //返回最终变换矩阵
}
------------------------------------------------------------------------------------------
let tileset = viewer.scene.primitives.add(
      new Cesium.Cesium3DTileset({
        url: ".../tileset.json",
      })
    );
    
    tileset.readyPromise.then(function (tileset) {
      window.tileset = tileset
      let longitude = 104.98680
      let latitude = 32.20795
      let height = 100
      let modelMatrix = moveModel(tileset,longitude,latitude,height)
      tileset.modelMatrix = modelMatrix;//移动模型
      // 创建圆形包围盒
      let boundingSphere = new Cesium.BoundingSphere(
        tileset.boundingSphere.center,
        tileset.boundingSphere.radius
      );
      //飞向该包围盒
      viewer.camera.flyToBoundingSphere(boundingSphere);
    });

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1991292.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IEEE Transactions on Intelligent Transportation Systems投稿指南

投稿记录 submitted 2024-5-29 Awaiting AE Assignment 2024-6-11 Under review 2024-6-15 Awaiting EIC Decision 2024-6-24 感觉要拒稿的节奏 Resubmit To Another Journal 2024-6-25 与期刊不符合 下载模板 IEEE Transactions on Intelligent Transportation Syste…

java.lang.NoClassDefFoundError: ch/qos/logback/core/util/StatusPrinter2

1、问题 SpringBoot升级报错: Exception in thread "main" java.lang.NoClassDefFoundError: ch/qos/logback/core/util/StatusPrinter2 类找不到: Caused by: java.lang.ClassNotFoundException: ch.qos.logback.core.util.StatusPrinter22、…

【Vue3】Pinia $subscribe

【Vue3】Pinia $subscribe 背景简介开发环境开发步骤及源码 背景 随着年龄的增长,很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来,技术出身的人总是很难放下一些执念,遂将这些知识整理成文,以纪念曾经努力学习奋斗的日子…

前端框架(三件套)

学习网站 HTML 系列教程&#xff08;有广告&#xff09; HTML&#xff08;超文本标记语言&#xff09; | MDN (mozilla.org)&#xff08;英文不太友好&#xff09; 1.HTML5 & CSS3 1.1HTML5表格 <!DOCTYPE html> <html lang"en"> <head>…

常见框架漏洞详解②!!

中间件 中间件&#xff08;英语&#xff1a;Middleware&#xff09;是提供系统软件和应⽤软件之间连接的软件&#xff0c;以便于软件各部 件之间的沟通。 中间件处在操作系统和更⾼⼀级应⽤程序之间。他充当的功能是&#xff1a;将应⽤程序运⾏环境与操作系统隔离&#xff0c;…

setState执行机制

当this.setState()被调用时&#xff0c;React会重新调用render方法来重新绘制UI 异步更新 setState通过一个队列机制实现state的更新当执行setState时&#xff0c;会将需要更新的state合并后放入状态队列&#xff0c;而不是立刻更新队列机制可以高效的批量更新state&#xff…

武汉流星汇聚:亚马逊跨境电商蓝海中的领航者,共绘商业新蓝图

在全球化日益加深的今天&#xff0c;跨境电商已成为连接世界市场的桥梁&#xff0c;为企业提供了前所未有的发展机遇。在这片充满机遇的蓝海中&#xff0c;武汉流星汇聚电子商务有限公司凭借其深厚的行业底蕴、卓越的用户体验以及“以客户为中心”的坚定理念&#xff0c;在亚马…

嵌入式学习day12(LinuxC高级)

由于C高级部分比较零碎&#xff0c;各部分之间没有联系&#xff0c;所以学起来比较累&#xff0c;多练习就好了 一丶Linux起源 寻科普|第二期:聊聊Linux的前世今生 UNIX和linux的区别&#xff1a; &#xff08;1&#xff09;linux是开发源代码的自由软件&#xff0e;而unix是…

前端模块化-探究webpack loader的原理以及实现常见的loader

前言 本节主要介绍这些插件的基本原理并手写一些常用的 Loader。 本节对应的 demo 可以在这里找到。 什么是 Loader 在 Webpack 中&#xff0c;Loader 是用于对模块的源代码进行转换的工具。Webpack 将一切视为模块&#xff0c;而这些模块可能是各种类型的文件&#xff0c;如…

VSCode编译多个不同文件夹下的C++文件

实际上VSCode编译C文件就是通过向g传递参数实现的&#xff0c;因此即使是不同包下面的cpp文件或者.h文件都是可以通过修改g的编译参数实现&#xff0c;而在VSCode中&#xff0c;task.json文件其实就是在配置g的编译参数&#xff0c;因此我们可以通过修改task.json里面的参数&am…

洛谷 B2145 digit 函数 B2146 Hermite 多项式 题解

题目目录&#xff1a; No.1 B2145 digit 函数 No.2 B2146 Hermite 多项式 OK&#xff0c;开始正文&#xff01; 第一题&#xff1a;B2145 digit 函数 题目描述 在程序中定义一函数 digit(n,k)&#xff0c;它能分离出整数 n 从右边数第 k 个数字。 输入格式 正整数 n …

Topsis法模型(评价类问题)

目录 本文章内容参考&#xff1a; 一. 概念 二. 特点和适用范围 三. 实现步骤 四. 代码实现 本文章内容参考&#xff1a; TOPSIS法模型讲解(附matlab和python代码) 【数学建模快速入门】数模加油站 江北_哔哩哔哩_bilibili 一. 概念 TOPSIS&#xff08;Technique for Or…

让EHS管理更智能,一起来看物联网如何重塑企业EHS管理

随着信息技术的飞速发展&#xff0c;物联网&#xff08;IoT&#xff09;技术正逐步渗透到企业管理的各个领域&#xff0c;特别是在环境、健康与安全&#xff08;EHS&#xff09;管理方面&#xff0c;物联网技术展现出了巨大的潜力和价值。 一、物联网技术在EHS管理中的应用场景…

达梦数据库 逻辑备份还原

达梦的逻辑备份还原 1.背景2.要求3.实验步骤3.1 相关术语3.2 dexp逻辑导出3.2.1 使用dexp工具3.2.2 dexp相关参数含义3.2.3 四种级别导出3.2.3.1 FULL3.2.3.2 OWNER3.2.3.3 SCHEMAS3.2.3.4 TABLES 3.2.4 使用范例3.2.4.1 环境准备3.2.4.2 dexp逻辑导出 3.3 dimp逻辑导入3.3.1 使…

【大模型从入门到精通10】openAI API 提示链的力量1

这里写目录标题 提示链的力量核心概念理解提示链用于清晰说明的类比 实际应用与益处工作流程管理成本效率错误减少动态信息加载 方法学步骤式方法最佳实践 示例设置环境从用户查询中提取相关信息获取详细产品信息 提示链的力量 核心概念 理解提示链 提示链涉及将复杂任务分解…

C++速学day2

xia复习 上一天的学习内容&#xff1a; 重点&#xff1a;1、封装———— 就是对类的抽象 &#xff0c;将一种对象的共性 抽象成一个类。 2、三个函数——-构造函数/复制构造函数/析构函数 注意&#xff1a;析构函数和构造函数的调用顺序刚好相反。 新内容 两个类的关系 …

巨能涨!用AI做沙雕日常图文号,闭眼出大爆款!接个软广3000+!

家人们&#xff01;最近圈子陆续整理了一波在小红书上&#xff0c;适合植入软广的AI小红书商单玩法案例&#xff0c;例如&#xff1a;AI美女博主账号、AI养生博主账号、AI治愈插画Vlog短视频账号等等&#xff0c;接下来也会持续输出更多高价值的软广案例玩法。 今天刚好在刷小…

【python】PyQt5中QButtonGroup的详细用法解析与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

正点原子imx6ull-mini-Linux驱动之Linux 网络驱动实验

网络驱动是 linux 里面驱动三巨头之一&#xff0c;linux 下的网络功能非常强大&#xff0c;嵌入式 linux 中也常 常用到网络功能。前面我们已经讲过了字符设备驱动和块设备驱动&#xff0c;本章我们就来学习一下 linux 里面的网络设备驱动。 1&#xff1a;嵌入式网络简介 1.1…

Pandas中高效的“For循环”

循环是我们编程技能中的一项固有技能。当我们熟悉任何编程语言时&#xff0c;循环就会成为一个基本的、易于解释的概念。 在这篇博文中&#xff0c;我们将探索遍历pandas dataframe的各种方法&#xff0c;检查每个循环方法的相关运行时。为了验证循环的有效性&#xff0c;我们…