Учитывая два следующих входа:
- точка на сфере (как наблюдатель на Земле);
- и матрица мираобъекта в космосе (положение и ориентация спутника),
как получить азимут и угол места объекта в касательном пространстве точки на сфере (высота и азимут, на которые должен смотреть наблюдатель)? В частности, когда объект находится точно в зените, поворот рыскания (вращение вокруг вертикальной оси) должен учитывать азимут (так что, хотя наблюдатель смотрит прямо вверх, его плечи будут смотреть на тот же азимут, что и объект).
Математика, которую я до сих пор пробовал:
- , чтобы поместить спутник в касательное пространство (умножить его мировую матрицу на обратную матрицу касательного пространства наГлобус). Или то же самое с кватернионами. Поворот эйлера затем выводится из результирующей матрицы (или результирующего кватерниона) с приоритетом "ZXY", а Z и X интерпретируются как азимут и угол места. Но это дает неправильные числа, так как часть вращения, кажется, часто интерпретируется как крен (вращение оси Y), который я хочу равным нулю.
- Интуитивный подход также состоит в том, чтобы вычислить угол между вектором наблюдателя и положением объекта с вертикальной осью, чтобы вывести высоту;в то время как азимут задается углом между касательным севером и предполагаемым положением объекта на «касательной земле» (плюс еще немного математики, чтобы отточить этот конкретный вывод). Но этот подход не работает для случая объекта в зените.
Ресурсы существуют онлайн, но не с этими конкретными входными данными и необходимостью поддержки случая зенита.
Между прочим, программа написана на машинописном языке для three.js, поэтому для первого решения, описанного выше, код выглядит следующим образом:
function getRotationAtPoint(
object: THREE.Object3D,
point: THREE.Vector3
): { azimuth: number, elevation: number } {
// 1. Get the matrix of the tangent space of the observer.
const tangentSpaceMatrix = new THREE.Matrix4();
const baseTangentSpaceAxes = getBaseTangentAxesOnSphere(point);
tangentSpaceMatrix.makeBasis(...baseTangentSpaceAxes);
// 2. Tranform the object's matrix in tangent space of observer.
const inverseMatrix = new THREE.Matrix4().getInverse(tangentSpaceMatrix);
const objectMatrix = object.matrixWorld.clone().multiply(inverseMatrix);
// 3. Get the angles.
const euler = new THREE.Euler().setFromRotationMatrix(objectMatrix);
return {
azimuth: euler.z,
elevation: euler.x
};
}
Кроме того, Three.js предлагает ссылки на верхнюю ось * 1031. * в некоторых случаях, однако программа, с которой я имею дело, вычисляет все непосредственно в матрицах объектов, и оси вверх нельзя доверять.