@johnmorrisdotca/chikyu-earth 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/NOTICE.md +11 -0
  3. package/README.md +172 -27
  4. package/dist/countries.d.ts +11 -0
  5. package/dist/countries.js +11 -0
  6. package/dist/element.d.ts +18 -0
  7. package/dist/element.js +15 -2
  8. package/dist/globe.d.ts +15 -1
  9. package/dist/globe.js +15 -1
  10. package/dist/index.d.ts +12 -1
  11. package/dist/index.js +12 -1
  12. package/dist/markers/cluster.d.ts +27 -0
  13. package/dist/markers/cluster.js +16 -0
  14. package/dist/markers/labels.d.ts +40 -0
  15. package/dist/markers/labels.js +18 -0
  16. package/dist/markers/layer.d.ts +80 -0
  17. package/dist/markers/layer.js +21 -0
  18. package/dist/markers/project.d.ts +63 -2
  19. package/dist/markers/project.js +52 -2
  20. package/dist/markers/types.d.ts +48 -3
  21. package/dist/realistic/earth.d.ts +30 -5
  22. package/dist/realistic/earth.js +41 -134
  23. package/dist/realistic/element.d.ts +47 -7
  24. package/dist/realistic/element.js +48 -44
  25. package/dist/realistic/gate.d.ts +45 -1
  26. package/dist/realistic/gate.js +33 -1
  27. package/dist/realistic/shaders.d.ts +9 -4
  28. package/dist/realistic/shaders.js +54 -9
  29. package/dist/realistic/shared.d.ts +23 -0
  30. package/dist/realistic/shared.js +51 -0
  31. package/dist/realistic/sun.d.ts +40 -3
  32. package/dist/realistic/sun.js +40 -3
  33. package/dist/realistic/textures.d.ts +40 -0
  34. package/dist/realistic/textures.js +141 -0
  35. package/dist/realistic/tiers.d.ts +80 -6
  36. package/dist/realistic/tiers.js +69 -5
  37. package/dist/rotate.d.ts +59 -4
  38. package/dist/rotate.js +59 -4
  39. package/dist/space/element.d.ts +134 -0
  40. package/dist/space/element.js +394 -0
  41. package/dist/space/ephemeris.d.ts +151 -0
  42. package/dist/space/ephemeris.js +162 -0
  43. package/dist/space/index.d.ts +3 -0
  44. package/dist/space/index.js +5 -0
  45. package/dist/space/scale.d.ts +124 -0
  46. package/dist/space/scale.js +141 -0
  47. package/dist/space/scene.d.ts +131 -0
  48. package/dist/space/scene.js +295 -0
  49. package/dist/styles.d.ts +65 -2
  50. package/dist/styles.js +43 -2
  51. package/dist/textures/moon-1024.webp +0 -0
  52. package/dist/textures/moon-2048.webp +0 -0
  53. package/dist/types.d.ts +55 -5
  54. package/dist/view.d.ts +63 -4
  55. package/dist/view.js +52 -4
  56. package/package.json +55 -8
@@ -0,0 +1,151 @@
1
+ /**
2
+ * A position or direction as `[x, y, z]`, in the scene's axes (x toward the vernal equinox, y north).
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import type { Vec3 } from "@johnmorrisdotca/chikyu-earth/space";
7
+ *
8
+ * const origin: Vec3 = [0, 0, 0];
9
+ * console.log(origin);
10
+ * ```
11
+ */
12
+ export type Vec3 = [number, number, number];
13
+ /**
14
+ * The planets drawn, nearest the Sun first.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { PLANETS } from "@johnmorrisdotca/chikyu-earth/space";
19
+ *
20
+ * console.log(PLANETS.join(", "));
21
+ * ```
22
+ */
23
+ export declare const PLANETS: readonly ["Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"];
24
+ /**
25
+ * One of the seven planets drawn, by name.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * import { orbitPath, type PlanetName } from "@johnmorrisdotca/chikyu-earth/space";
30
+ *
31
+ * const planet: PlanetName = "Mars";
32
+ * console.log(orbitPath(planet, Date.UTC(2026, 10, 2), 8).length);
33
+ * ```
34
+ */
35
+ export type PlanetName = (typeof PLANETS)[number];
36
+ /**
37
+ * Where everything is at one moment: positions in astronomical units from the Earth's centre, in scene axes (x to the vernal equinox, y north, z toward -y of the equator).
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * import { frameAt, type Frame } from "@johnmorrisdotca/chikyu-earth/space";
42
+ *
43
+ * const frame: Frame = frameAt(Date.UTC(2026, 10, 2, 12));
44
+ * console.log(Object.keys(frame.planets).length, frame.spin.toFixed(0));
45
+ * ```
46
+ */
47
+ export interface Frame {
48
+ ms: number;
49
+ sun: Vec3;
50
+ moon: Vec3;
51
+ planets: Record<PlanetName, Vec3>;
52
+ /** Greenwich sidereal time, in degrees: how far the Earth has turned against the stars. */
53
+ spin: number;
54
+ }
55
+ /**
56
+ * The Earth's radius in kilometres, the unit of the scene's distances.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * import { EARTH_RADIUS_KM } from "@johnmorrisdotca/chikyu-earth/space";
61
+ *
62
+ * console.log(EARTH_RADIUS_KM);
63
+ * ```
64
+ */
65
+ export declare const EARTH_RADIUS_KM = 6371;
66
+ /**
67
+ * Earth radii in one astronomical unit.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * import { AU_IN_EARTH_RADII } from "@johnmorrisdotca/chikyu-earth/space";
72
+ *
73
+ * console.log(Math.round(AU_IN_EARTH_RADII));
74
+ * ```
75
+ */
76
+ export declare const AU_IN_EARTH_RADII: number;
77
+ /**
78
+ * The state of the sky at `ms`: nine vectors and an angle, in a few tenths of a millisecond. It needs astronomy-engine (an optional peer dependency).
79
+ *
80
+ * @param ms - A moment, in milliseconds since the Unix epoch.
81
+ * @returns The Sun, the Moon and the planets as seen from the Earth's centre, and how far the Earth has turned.
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * import { frameAt } from "@johnmorrisdotca/chikyu-earth/space";
86
+ *
87
+ * const frame = frameAt(Date.UTC(2026, 10, 2, 12));
88
+ * console.log(frame.moon.map((n) => n.toFixed(4)));
89
+ * ```
90
+ */
91
+ export declare function frameAt(ms: number): Frame;
92
+ /**
93
+ * A frame between two others, `t` from 0 to 1. The spin goes the short way round, so a step under half a turn is right.
94
+ *
95
+ * @param a - The earlier frame.
96
+ * @param b - The later frame.
97
+ * @param t - How far from `a` to `b`, from 0 to 1.
98
+ * @returns The frame at that fraction.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * import { blend, frameAt } from "@johnmorrisdotca/chikyu-earth/space";
103
+ *
104
+ * const start = Date.UTC(2026, 10, 2);
105
+ * const middle = blend(frameAt(start), frameAt(start + 1000), 0.5);
106
+ * console.log(middle.ms - start);
107
+ * ```
108
+ */
109
+ export declare function blend(a: Frame, b: Frame, t: number): Frame;
110
+ /**
111
+ * Answers for any moment from two real ones: `at(ms)` asks astronomy-engine only when `ms` leaves the span the last two answers cover, and then looks
112
+ * `stepMs` ahead, so playing time at a steady rate costs one pair of lookups every `stepMs` and every draw in between is arithmetic.
113
+ *
114
+ * @param initialStepMs - How far ahead the second answer looks, in milliseconds.
115
+ * @returns A track: `at(ms)` for a frame, `lookups` for how many times the ephemeris was asked, `reset()` and `setStep(ms)`.
116
+ *
117
+ * @example
118
+ * ```ts
119
+ * import { createTrack } from "@johnmorrisdotca/chikyu-earth/space";
120
+ *
121
+ * const track = createTrack(1000);
122
+ * const start = Date.UTC(2026, 10, 2);
123
+ * for (let step = 0; step < 10; step += 1) track.at(start + step * 50);
124
+ * console.log(track.lookups);
125
+ * ```
126
+ */
127
+ export declare function createTrack(initialStepMs?: number): {
128
+ at(ms: number): Frame;
129
+ /** How many times astronomy-engine has been asked for a frame. */
130
+ readonly lookups: number;
131
+ reset(): void;
132
+ /** Look further ahead (a faster game clock): the next lookup uses it. */
133
+ setStep(ms: number): void;
134
+ };
135
+ /** The path a planet takes round the Sun, as `count` points around the orbit that starts where the planet is at `ms`, relative to the Sun (scene axes, AU).
136
+ *
137
+ * @param name - The planet.
138
+ * @param ms - The moment the orbit starts at, in milliseconds since the Unix epoch.
139
+ * @param count - How many segments to cut the orbit into.
140
+ * @returns `count + 1` points, the last on the first.
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * import { orbitPath } from "@johnmorrisdotca/chikyu-earth/space";
145
+ *
146
+ * const points = orbitPath("Jupiter", Date.UTC(2026, 10, 2), 12);
147
+ * console.log(points.length);
148
+ * ```
149
+ */
150
+ export declare function orbitPath(name: PlanetName, ms: number, count?: number): Vec3[];
151
+ /** The Earth's own place relative to the Sun, for placing the orbits round the Sun's place in the Earth-centred scene. */
@@ -0,0 +1,162 @@
1
+ // Where the Sun, the Moon and the planets are, as seen from the centre of the Earth, for any date. astronomy-engine (MIT) does the sums; this file asks it
2
+ // for a handful of vectors, keeps them in the scene's axes, and lets a draw interpolate between two answers a second apart instead of asking at every frame.
3
+ import { Body, GeoVector, HelioVector, SiderealTime } from "astronomy-engine";
4
+ /**
5
+ * The planets drawn, nearest the Sun first.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { PLANETS } from "@johnmorrisdotca/chikyu-earth/space";
10
+ *
11
+ * console.log(PLANETS.join(", "));
12
+ * ```
13
+ */
14
+ export const PLANETS = ["Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"];
15
+ /** Equatorial J2000 axes (x to the vernal equinox, z to the north pole) to the scene's (y up). */
16
+ const scene = (v) => [v.x, v.z, -v.y];
17
+ const AU_KM = 149_597_870.7;
18
+ /**
19
+ * The Earth's radius in kilometres, the unit of the scene's distances.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * import { EARTH_RADIUS_KM } from "@johnmorrisdotca/chikyu-earth/space";
24
+ *
25
+ * console.log(EARTH_RADIUS_KM);
26
+ * ```
27
+ */
28
+ export const EARTH_RADIUS_KM = 6371;
29
+ /**
30
+ * Earth radii in one astronomical unit.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * import { AU_IN_EARTH_RADII } from "@johnmorrisdotca/chikyu-earth/space";
35
+ *
36
+ * console.log(Math.round(AU_IN_EARTH_RADII));
37
+ * ```
38
+ */
39
+ export const AU_IN_EARTH_RADII = AU_KM / EARTH_RADIUS_KM;
40
+ /**
41
+ * The state of the sky at `ms`: nine vectors and an angle, in a few tenths of a millisecond. It needs astronomy-engine (an optional peer dependency).
42
+ *
43
+ * @param ms - A moment, in milliseconds since the Unix epoch.
44
+ * @returns The Sun, the Moon and the planets as seen from the Earth's centre, and how far the Earth has turned.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * import { frameAt } from "@johnmorrisdotca/chikyu-earth/space";
49
+ *
50
+ * const frame = frameAt(Date.UTC(2026, 10, 2, 12));
51
+ * console.log(frame.moon.map((n) => n.toFixed(4)));
52
+ * ```
53
+ */
54
+ export function frameAt(ms) {
55
+ const date = new Date(ms);
56
+ const planets = {};
57
+ for (const name of PLANETS)
58
+ planets[name] = scene(GeoVector(Body[name], date, true));
59
+ return {
60
+ ms,
61
+ sun: scene(GeoVector(Body.Sun, date, true)),
62
+ moon: scene(GeoVector(Body.Moon, date, true)),
63
+ planets,
64
+ spin: SiderealTime(date) * 15,
65
+ };
66
+ }
67
+ const lerp3 = (a, b, t) => [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t];
68
+ /**
69
+ * A frame between two others, `t` from 0 to 1. The spin goes the short way round, so a step under half a turn is right.
70
+ *
71
+ * @param a - The earlier frame.
72
+ * @param b - The later frame.
73
+ * @param t - How far from `a` to `b`, from 0 to 1.
74
+ * @returns The frame at that fraction.
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * import { blend, frameAt } from "@johnmorrisdotca/chikyu-earth/space";
79
+ *
80
+ * const start = Date.UTC(2026, 10, 2);
81
+ * const middle = blend(frameAt(start), frameAt(start + 1000), 0.5);
82
+ * console.log(middle.ms - start);
83
+ * ```
84
+ */
85
+ export function blend(a, b, t) {
86
+ const planets = {};
87
+ for (const name of PLANETS)
88
+ planets[name] = lerp3(a.planets[name], b.planets[name], t);
89
+ let turn = b.spin - a.spin;
90
+ turn -= 360 * Math.round(turn / 360);
91
+ return { ms: a.ms + (b.ms - a.ms) * t, sun: lerp3(a.sun, b.sun, t), moon: lerp3(a.moon, b.moon, t), planets, spin: a.spin + turn * t };
92
+ }
93
+ /**
94
+ * Answers for any moment from two real ones: `at(ms)` asks astronomy-engine only when `ms` leaves the span the last two answers cover, and then looks
95
+ * `stepMs` ahead, so playing time at a steady rate costs one pair of lookups every `stepMs` and every draw in between is arithmetic.
96
+ *
97
+ * @param initialStepMs - How far ahead the second answer looks, in milliseconds.
98
+ * @returns A track: `at(ms)` for a frame, `lookups` for how many times the ephemeris was asked, `reset()` and `setStep(ms)`.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * import { createTrack } from "@johnmorrisdotca/chikyu-earth/space";
103
+ *
104
+ * const track = createTrack(1000);
105
+ * const start = Date.UTC(2026, 10, 2);
106
+ * for (let step = 0; step < 10; step += 1) track.at(start + step * 50);
107
+ * console.log(track.lookups);
108
+ * ```
109
+ */
110
+ export function createTrack(initialStepMs = 1000) {
111
+ let stepMs = initialStepMs;
112
+ let a;
113
+ let b;
114
+ let lookups = 0;
115
+ return {
116
+ at(ms) {
117
+ if (!a || !b || ms < a.ms || ms > b.ms) {
118
+ a = frameAt(ms);
119
+ b = frameAt(ms + stepMs);
120
+ lookups += 2;
121
+ }
122
+ return blend(a, b, (ms - a.ms) / (b.ms - a.ms));
123
+ },
124
+ /** How many times astronomy-engine has been asked for a frame. */
125
+ get lookups() {
126
+ return lookups;
127
+ },
128
+ reset() {
129
+ a = undefined;
130
+ b = undefined;
131
+ },
132
+ /** Look further ahead (a faster game clock): the next lookup uses it. */
133
+ setStep(ms) {
134
+ stepMs = Math.max(1, ms);
135
+ a = undefined;
136
+ b = undefined;
137
+ },
138
+ };
139
+ }
140
+ /** The path a planet takes round the Sun, as `count` points around the orbit that starts where the planet is at `ms`, relative to the Sun (scene axes, AU).
141
+ *
142
+ * @param name - The planet.
143
+ * @param ms - The moment the orbit starts at, in milliseconds since the Unix epoch.
144
+ * @param count - How many segments to cut the orbit into.
145
+ * @returns `count + 1` points, the last on the first.
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * import { orbitPath } from "@johnmorrisdotca/chikyu-earth/space";
150
+ *
151
+ * const points = orbitPath("Jupiter", Date.UTC(2026, 10, 2), 12);
152
+ * console.log(points.length);
153
+ * ```
154
+ */
155
+ export function orbitPath(name, ms, count = 96) {
156
+ const periodDays = { Mercury: 87.97, Venus: 224.7, Mars: 686.98, Jupiter: 4332.6, Saturn: 10759, Uranus: 30688, Neptune: 60182 }[name];
157
+ const points = [];
158
+ for (let i = 0; i <= count; i += 1)
159
+ points.push(scene(HelioVector(Body[name], new Date(ms + (i / count) * periodDays * 86_400_000))));
160
+ return points;
161
+ }
162
+ /** The Earth's own place relative to the Sun, for placing the orbits round the Sun's place in the Earth-centred scene. */
@@ -0,0 +1,3 @@
1
+ export { AU_IN_EARTH_RADII, blend, createTrack, EARTH_RADIUS_KM, frameAt, orbitPath, PLANETS, type Frame, type PlanetName, type Vec3 } from "./ephemeris.ts";
2
+ export { compress, MOON_COMPRESSED, placeAround, placeMoon, placeSun, RADIUS, SUN_COMPRESSED, truePosition, type ScaleMode } from "./scale.ts";
3
+ export { plainPainter, type BodyDrawing, type BodyPainter } from "./scene.ts";
@@ -0,0 +1,5 @@
1
+ // The space view's pure parts: where the bodies are (astronomy-engine, an optional peer) and the two scales. They import on a server. The element is
2
+ // `@johnmorrisdotca/chikyu-earth/space/element`.
3
+ export { AU_IN_EARTH_RADII, blend, createTrack, EARTH_RADIUS_KM, frameAt, orbitPath, PLANETS } from "./ephemeris.js";
4
+ export { compress, MOON_COMPRESSED, placeAround, placeMoon, placeSun, RADIUS, SUN_COMPRESSED, truePosition } from "./scale.js";
5
+ export { plainPainter } from "./scene.js";
@@ -0,0 +1,124 @@
1
+ import { type Vec3 } from "./ephemeris.ts";
2
+ /**
3
+ * The scale the space view is drawn in: `compressed` squeezes the distances so the Moon, the Sun and Neptune fit one view, and `true` keeps the real ones.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * import { placeMoon, type ScaleMode } from "@johnmorrisdotca/chikyu-earth/space";
8
+ *
9
+ * const mode: ScaleMode = "compressed";
10
+ * console.log(placeMoon(mode, [0.00257, 0, 0]));
11
+ * ```
12
+ */
13
+ export type ScaleMode = "compressed" | "true";
14
+ /**
15
+ * The Moon's distance in a compressed view, in Earth radii (the true one is about 60).
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { MOON_COMPRESSED } from "@johnmorrisdotca/chikyu-earth/space";
20
+ *
21
+ * console.log(MOON_COMPRESSED);
22
+ * ```
23
+ */
24
+ export declare const MOON_COMPRESSED = 10;
25
+ /**
26
+ * The Sun's distance from the Earth in a compressed view, in Earth radii (the true one is about 23,500). One astronomical unit is this long there.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import { SUN_COMPRESSED } from "@johnmorrisdotca/chikyu-earth/space";
31
+ *
32
+ * console.log(SUN_COMPRESSED);
33
+ * ```
34
+ */
35
+ export declare const SUN_COMPRESSED = 44;
36
+ /**
37
+ * A place in astronomical units from the Earth's centre, at true distance, in Earth radii.
38
+ *
39
+ * @param v - The place, in astronomical units.
40
+ * @returns The same direction, in Earth radii.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import { truePosition } from "@johnmorrisdotca/chikyu-earth/space";
45
+ *
46
+ * console.log(truePosition([0.00257, 0, 0]).map(Math.round));
47
+ * ```
48
+ */
49
+ export declare const truePosition: (v: Vec3) => Vec3;
50
+ /**
51
+ * The same direction at a compressed distance from the Earth: the Moon is 10 Earth radii away, and a body k times further than the Moon is k^0.25 times as far here.
52
+ *
53
+ * @param v - The place, in astronomical units from the Earth's centre.
54
+ * @returns The place in Earth radii, compressed; the centre stays at the centre.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * import { compress } from "@johnmorrisdotca/chikyu-earth/space";
59
+ *
60
+ * console.log(compress([0.00257, 0, 0]), compress([0, 0, 0]));
61
+ * ```
62
+ */
63
+ export declare function compress(v: Vec3): Vec3;
64
+ /**
65
+ * The Moon, from the Earth's centre.
66
+ *
67
+ * @param mode - The scale.
68
+ * @param geo - The Moon's place in astronomical units from the Earth's centre.
69
+ * @returns Where to draw it, in Earth radii.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * import { placeMoon } from "@johnmorrisdotca/chikyu-earth/space";
74
+ *
75
+ * console.log(placeMoon("true", [0.00257, 0, 0]).map(Math.round));
76
+ * ```
77
+ */
78
+ export declare const placeMoon: (mode: ScaleMode, geo: Vec3) => Vec3;
79
+ /**
80
+ * The Sun, from the Earth's centre: in a compressed view always 44 Earth radii away, in its real direction.
81
+ *
82
+ * @param mode - The scale.
83
+ * @param geo - The Sun's place in astronomical units from the Earth's centre.
84
+ * @returns Where to draw it, in Earth radii.
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * import { placeSun } from "@johnmorrisdotca/chikyu-earth/space";
89
+ *
90
+ * console.log(placeSun("compressed", [1, 0, 0]));
91
+ * ```
92
+ */
93
+ export declare function placeSun(mode: ScaleMode, geo: Vec3): Vec3;
94
+ /**
95
+ * A place `helio` astronomical units from the Sun (a planet, or a point on its orbit), round the Sun at `sun`. True: as it is. Compressed: the same direction from
96
+ * the Sun, at 44 Earth radii times its distance in astronomical units to the power 0.45, so the Earth's own orbit is the 44 and Neptune's is about 200 (30 times as far, really).
97
+ *
98
+ * @param mode - The scale.
99
+ * @param sun - Where the Sun is drawn, in Earth radii.
100
+ * @param helio - The place in astronomical units from the Sun.
101
+ * @returns Where to draw the place, in Earth radii from the Earth's centre.
102
+ *
103
+ * @example
104
+ * ```ts
105
+ * import { placeAround } from "@johnmorrisdotca/chikyu-earth/space";
106
+ *
107
+ * console.log(placeAround("compressed", [44, 0, 0], [1, 0, 0]));
108
+ * ```
109
+ */
110
+ export declare function placeAround(mode: ScaleMode, sun: Vec3, helio: Vec3): Vec3;
111
+ /**
112
+ * Radii in Earth radii: the real ones, and ones large enough to see in a compressed view.
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * import { RADIUS } from "@johnmorrisdotca/chikyu-earth/space";
117
+ *
118
+ * console.log(RADIUS["Moon"]);
119
+ * ```
120
+ */
121
+ export declare const RADIUS: Record<string, {
122
+ true: number;
123
+ compressed: number;
124
+ }>;
@@ -0,0 +1,141 @@
1
+ // The two scales the space view can show. The true one is the Earth's radius for a unit and the real distances in it; the compressed one keeps every
2
+ // direction but squeezes the distances so that the Moon, the Sun and Neptune fit one view. Pure.
3
+ import { AU_IN_EARTH_RADII } from "./ephemeris.js";
4
+ const MOON_AU = 0.00257;
5
+ /**
6
+ * The Moon's distance in a compressed view, in Earth radii (the true one is about 60).
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { MOON_COMPRESSED } from "@johnmorrisdotca/chikyu-earth/space";
11
+ *
12
+ * console.log(MOON_COMPRESSED);
13
+ * ```
14
+ */
15
+ export const MOON_COMPRESSED = 10;
16
+ /**
17
+ * The Sun's distance from the Earth in a compressed view, in Earth radii (the true one is about 23,500). One astronomical unit is this long there.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * import { SUN_COMPRESSED } from "@johnmorrisdotca/chikyu-earth/space";
22
+ *
23
+ * console.log(SUN_COMPRESSED);
24
+ * ```
25
+ */
26
+ export const SUN_COMPRESSED = 44;
27
+ const length = (v) => Math.hypot(v[0], v[1], v[2]);
28
+ const scaled = (v, k) => [v[0] * k, v[1] * k, v[2] * k];
29
+ /**
30
+ * A place in astronomical units from the Earth's centre, at true distance, in Earth radii.
31
+ *
32
+ * @param v - The place, in astronomical units.
33
+ * @returns The same direction, in Earth radii.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * import { truePosition } from "@johnmorrisdotca/chikyu-earth/space";
38
+ *
39
+ * console.log(truePosition([0.00257, 0, 0]).map(Math.round));
40
+ * ```
41
+ */
42
+ export const truePosition = (v) => scaled(v, AU_IN_EARTH_RADII);
43
+ /**
44
+ * The same direction at a compressed distance from the Earth: the Moon is 10 Earth radii away, and a body k times further than the Moon is k^0.25 times as far here.
45
+ *
46
+ * @param v - The place, in astronomical units from the Earth's centre.
47
+ * @returns The place in Earth radii, compressed; the centre stays at the centre.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * import { compress } from "@johnmorrisdotca/chikyu-earth/space";
52
+ *
53
+ * console.log(compress([0.00257, 0, 0]), compress([0, 0, 0]));
54
+ * ```
55
+ */
56
+ export function compress(v) {
57
+ const l = length(v);
58
+ return l === 0 ? [0, 0, 0] : scaled(v, (MOON_COMPRESSED * (l / MOON_AU) ** 0.25) / l);
59
+ }
60
+ /**
61
+ * The Moon, from the Earth's centre.
62
+ *
63
+ * @param mode - The scale.
64
+ * @param geo - The Moon's place in astronomical units from the Earth's centre.
65
+ * @returns Where to draw it, in Earth radii.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * import { placeMoon } from "@johnmorrisdotca/chikyu-earth/space";
70
+ *
71
+ * console.log(placeMoon("true", [0.00257, 0, 0]).map(Math.round));
72
+ * ```
73
+ */
74
+ export const placeMoon = (mode, geo) => (mode === "true" ? truePosition(geo) : compress(geo));
75
+ /**
76
+ * The Sun, from the Earth's centre: in a compressed view always 44 Earth radii away, in its real direction.
77
+ *
78
+ * @param mode - The scale.
79
+ * @param geo - The Sun's place in astronomical units from the Earth's centre.
80
+ * @returns Where to draw it, in Earth radii.
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * import { placeSun } from "@johnmorrisdotca/chikyu-earth/space";
85
+ *
86
+ * console.log(placeSun("compressed", [1, 0, 0]));
87
+ * ```
88
+ */
89
+ export function placeSun(mode, geo) {
90
+ if (mode === "true")
91
+ return truePosition(geo);
92
+ const l = length(geo);
93
+ return l === 0 ? [0, 0, 0] : scaled(geo, SUN_COMPRESSED / l);
94
+ }
95
+ /**
96
+ * A place `helio` astronomical units from the Sun (a planet, or a point on its orbit), round the Sun at `sun`. True: as it is. Compressed: the same direction from
97
+ * the Sun, at 44 Earth radii times its distance in astronomical units to the power 0.45, so the Earth's own orbit is the 44 and Neptune's is about 200 (30 times as far, really).
98
+ *
99
+ * @param mode - The scale.
100
+ * @param sun - Where the Sun is drawn, in Earth radii.
101
+ * @param helio - The place in astronomical units from the Sun.
102
+ * @returns Where to draw the place, in Earth radii from the Earth's centre.
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * import { placeAround } from "@johnmorrisdotca/chikyu-earth/space";
107
+ *
108
+ * console.log(placeAround("compressed", [44, 0, 0], [1, 0, 0]));
109
+ * ```
110
+ */
111
+ export function placeAround(mode, sun, helio) {
112
+ if (mode === "true")
113
+ return [sun[0] + helio[0] * AU_IN_EARTH_RADII, sun[1] + helio[1] * AU_IN_EARTH_RADII, sun[2] + helio[2] * AU_IN_EARTH_RADII];
114
+ const l = length(helio);
115
+ if (l === 0)
116
+ return sun;
117
+ const d = (SUN_COMPRESSED * l ** 0.45) / l;
118
+ return [sun[0] + helio[0] * d, sun[1] + helio[1] * d, sun[2] + helio[2] * d];
119
+ }
120
+ /**
121
+ * Radii in Earth radii: the real ones, and ones large enough to see in a compressed view.
122
+ *
123
+ * @example
124
+ * ```ts
125
+ * import { RADIUS } from "@johnmorrisdotca/chikyu-earth/space";
126
+ *
127
+ * console.log(RADIUS["Moon"]);
128
+ * ```
129
+ */
130
+ export const RADIUS = {
131
+ Sun: { true: 109.1, compressed: 5 },
132
+ Earth: { true: 1, compressed: 1 },
133
+ Moon: { true: 0.2727, compressed: 0.9 },
134
+ Mercury: { true: 0.383, compressed: 0.5 },
135
+ Venus: { true: 0.949, compressed: 0.8 },
136
+ Mars: { true: 0.532, compressed: 0.6 },
137
+ Jupiter: { true: 10.97, compressed: 1.8 },
138
+ Saturn: { true: 9.14, compressed: 1.6 },
139
+ Uranus: { true: 3.98, compressed: 1.0 },
140
+ Neptune: { true: 3.86, compressed: 1.0 },
141
+ };