From 3443c1c65e9f1753e1e656b35d08416c1fa298f2 Mon Sep 17 00:00:00 2001 From: godosa Date: Wed, 7 Oct 2026 00:14:38 +0200 Subject: worldmap-viewer: initial public history --- viewer/js/sky.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 viewer/js/sky.js (limited to 'viewer/js/sky.js') 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] : ''; +} -- cgit