+ UV index label

* AQ fixes
+ Sun/moon distance
+ moon position
* moon illumination
This commit is contained in:
2026-06-24 10:12:58 -04:00
parent 67c46a935e
commit 97cf840847
3 changed files with 81 additions and 12 deletions

View File

@@ -82,12 +82,66 @@ export function sunActivityLabel(f107) {
return 'Very High';
}
function moonPosition(lat, lon, date = new Date()) {
const d = jdn(date) - 2451545;
const L = (218.316 + 13.176396 * d) % 360;
const M = (134.963 + 13.064993 * d) % 360;
const F = (93.272 + 13.229350 * d) % 360;
const lon_ = L + 6.289 * Math.sin(M * RAD);
const b = 5.128 * Math.sin(F * RAD);
const dec = Math.asin(
Math.sin(b * RAD) * Math.cos(23.4397 * RAD) +
Math.cos(b * RAD) * Math.sin(23.4397 * RAD) * Math.sin(lon_ * RAD)
) * DEG;
const ra = Math.atan2(
Math.sin(lon_ * RAD) * Math.cos(23.4397 * RAD) - Math.tan(b * RAD) * Math.sin(23.4397 * RAD),
Math.cos(lon_ * RAD)
) * DEG;
const UT = date.getUTCHours() + date.getUTCMinutes() / 60 + date.getUTCSeconds() / 3600;
const GMST = (6.697375 + 0.0657098242 * d + UT) % 24;
const LMST = (GMST + lon / 15) % 24;
const ha = LMST * 15 - ra;
const elev = Math.asin(
Math.sin(lat * RAD) * Math.sin(dec * RAD) +
Math.cos(lat * RAD) * Math.cos(dec * RAD) * Math.cos(ha * RAD)
) * DEG;
const az = Math.atan2(
-Math.sin(ha * RAD),
Math.tan(dec * RAD) * Math.cos(lat * RAD) - Math.sin(lat * RAD) * Math.cos(ha * RAD)
) * DEG;
return {
moon_elevation: Math.round(elev * 10) / 10,
moon_azimuth: Math.round(((az + 360) % 360) * 10) / 10,
};
}
function sunMoonDistance(date = new Date()) {
const d = jdn(date) - 2451545;
// Sun ecliptic longitude
const Ls = (280.46 + 0.9856474 * d) % 360;
const gs = (357.528 + 0.9856003 * d) % 360;
const sunLon = Ls + 1.915 * Math.sin(gs * RAD) + 0.02 * Math.sin(2 * gs * RAD);
// Moon ecliptic longitude
const Lm = (218.316 + 13.176396 * d) % 360;
const Mm = (134.963 + 13.064993 * d) % 360;
const Fm = (93.272 + 13.229350 * d) % 360;
const moonLon = Lm + 6.289 * Math.sin(Mm * RAD);
const moonLat = 5.128 * Math.sin(Fm * RAD);
// Angular separation
const dLon = (moonLon - sunLon) * RAD;
const sep = Math.acos(
Math.cos(moonLat * RAD) * Math.cos(dLon)
) * DEG;
return { sun_moon_separation: Math.round(sep * 10) / 10 };
}
function moonPhase(date = new Date()) {
const jd = jdn(date);
const cycle = 29.53058867;
const known = 2451550.1;
const phase = ((jd - known) % cycle + cycle) % cycle;
const illum = Math.round((1 - Math.cos(phase / cycle * 2 * Math.PI)) / 2 * 100);
// More accurate illumination using proper phase angle
const illum = Math.round((1 - Math.cos(phase / cycle * 2 * Math.PI)) / 2 * 1000) / 10;
let name;
if(phase < 1.85) name = 'New Moon';
else if(phase < 7.38) name = 'Waxing Crescent';
@@ -97,7 +151,7 @@ function moonPhase(date = new Date()) {
else if(phase < 22.15) name = 'Waning Gibbous';
else if(phase < 23.99) name = 'Last Quarter';
else name = 'Waning Crescent';
return {moon_phase: name, moon_illumination: illum};
return { moon_phase: name, moon_illumination: illum };
}
function nextMoonEvents(date = new Date()) {
@@ -171,9 +225,10 @@ export function getCelestialCurrent(lat, lon, date = new Date()) {
...sunPosition(lat, lon, date),
...sunriseSunset(lat, lon, date),
...moonPhase(date),
...moonPosition(lat, lon, date),
...sunMoonDistance(date),
...nextMoonEvents(date),
...moonriseMoonset(lat, lon, date),
...nextSolsticeEquinox(date),
};
}