aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/viewer/js/sky.js
diff options
context:
space:
mode:
authorgodosa <godosa@godosa.eu>2026-10-07 00:14:38 +0200
committergodosa <godosa@godosa.eu>2026-10-07 00:14:38 +0200
commit3443c1c65e9f1753e1e656b35d08416c1fa298f2 (patch)
tree4e43236f460145a4d75d1b4616dcb7aa6ef08f51 /viewer/js/sky.js
downloadworldmap-viewer-3443c1c65e9f1753e1e656b35d08416c1fa298f2.tar.gz
worldmap-viewer-3443c1c65e9f1753e1e656b35d08416c1fa298f2.zip
worldmap-viewer: initial public history
Diffstat (limited to 'viewer/js/sky.js')
-rw-r--r--viewer/js/sky.js41
1 files changed, 41 insertions, 0 deletions
diff --git a/viewer/js/sky.js b/viewer/js/sky.js
new file mode 100644
index 0000000..df4f000
--- /dev/null
+++ b/viewer/js/sky.js
@@ -0,0 +1,41 @@
+// sky.js — sun geometry (pure), values from planet.js. Viewer convention: day 0 = northern spring equinox,
+// moment 0 = midnight at longitude 0°. Circular orbit. A day has in-world moments (units.moment_s) or minutes;
+// a sun-locked world keeps its sun still.
+import { toVec } from './geo.js';
+import { PLANET } from './planet.js';
+
+export const TILT_DEG = PLANET.tilt_deg;
+export const YEAR_DAYS = Math.max(1, Math.round(PLANET.year_days));
+export const MOMENT_S = PLANET.moment_s || 60;
+export const DAY_MOMENTS = Math.round(PLANET.day_hours * 3600 / MOMENT_S);
+const q = YEAR_DAYS / 4;
+export const SEASONS = TILT_DEG > 0 ? [[0, 'northern spring equinox'], [q, 'northern midsummer'], [2 * q, 'northern autumn equinox'],
+ [3 * q, 'northern midwinter'], [YEAR_DAYS, 'northern spring equinox']] : [];
+const D = Math.PI / 180;
+
+export function subsolar(day, moment) {
+ if (PLANET.sun_lock) return { lat: PLANET.sun_lock[0], lon: PLANET.sun_lock[1] };
+ const t = day + moment / DAY_MOMENTS;
+ const lat = Math.asin(Math.sin(TILT_DEG * D) * Math.sin((2 * Math.PI * t) / YEAR_DAYS)) / D;
+ const lon = ((((180 - (360 * moment) / DAY_MOMENTS + 180) % 360) + 360) % 360) - 180;
+ return { lat, lon };
+}
+
+export function sunVec(day, moment) {
+ const s = subsolar(day, moment);
+ return toVec(s.lat, s.lon);
+}
+
+export function dayFraction(lat, day) {
+ const dec = subsolar(day, 0).lat * D; // declination at the start of the day
+ const phi = Math.max(-89.9999, Math.min(89.9999, lat)) * D;
+ const x = -Math.tan(phi) * Math.tan(dec);
+ if (x <= -1) return 1;
+ if (x >= 1) return 0;
+ return Math.acos(x) / Math.PI;
+}
+
+export function seasonName(day) {
+ const hit = SEASONS.find(([d]) => Math.abs(day - d) <= Math.min(2, YEAR_DAYS / 20));
+ return hit ? hit[1] : '';
+}