-
Notifications
You must be signed in to change notification settings - Fork 73
/
Copy pathcamera.js
126 lines (99 loc) · 5.09 KB
/
camera.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
camera.js - by Don Cross - 2021-03-26
Example Node.js program for Astronomy Engine:
https://github.com/cosinekitty/astronomy
Given an observer's location on the Earth and a date/time,
calculates the angle of the sunlit side of the Moon as
seen through a camera aimed at it.
To execute, run the command:
node camera latitude longitude [date]
*/
const Astronomy = require('./astronomy.js');
function ParseNumber(text, name) {
const x = Number(text);
if (!Number.isFinite(x)) {
console.error(`ERROR: Not a valid numeric value for ${name}: "${text}"`);
process.exit(1);
}
return x;
}
function ParseDate(text) {
const d = new Date(text);
if (!Number.isFinite(d.getTime())) {
console.error(`ERROR: Not a valid date: "${text}"`);
process.exit(1);
}
return d;
}
function Camera(observer, time) {
const tolerance = 1.0e-15;
const RAD2DEG = 57.295779513082321;
// Calculate the topocentric equatorial coordinates of date for the Moon.
// Assume aberration does not matter because the Moon is so close and has such a small relative velocity.
const moon_equ = Astronomy.Equator(Astronomy.Body.Moon, time, observer, true, false);
// Also calculate the Sun's topocentric position in the same coordinate system.
const sun_equ = Astronomy.Equator(Astronomy.Body.Sun, time, observer, true, false);
// Get the Moon's horizontal coordinates, so we know how much to pivot azimuth and altitude.
const moon_hor = Astronomy.Horizon(time, observer, moon_equ.ra, moon_equ.dec, false);
console.log(`Moon horizontal position: azimuth = ${moon_hor.azimuth.toFixed(3)}, altitude = ${moon_hor.altitude.toFixed(3)}`);
// Get the rotation matrix that converts equatorial to horizontal coordintes for this place and time.
let rot = Astronomy.Rotation_EQD_HOR(time, observer);
// Modify the rotation matrix in two steps:
// First, rotate the orientation so we are facing the Moon's azimuth.
// We do this by pivoting around the zenith axis.
// Horizontal axes are: 0 = north, 1 = west, 2 = zenith.
// Tricky: because the pivot angle increases counterclockwise, and azimuth
// increases clockwise, we undo the azimuth by adding the positive value.
rot = Astronomy.Pivot(rot, 2, moon_hor.azimuth);
// Second, pivot around the leftward axis to bring the Moon to the camera's altitude level.
// From the point of view of the leftward axis, looking toward the camera,
// adding the angle is the correct sense for subtracting the altitude.
rot = Astronomy.Pivot(rot, 1, moon_hor.altitude);
// As a sanity check, apply this rotation to the Moon's equatorial (EQD) coordinates and verify x=0, y=0.
let vec = Astronomy.RotateVector(rot, moon_equ.vec);
// Convert to unit vector.
const radius = vec.Length();
vec.x /= radius;
vec.y /= radius;
vec.z /= radius;
console.log(`Moon check: x = ${vec.x.toFixed(6)}, y = ${Math.abs(vec.y).toFixed(6)}, z = ${Math.abs(vec.z).toFixed(6)}`);
if (!Number.isFinite(vec.x) || Math.abs(vec.x - 1.0) > tolerance) {
console.error("Excessive error in moon check (x).");
return 1;
}
if (!Number.isFinite(vec.y) || Math.abs(vec.y) > tolerance) {
console.error("Excessive error in moon check (y).");
return 1;
}
if (!Number.isFinite(vec.z) || Math.abs(vec.z) > tolerance) {
console.error("Excessive error in moon check (z).");
return 1;
}
// Apply the same rotation to the Sun's equatorial vector.
// The x- and y-coordinates now tell us which side appears sunlit in the camera!
vec = Astronomy.RotateVector(rot, sun_equ.vec);
// Don't bother normalizing the Sun vector, because in AU it will be close to unit anyway.
console.log(`Sun vector: x = ${vec.x.toFixed(6)}, y = ${vec.y.toFixed(6)}, z = ${vec.z.toFixed(6)}`);
// Calculate the tilt angle of the sunlit side, as seen by the camera.
// The x-axis is now pointing directly at the object, z is up in the camera image, y is to the left.
const tilt = RAD2DEG * Math.atan2(vec.y, vec.z);
console.log(`Tilt angle of sunlit side of the Moon = ${tilt.toFixed(3)} degrees counterclockwise from up.`);
const illum = Astronomy.Illumination(Astronomy.Body.Moon, time);
console.log(`Moon magnitude = ${illum.mag.toFixed(2)}, phase angle = ${illum.phase_angle.toFixed(2)} degrees.`);
const angle = Astronomy.AngleFromSun(Astronomy.Body.Moon, time);
console.log(`Angle between Moon and Sun as seen from Earth = ${angle.toFixed(2)} degrees.`);
}
function Demo() {
if (process.argv.length === 4 || process.argv.length === 5) {
const latitude = ParseNumber(process.argv[2]);
const longitude = ParseNumber(process.argv[3]);
const observer = new Astronomy.Observer(latitude, longitude, 0);
const time = Astronomy.MakeTime((process.argv.length === 5) ? ParseDate(process.argv[4]) : new Date());
Camera(observer, time);
process.exit(0);
} else {
console.log('USAGE: node camera latitude longitude [date]');
process.exit(1);
}
}
Demo();