Cesium.Transforms.eastNorthUpToFixedFrame
在Cesium中,创建局部坐标系的函数主要是Cesium.Transforms.eastNorthUpToFixedFrame
。这个函数允许你根据一个给定的世界坐标点(通常是地球上的某个经纬度位置,通过Cesium.Cartesian3.fromDegrees
转换为笛卡尔坐标)来创建一个局部坐标系。这个局部坐标系以,y轴指向北,z轴指该点为中心,其x轴指向东向上方(通常是椭球体的法线方向)。
Cesium.Transforms.eastNorthUpToFixedFrame
参数说明:
origin
:Cesium.Cartesian3
类型,表示局部坐标系的原点,即你希望以此为中心创建局部坐标系的点。ellipsoid
(可选):Cesium.Ellipsoid
类型,表示用于计算局部坐标系的椭球体。如果不指定,则默认使用WGS84椭球体。result
(可选):Cesium.Matrix4
类型,用于存储计算结果的矩阵。如果不提供,将创建一个新的Matrix4
实例。
返回值:
- 返回
Cesium.Matrix4
类型的结果,表示从局部坐标系到世界坐标系的变换矩阵。这个矩阵可以用于将局部坐标系中的点转换到世界坐标系中,或者用于计算与局部坐标系相关的其他变换。
应用场景
这个函数在Cesium开发中非常有用,尤其是在处理三维模型、地形或任何需要局部坐标变换的场景时。通过创建一个局部坐标系,你可以更容易地对模型进行平移、旋转和缩放等操作,因为这些操作在局部坐标系中通常更加直观和简单。
示例代码
以下是一个使用Cesium.Transforms.eastNorthUpToFixedFrame
创建局部坐标系,并计算新坐标点的示例:
// 假设我们有一个经纬度点
var longitude = -123.0744619;
var latitude = 44.0503706;
var height = 0.0;
// 将经纬度转换为笛卡尔坐标
var origin = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
// 创建局部坐标系到世界坐标系的变换矩阵
var localToWorldMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);
// 假设我们想要在局部坐标系中沿x轴(东方向)移动100米
// 注意:这里需要先将米转换为椭球面上的距离,但为简化示例,我们直接使用Cartesian3.fromElements
var localPoint = new Cesium.Cartesian3(100.0, 0.0, 0.0); // x=100米, y=0米, z=0米
// 使用矩阵乘法将局部坐标转换为世界坐标
var worldPoint = Cesium.Matrix4.multiplyByPoint(localToWorldMatrix, localPoint, new Cesium.Cartesian3());
// 现在worldPoint包含了在世界坐标系中的新位置
注意:上面的示例中,直接将米数作为笛卡尔坐标的x分量进行处理是不准确的,因为地球是一个椭球体,不是简单的平面。在实际应用中,你可能需要使用更复杂的方法来计算椭球面上的距离和坐标。然而,为了简化示例,这里直接使用了Cartesian3.fromElements
来创建一个近似的局部坐标点。
应用-修改Primitive位置
在Cesium中,将一个对象(如Cesium3DTileset
、Entity
等)移动到特定位置通常不是通过一个单独的“移动至特定位置”的函数来实现的,而是通过修改对象的position
属性(对于Entity
)或modelMatrix
属性(对于更复杂的变换,包括旋转和平移)来完成的。
Entity
你可以直接设置其position
属性为一个Cesium.Cartesian3
对象,该对象表示了地球上的经纬度位置(在WGS 84坐标系中)或笛卡尔坐标(如果使用的是笛卡尔坐标系)。但是,对于经纬度位置,你通常会使用Cesium.Cartesian3.fromDegrees
函数来将经纬度转换为笛卡尔坐标,然后设置给position
属性。
Primitive
它没有直接的position
属性来设置其位置。相反,你可以通过修改其modelMatrix
属性来应用一个包含平移、旋转和缩放的变换矩阵。但是,对于简单的位置移动,你通常会创建一个仅包含平移的矩阵,并将其与tileset的当前变换矩阵(如果有的话)相乘。
然而,在大多数情况下,如果你只是想将tileset移动到一个新的位置而不改变其朝向,最简单的方法是使用Cesium.Transforms.eastNorthUpToFixedFrame
来创建一个从地球表面某点到固定框架的变换矩阵,并将其设置为modelMatrix
。但是,请注意,这将改变tileset的朝向,使其面向新的东-北-上方向。
如果你只是想移动tileset而不改变其朝向,你可能需要手动计算一个仅包含平移的矩阵,但这通常比使用Cesium.Transforms.eastNorthUpToFixedFrame
然后调整结果更复杂。
然而,对于大多数用例,如果你只是想在视觉上移动tileset而不关心其内部的朝向或坐标系统,你可以简单地使用平Cesium.Matrix4.fromTranslation
来创建一个移矩阵,并将其与tileset的当前modelMatrix
(如果有的话)相乘,或者如果tileset没有设置modelMatrix
,则直接将其设置为平移矩阵。但是,请注意,如果tileset已经有了一个非单位矩阵的modelMatrix
,那么直接替换它可能会导致不期望的结果。Cesium.Quaternion(四元数,用于描述围绕某个向量旋转一定角度的变换)
一个更安全的做法是使用Cesium的变换工具来确保你的变换是相对于tileset当前位置的。但是,对于简单的平移,如果你知道tileset的原始位置并且只是想将其移动到一个新的位置,你可以这样做:
// 假设tileset已经添加到了viewer的scene.primitives中
var tileset = ...; // 你的tileset对象
// 计算新的位置(笛卡尔坐标)
var newPosition = Cesium.Cartesian3.fromDegrees(-117.16, 32.71, 0.0); // 例如,洛杉矶的经纬度
// 如果你知道tileset的原始位置并且想要相对于它进行移动,
// 你需要首先获取tileset的当前变换矩阵(如果有的话),
// 但通常对于简单的移动,我们可以直接创建一个平移矩阵
// 创建一个仅包含平移的矩阵
var translation = Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3.subtract(newPosition, tileset.boundingSphere.center, new Cesium.Cartesian3()));
// 注意:上面的代码实际上是不正确的,因为boundingSphere.center可能不是tileset的“原点”
// 正确的做法可能需要你根据tileset的具体内容和结构来确定如何计算平移
// 由于我们通常不知道tileset的确切“原点”,一个更简单但可能不那么精确的方法是
// 直接使用newPosition作为平移的基准,但这将不会考虑tileset内部的任何现有变换
// 因此,这里我们假设我们想要“重置”tileset的位置
// 如果tileset没有设置modelMatrix或者你想要完全替换它
tileset.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(newPosition);
// 注意:这将改变tileset的朝向!
// 或者,如果你只是想在现有变换的基础上添加平移(但通常很难知道现有的变换是什么)
// 你可能需要先获取并分解现有的modelMatrix,然后应用新的平移
// 这通常比较复杂,且容易出错
// 在许多情况下,最简单且最有效的方法可能是
// 重新加载tileset并将其位置设置为新的经纬度(但这将重置tileset的所有状态,如可见性、选择等)
// 或者,如果可能的话,调整你的数据或tileset的加载方式,以便它们从一开始就在正确的位置