Skip to content

Commit 349e340

Browse files
committed
Added nodejs demo for calculating equatorial coordinates from horizontal coordinates.
1 parent 5cd0e60 commit 349e340

File tree

4 files changed

+123
-1
lines changed

4 files changed

+123
-1
lines changed

demo/nodejs/equatorial.js

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
equatorial.js - by Don Cross - 2021-03-27
3+
4+
Example Node.js program for Astronomy Engine:
5+
https://github.com/cosinekitty/astronomy
6+
7+
Given an observer's location on the Earth, a
8+
date/time, and horizontal coordinates (azimuth, altitude)
9+
for that observer, this program works backwards
10+
to figure out the equatorial coordinates for that
11+
location in the sky. It provides two solutions:
12+
one that includes atmospheric refraction, another
13+
that ignores atmospheric refraction.
14+
15+
To execute, run the command:
16+
node equatorial latitude longitude azimuth altitude [date]
17+
*/
18+
19+
const Astronomy = require('./astronomy.js');
20+
21+
function ParseNumber(text, name) {
22+
const x = Number(text);
23+
if (!Number.isFinite(x)) {
24+
console.error(`ERROR: Not a valid numeric value for ${name}: "${text}"`);
25+
process.exit(1);
26+
}
27+
return x;
28+
}
29+
30+
function ParseDate(text) {
31+
const d = new Date(text);
32+
if (!Number.isFinite(d.getTime())) {
33+
console.error(`ERROR: Not a valid date: "${text}"`);
34+
process.exit(1);
35+
}
36+
return d;
37+
}
38+
39+
40+
function Format(x, length, digits) {
41+
let s = x.toFixed(digits);
42+
while (s.length < length)
43+
s = ' ' + s;
44+
return s;
45+
}
46+
47+
48+
function Solve(refract, observer, time, azimuth, altitude) {
49+
// Convert the angular horizontal coordinates (azimuth, altitude)
50+
// to a horizontal vector (north, west, zenith).
51+
const hor_sphere = new Astronomy.Spherical(altitude, azimuth, 1);
52+
const refraction_option = refract ? 'normal' : null;
53+
const hor_vec = Astronomy.VectorFromHorizon(hor_sphere, time, refraction_option);
54+
55+
// Make a rotation matrix for this observer and date/time that converts
56+
// horizontal coordinates (HOR) to equatorial coordinates in the J2000 epoch (EQJ).
57+
const rot_hor_eqj = Astronomy.Rotation_HOR_EQJ(time, observer);
58+
59+
// Use the rotation matrix to convert the horizontal vector to an equatorial vector.
60+
const eqj_vec = Astronomy.RotateVector(rot_hor_eqj, hor_vec);
61+
62+
// Convert the equatorial vector to equatorial angular coordinates (RA, DEC).
63+
const eqj = Astronomy.EquatorFromVector(eqj_vec);
64+
65+
// Self-check the answers by converting back to horizontal coordinates,
66+
// using a different algorithm that has been tested to work.
67+
68+
// First we need to convert J2000 equatorial (EQJ) to equator-of-date (EQD),
69+
// because the Horizon function expects EQD.
70+
const rot_eqj_eqd = Astronomy.Rotation_EQJ_EQD(time);
71+
const eqd_vec = Astronomy.RotateVector(rot_eqj_eqd, eqj_vec);
72+
const eqd = Astronomy.EquatorFromVector(eqd_vec);
73+
74+
const check_hor = Astronomy.Horizon(time, observer, eqd.ra, eqd.dec, refraction_option);
75+
const alt_error = Math.abs(check_hor.altitude - altitude);
76+
const az_error = Math.abs(check_hor.azimuth - azimuth);
77+
78+
let line = (refract ? ' yes' : ' no ');
79+
line += ' ' + Format(eqj.ra, 10, 4);
80+
line += ' ' + Format(eqj.dec, 10, 4);
81+
line += ' ' + Format(eqd.ra, 10, 4);
82+
line += ' ' + Format(eqd.dec, 10, 4);
83+
line += ' ' + Format(alt_error, 10, 6);
84+
line += ' ' + Format(az_error, 10, 6);
85+
console.log(line);
86+
}
87+
88+
89+
function Demo() {
90+
if (process.argv.length === 6 || process.argv.length === 7) {
91+
const latitude = ParseNumber(process.argv[2]);
92+
const longitude = ParseNumber(process.argv[3]);
93+
const observer = new Astronomy.Observer(latitude, longitude, 0);
94+
const azimuth = ParseNumber(process.argv[4]);
95+
const altitude = ParseNumber(process.argv[5]);
96+
const time = Astronomy.MakeTime((process.argv.length === 7) ? ParseDate(process.argv[6]) : new Date());
97+
98+
// Print a common header for both solutions.
99+
console.log('Refract? J2000_RA J2000_DEC OFDATE_RA OFDATE_DEC ALT_error AZ_error');
100+
101+
// Solve once ignoring atmospheric refraction.
102+
Solve(false, observer, time, azimuth, altitude);
103+
104+
// Solve again considering atmospheric refraction.
105+
Solve(true, observer, time, azimuth, altitude);
106+
107+
process.exit(0);
108+
} else {
109+
console.log('USAGE: node equatorial latitude longitude azimuth altitude [date]');
110+
process.exit(1);
111+
}
112+
}
113+
114+
Demo();

demo/nodejs/test/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
equatorial.txt
12
camera.txt
23
moonphase.txt
34
positions.txt
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Refract? J2000_RA J2000_DEC OFDATE_RA OFDATE_DEC ALT_error AZ_error
2+
no 22.8101 -19.9671 22.8288 -19.8565 0.000000 0.000000
3+
yes 22.8087 -20.0007 22.8275 -19.8901 0.000000 0.000000

demo/nodejs/test/test

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ Fail()
55
exit 1
66
}
77

8-
rm -f test/{camera,moonphase,positions,riseset,seasons,culminate,horizon,lunar_eclipse}.txt
8+
rm -f test/{equatorial,camera,moonphase,positions,riseset,seasons,culminate,horizon,lunar_eclipse}.txt
9+
10+
echo "Testing example: equatorial.js"
11+
node equatorial.js 38.1256 -89.5544 215.7 23.5 2021-03-27T18:45:00Z > test/equatorial.txt || Fail "Error testing equatorial.js."
12+
diff test/equatorial.txt test/equatorial_correct.txt || Fail "Error comparing equatorial.js output."
913

1014
echo "Testing example: camera.js"
1115
node camera.js 29 -81 2021-03-22T02:45:00Z > test/camera.txt || Fail "Error testing camera.js."

0 commit comments

Comments
 (0)