我将 Cesium 的一个模型加载到场景中,我有两个点要用来计算模型的方向,这是我创建的函数。
// calculate the direction which the model is facing
calculateOrientation({ position, nextPosition }) {
let dir = new Cesium.Cartesian3();
let normalizedDir = new Cesium.Cartesian3();
Cesium.Cartesian3.subtract(nextPosition, position, dir);
Cesium.Cartesian3.normalize(dir, normalizedDir);
var heading = Math.acos(normalizedDir.x);
var pitch = Math.acos(normalizedDir.y);
var roll = 0;
var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);
return orientation;
}
但是我得到的旋转没有任何意义。我的数学有问题吗?
更新
在@Keshet 给出第一个答案后,我查找了如何找到平面和矢量之间的 Angular 。我想如果我找到每个平面的法线和 -90 之间的 Angular ,我应该得到正确的 Angular ,但我不确定这是否正确。
我也不知道 Cesium Axis 是如何工作的,我也找不到任何描述它的文档。例如XY平面等。
let dir = new Cesium.Cartesian3();
let xyNormal = new Cesium.Cartesian3(0,0,1);
let xzNormal = new Cesium.Cartesian3(0,1,0);
let yzNormal = new Cesium.Cartesian3(1,0,0);
Cesium.Cartesian3.subtract(nextPosition, position, dir);
let xyAngle = Cesium.Math.PI_OVER_TWO - Cesium.Cartesian3.angleBetween(dir, xyNormal);
let xzAngle = Cesium.Math.PI_OVER_TWO - Cesium.Cartesian3.angleBetween(dir, xzNormal);
let yzAngle = Cesium.Math.PI_OVER_TWO - Cesium.Cartesian3.angleBetween(dir, yzNormal);
更新 2
根据@IIan 建议使用 atan2,这里是代码:
Cesium.Cartesian3.subtract(position, nextPosition, dir);
// create the mapped to plane vectors, and get the
// normalized versions
let xyMappedVectorNormalized = new Cesium.Cartesian3(0, 0, 0);
let xyMappedVector = new Cesium.Cartesian3(dir.x, dir.y, 0);
let xzMappedVectorNormalized = new Cesium.Cartesian3(0, 0, 0);
let xzMappedVector = new Cesium.Cartesian3(dir.x, 0, dir.z);
let yzMappedVectorNormalized = new Cesium.Cartesian3(0, 0, 0);
let yzMappedVector = new Cesium.Cartesian3(0, dir.y, dir.z);
Cesium.Cartesian3.normalize(xyMappedVector, xyMappedVectorNormalized);
Cesium.Cartesian3.normalize(xzMappedVector, xzMappedVectorNormalized);
Cesium.Cartesian3.normalize(yzMappedVector, yzMappedVectorNormalized);
// calculate the angles
let xyAngle = Math.atan2(xyMappedVectorNormalized.y, xyMappedVectorNormalized.x);
let xzAngle = Math.atan2(xzMappedVectorNormalized.z, xzMappedVectorNormalized.x);
let yzAngle = Math.atan2(yzMappedVectorNormalized.z, yzMappedVectorNormalized.y);
最佳答案
首先,我们需要解释航向 Angular 、俯仰 Angular 和横滚 Angular 代表什么。
- 航向 Angular 表示相对于 XY 平面的弧度 Angular
- 俯仰 Angular 表示相对于 XZ 平面的弧度 Angular
- 滚动 Angular 表示相对于 YZ 平面的弧度 Angular
你不能简单地使用 x/y 来计算航向/俯仰
var heading = Math.acos(normalizedDir.x);
var pitch = Math.acos(normalizedDir.y);
您需要获得每个平面上的总 Angular 。
在 XY 平面上,您将使用归一化的 |(X, Y)| 在 XZ 平面上,您将使用归一化的 |(X, Z)| 在 YZ 平面上,您将使用归一化的 |(Y, Z)|
更新
|(X,Y)|表示单位圆上的一个点。
其中 (sin(theta), cos(theta)) = |(X, Y)|
IE 当 theta = 0 时,|(X, Y)| = (1, 0) 当 theta = PI/2, |(X, Y)| = (0, 1)
这个 theta 将是您用于航向的 Angular
然后,您可以调用arctan2函数来计算相对于平面的 Angular 。
atan2(y, x) = theta 其中 [x, y] 是使用相应的归一化二维向量从上面计算得出的
注意:atan2 给出的 Angular 范围为 (-PI, PI]
示例
如果您的 3D 向量是 (1, 2, 3) -- 在 XY 平面上 X = 1,Y = 2。
然后如果你规范化 (1, 2) => (1/sqrt(5), 2/sqrt(5))
然后您可以使用 atan2(2/sqrt(5), 1/sqrt(5) 来计算航向的弧度 Angular
关于javascript - Cesiumjs 从矢量计算俯仰、偏航、航向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50997196/