TLE2ToCZML/node_modules/satellite.js/lib/transforms.js

186 lines
5.4 KiB
JavaScript

/*!
* satellite-js v5.0.0
* (c) 2013 Shashwat Kandadai and UCSC
* https://github.com/shashwatak/satellite-js
* License: MIT
*/
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.degreesLat = degreesLat;
exports.degreesLong = degreesLong;
exports.degreesToRadians = degreesToRadians;
exports.ecfToEci = ecfToEci;
exports.ecfToLookAngles = ecfToLookAngles;
exports.eciToEcf = eciToEcf;
exports.eciToGeodetic = eciToGeodetic;
exports.geodeticToEcf = geodeticToEcf;
exports.radiansLat = radiansLat;
exports.radiansLong = radiansLong;
exports.radiansToDegrees = radiansToDegrees;
var _constants = require("./constants");
function radiansToDegrees(radians) {
return radians * _constants.rad2deg;
}
function degreesToRadians(degrees) {
return degrees * _constants.deg2rad;
}
function degreesLat(radians) {
if (radians < -_constants.pi / 2 || radians > _constants.pi / 2) {
throw new RangeError('Latitude radians must be in range [-pi/2; pi/2].');
}
return radiansToDegrees(radians);
}
function degreesLong(radians) {
if (radians < -_constants.pi || radians > _constants.pi) {
throw new RangeError('Longitude radians must be in range [-pi; pi].');
}
return radiansToDegrees(radians);
}
function radiansLat(degrees) {
if (degrees < -90 || degrees > 90) {
throw new RangeError('Latitude degrees must be in range [-90; 90].');
}
return degreesToRadians(degrees);
}
function radiansLong(degrees) {
if (degrees < -180 || degrees > 180) {
throw new RangeError('Longitude degrees must be in range [-180; 180].');
}
return degreesToRadians(degrees);
}
function geodeticToEcf(geodetic) {
var longitude = geodetic.longitude,
latitude = geodetic.latitude,
height = geodetic.height;
var a = 6378.137;
var b = 6356.7523142;
var f = (a - b) / a;
var e2 = 2 * f - f * f;
var normal = a / Math.sqrt(1 - e2 * (Math.sin(latitude) * Math.sin(latitude)));
var x = (normal + height) * Math.cos(latitude) * Math.cos(longitude);
var y = (normal + height) * Math.cos(latitude) * Math.sin(longitude);
var z = (normal * (1 - e2) + height) * Math.sin(latitude);
return {
x: x,
y: y,
z: z
};
}
function eciToGeodetic(eci, gmst) {
// http://www.celestrak.com/columns/v02n03/
var a = 6378.137;
var b = 6356.7523142;
var R = Math.sqrt(eci.x * eci.x + eci.y * eci.y);
var f = (a - b) / a;
var e2 = 2 * f - f * f;
var longitude = Math.atan2(eci.y, eci.x) - gmst;
while (longitude < -_constants.pi) {
longitude += _constants.twoPi;
}
while (longitude > _constants.pi) {
longitude -= _constants.twoPi;
}
var kmax = 20;
var k = 0;
var latitude = Math.atan2(eci.z, Math.sqrt(eci.x * eci.x + eci.y * eci.y));
var C;
while (k < kmax) {
C = 1 / Math.sqrt(1 - e2 * (Math.sin(latitude) * Math.sin(latitude)));
latitude = Math.atan2(eci.z + a * C * e2 * Math.sin(latitude), R);
k += 1;
}
var height = R / Math.cos(latitude) - a * C;
return {
longitude: longitude,
latitude: latitude,
height: height
};
}
function ecfToEci(ecf, gmst) {
// ccar.colorado.edu/ASEN5070/handouts/coordsys.doc
//
// [X] [C -S 0][X]
// [Y] = [S C 0][Y]
// [Z]eci [0 0 1][Z]ecf
//
var X = ecf.x * Math.cos(gmst) - ecf.y * Math.sin(gmst);
var Y = ecf.x * Math.sin(gmst) + ecf.y * Math.cos(gmst);
var Z = ecf.z;
return {
x: X,
y: Y,
z: Z
};
}
function eciToEcf(eci, gmst) {
// ccar.colorado.edu/ASEN5070/handouts/coordsys.doc
//
// [X] [C -S 0][X]
// [Y] = [S C 0][Y]
// [Z]eci [0 0 1][Z]ecf
//
//
// Inverse:
// [X] [C S 0][X]
// [Y] = [-S C 0][Y]
// [Z]ecf [0 0 1][Z]eci
var x = eci.x * Math.cos(gmst) + eci.y * Math.sin(gmst);
var y = eci.x * -Math.sin(gmst) + eci.y * Math.cos(gmst);
var z = eci.z;
return {
x: x,
y: y,
z: z
};
}
function topocentric(observerGeodetic, satelliteEcf) {
// http://www.celestrak.com/columns/v02n02/
// TS Kelso's method, except I'm using ECF frame
// and he uses ECI.
var longitude = observerGeodetic.longitude,
latitude = observerGeodetic.latitude;
var observerEcf = geodeticToEcf(observerGeodetic);
var rx = satelliteEcf.x - observerEcf.x;
var ry = satelliteEcf.y - observerEcf.y;
var rz = satelliteEcf.z - observerEcf.z;
var topS = Math.sin(latitude) * Math.cos(longitude) * rx + Math.sin(latitude) * Math.sin(longitude) * ry - Math.cos(latitude) * rz;
var topE = -Math.sin(longitude) * rx + Math.cos(longitude) * ry;
var topZ = Math.cos(latitude) * Math.cos(longitude) * rx + Math.cos(latitude) * Math.sin(longitude) * ry + Math.sin(latitude) * rz;
return {
topS: topS,
topE: topE,
topZ: topZ
};
}
/**
* @param {Object} tc
* @param {Number} tc.topS Positive horizontal vector S due south.
* @param {Number} tc.topE Positive horizontal vector E due east.
* @param {Number} tc.topZ Vector Z normal to the surface of the earth (up).
* @returns {Object}
*/
function topocentricToLookAngles(tc) {
var topS = tc.topS,
topE = tc.topE,
topZ = tc.topZ;
var rangeSat = Math.sqrt(topS * topS + topE * topE + topZ * topZ);
var El = Math.asin(topZ / rangeSat);
var Az = Math.atan2(-topE, topS) + _constants.pi;
return {
azimuth: Az,
elevation: El,
rangeSat: rangeSat // Range in km
};
}
function ecfToLookAngles(observerGeodetic, satelliteEcf) {
var topocentricCoords = topocentric(observerGeodetic, satelliteEcf);
return topocentricToLookAngles(topocentricCoords);
}