@johnmorrisdotca/chikyu-earth 0.4.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.
- package/CHANGELOG.md +78 -0
- package/NOTICE.md +39 -1
- package/README.md +199 -24
- package/dist/countries.d.ts +11 -0
- package/dist/countries.js +11 -0
- package/dist/element.d.ts +24 -1
- package/dist/element.js +70 -5
- package/dist/globe.d.ts +15 -1
- package/dist/globe.js +15 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +12 -1
- package/dist/markers/cluster.d.ts +38 -0
- package/dist/markers/cluster.js +42 -0
- package/dist/markers/index.d.ts +5 -0
- package/dist/markers/index.js +6 -0
- package/dist/markers/labels.d.ts +64 -0
- package/dist/markers/labels.js +70 -0
- package/dist/markers/layer.d.ts +129 -0
- package/dist/markers/layer.js +455 -0
- package/dist/markers/project.d.ts +82 -0
- package/dist/markers/project.js +93 -0
- package/dist/markers/types.d.ts +83 -0
- package/dist/markers/types.js +1 -0
- package/dist/realistic/earth.d.ts +81 -0
- package/dist/realistic/earth.js +163 -0
- package/dist/realistic/element.d.ts +93 -0
- package/dist/realistic/element.js +284 -0
- package/dist/realistic/gate.d.ts +64 -0
- package/dist/realistic/gate.js +72 -0
- package/dist/realistic/index.d.ts +5 -0
- package/dist/realistic/index.js +6 -0
- package/dist/realistic/shaders.d.ts +10 -0
- package/dist/realistic/shaders.js +124 -0
- package/dist/realistic/shared.d.ts +23 -0
- package/dist/realistic/shared.js +51 -0
- package/dist/realistic/sun.d.ts +44 -0
- package/dist/realistic/sun.js +65 -0
- package/dist/realistic/textures.d.ts +40 -0
- package/dist/realistic/textures.js +141 -0
- package/dist/realistic/tiers.d.ts +94 -0
- package/dist/realistic/tiers.js +94 -0
- package/dist/rotate.d.ts +59 -4
- package/dist/rotate.js +59 -4
- package/dist/space/element.d.ts +134 -0
- package/dist/space/element.js +394 -0
- package/dist/space/ephemeris.d.ts +151 -0
- package/dist/space/ephemeris.js +162 -0
- package/dist/space/index.d.ts +3 -0
- package/dist/space/index.js +5 -0
- package/dist/space/scale.d.ts +124 -0
- package/dist/space/scale.js +141 -0
- package/dist/space/scene.d.ts +131 -0
- package/dist/space/scene.js +295 -0
- package/dist/styles.d.ts +65 -2
- package/dist/styles.js +43 -2
- package/dist/textures/clouds-1024.webp +0 -0
- package/dist/textures/clouds-2048.webp +0 -0
- package/dist/textures/day-1024.webp +0 -0
- package/dist/textures/day-2048.webp +0 -0
- package/dist/textures/day-4096.webp +0 -0
- package/dist/textures/moon-1024.webp +0 -0
- package/dist/textures/moon-2048.webp +0 -0
- package/dist/textures/night-1024.webp +0 -0
- package/dist/textures/night-2048.webp +0 -0
- package/dist/textures/water-1024.webp +0 -0
- package/dist/textures/water-2048.webp +0 -0
- package/dist/types.d.ts +55 -5
- package/dist/view.d.ts +64 -3
- package/dist/view.js +56 -3
- package/package.json +93 -8
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type * as THREE from "three";
|
|
2
|
+
import type { AssetCache, Item3D } from "@johnmorrisdotca/kazoku-ui/renderer";
|
|
3
|
+
import { type ThreeParts } from "../realistic/textures.ts";
|
|
4
|
+
import type { Layer } from "../realistic/tiers.ts";
|
|
5
|
+
import { type Frame, type PlanetName, type Vec3 } from "./ephemeris.ts";
|
|
6
|
+
import { type ScaleMode } from "./scale.ts";
|
|
7
|
+
type Three = ThreeParts;
|
|
8
|
+
/** The camera's distance, in Earth radii, at which the Earth fills the view at zoom 1. */
|
|
9
|
+
export declare const FIT_DISTANCE = 3.4;
|
|
10
|
+
/**
|
|
11
|
+
* The ten bodies the space view places, names and lets a reader choose: the Earth, the Sun, the Moon and the seven other planets.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts no-run
|
|
15
|
+
* import { BODY_NAMES } from "@johnmorrisdotca/chikyu-earth/space/element";
|
|
16
|
+
*
|
|
17
|
+
* console.log(BODY_NAMES.join(", "));
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare const BODY_NAMES: readonly ["Earth", "Sun", "Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"];
|
|
21
|
+
/**
|
|
22
|
+
* The name of one of the bodies in `BODY_NAMES`.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts no-run
|
|
26
|
+
* import { BODY_NAMES, type BodyName } from "@johnmorrisdotca/chikyu-earth/space/element";
|
|
27
|
+
*
|
|
28
|
+
* const mars: BodyName = "Mars";
|
|
29
|
+
* console.log(BODY_NAMES.includes(mars));
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export type BodyName = (typeof BODY_NAMES)[number];
|
|
33
|
+
export interface SpaceModel {
|
|
34
|
+
/** Moment shown, milliseconds since the epoch. */
|
|
35
|
+
time: number;
|
|
36
|
+
mode: ScaleMode;
|
|
37
|
+
/** The shared controls' yaw, tilt and zoom. */
|
|
38
|
+
view: {
|
|
39
|
+
yaw: number;
|
|
40
|
+
tilt: number;
|
|
41
|
+
zoom: number;
|
|
42
|
+
};
|
|
43
|
+
/** The home place: the camera starts above it. */
|
|
44
|
+
centre: {
|
|
45
|
+
lon: number;
|
|
46
|
+
lat: number;
|
|
47
|
+
};
|
|
48
|
+
/** Earth's turn against the stars (degrees) at the moment the camera was last moved: the camera is fixed to the stars, not to the ground. */
|
|
49
|
+
cameraSpin: number | null;
|
|
50
|
+
orbits: boolean;
|
|
51
|
+
labels: boolean;
|
|
52
|
+
/** Milliseconds of game time one second of wall time covers (the ephemeris is looked up once per such span). */
|
|
53
|
+
stepMs: number;
|
|
54
|
+
/** The body the camera looks at, and (in `zoom`) fills the view with at 1x. */
|
|
55
|
+
focus: BodyName;
|
|
56
|
+
/** Filled at each draw. */
|
|
57
|
+
drawn: {
|
|
58
|
+
frame: Frame;
|
|
59
|
+
distance: number;
|
|
60
|
+
radiusPx: number;
|
|
61
|
+
} | null;
|
|
62
|
+
/** How many times astronomy-engine has been asked for a frame. */
|
|
63
|
+
lookups: number;
|
|
64
|
+
ratio(): number;
|
|
65
|
+
}
|
|
66
|
+
export declare const newSpaceModel: () => SpaceModel;
|
|
67
|
+
/** Where a body is on the screen: its centre and its apparent radius, in CSS pixels in the box. */
|
|
68
|
+
export interface BodyPlace {
|
|
69
|
+
x: number;
|
|
70
|
+
y: number;
|
|
71
|
+
r: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* One body as drawn by a painter: an object of radius 1 at the origin, which the scene places, scales and (for the Sun) turns to face the camera.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts no-run
|
|
78
|
+
* import type { BodyDrawing } from "@johnmorrisdotca/chikyu-earth/space";
|
|
79
|
+
*
|
|
80
|
+
* const drawing = { object: undefined as never, dispose: () => undefined } satisfies BodyDrawing;
|
|
81
|
+
* console.log(typeof drawing.dispose);
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export interface BodyDrawing {
|
|
85
|
+
object: THREE.Object3D;
|
|
86
|
+
/** Told at each draw the unit direction from the body to the Sun, in scene axes (x to the vernal equinox, y north). */
|
|
87
|
+
light?(toSun: Vec3): void;
|
|
88
|
+
/** True to have the scene turn the object to face the camera (a disc or a glow). */
|
|
89
|
+
billboard?: boolean;
|
|
90
|
+
dispose(): void;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The seam for drawing the Sun and the planets. The space view places them, sizes them, lights them and labels them; a painter only makes what is drawn at
|
|
94
|
+
* each place. The default (`plainPainter`) is a sphere in the body's colour, and a glow for the Sun. Another package can supply better looking ones.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts no-run
|
|
98
|
+
* import { plainPainter, type BodyPainter } from "@johnmorrisdotca/chikyu-earth/space";
|
|
99
|
+
*
|
|
100
|
+
* const painter: BodyPainter = { make: (three, name) => plainPainter.make(three, name) };
|
|
101
|
+
* console.log(typeof painter.make);
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export interface BodyPainter {
|
|
105
|
+
make(three: ThreeParts, name: PlanetName | "Sun"): BodyDrawing;
|
|
106
|
+
}
|
|
107
|
+
export interface SpaceDeps {
|
|
108
|
+
assets: AssetCache;
|
|
109
|
+
textureBase: () => string;
|
|
110
|
+
cap: () => number;
|
|
111
|
+
invalidate: () => void;
|
|
112
|
+
onError?: (error: unknown) => void;
|
|
113
|
+
onTier?: (layer: Layer, width: number) => void;
|
|
114
|
+
/** Where each body is on the screen, in CSS pixels in the box, or null when it is behind the camera. Called at each draw. */
|
|
115
|
+
onLabels?: (places: Record<BodyName, BodyPlace | null>) => void;
|
|
116
|
+
/** How the Sun and the planets are drawn; left out, plain spheres in the right colours (see `BodyPainter`). */
|
|
117
|
+
painter?: BodyPainter;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* The default look: a sphere in the planet's colour, lit by the Sun, and for the Sun a glowing disc.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts no-run
|
|
124
|
+
* import { plainPainter } from "@johnmorrisdotca/chikyu-earth/space";
|
|
125
|
+
*
|
|
126
|
+
* console.log(typeof plainPainter.make);
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export declare const plainPainter: BodyPainter;
|
|
130
|
+
export declare function createSpaceItem(model: SpaceModel, deps: SpaceDeps): Item3D<Three>;
|
|
131
|
+
export {};
|