generated from ztimson/template
42 lines
1.6 KiB
JavaScript
42 lines
1.6 KiB
JavaScript
export const rad = (degrees) => (degrees * Math.PI) / 180;
|
|
export const deg = (radians) => (radians * 180) / Math.PI;
|
|
export const wrap360 = (degrees) => ((degrees % 360) + 360) % 360;
|
|
export const wrap180 = (degrees) => ((degrees + 180) % 360 + 360) % 360 - 180;
|
|
|
|
/** Convert azimuth clockwise from north and altitude above the horizon to a unit ENU vector. */
|
|
export function azAltToVec(az, alt) {
|
|
const a = rad(az), e = rad(alt), ce = Math.cos(e);
|
|
return [ce * Math.sin(a), ce * Math.cos(a), Math.sin(e)];
|
|
}
|
|
|
|
/** Convert an east/north/up vector to azimuth clockwise from north and altitude. */
|
|
export function vecToAzAlt(vector) {
|
|
const [east, north, up] = vector;
|
|
const horizontal = Math.hypot(east, north);
|
|
return { az: wrap360(deg(Math.atan2(east, north))), alt: deg(Math.atan2(up, horizontal)) };
|
|
}
|
|
|
|
/** Quaternion [x,y,z,w] conjugate. */
|
|
export function quatConj([x, y, z, w]) {
|
|
return [-x, -y, -z, w];
|
|
}
|
|
|
|
/** Rotate a 3D vector by quaternion [x,y,z,w]. */
|
|
export function quatRotate([x, y, z, w], [vx, vy, vz]) {
|
|
const tx = 2 * (y * vz - z * vy);
|
|
const ty = 2 * (z * vx - x * vz);
|
|
const tz = 2 * (x * vy - y * vx);
|
|
return [
|
|
vx + w * tx + (y * tz - z * ty),
|
|
vy + w * ty + (z * tx - x * tz),
|
|
vz + w * tz + (x * ty - y * tx),
|
|
];
|
|
}
|
|
|
|
/** Great-circle angular separation of two azimuth/altitude positions, in degrees. */
|
|
export function angularSeparation(az1, alt1, az2, alt2) {
|
|
const a1 = rad(alt1), a2 = rad(alt2), da = rad(wrap180(az2 - az1));
|
|
const cosSep = Math.sin(a1) * Math.sin(a2) + Math.cos(a1) * Math.cos(a2) * Math.cos(da);
|
|
return deg(Math.acos(Math.max(-1, Math.min(1, cosSep))));
|
|
}
|