/** =============== KONSOLEN HEINZI ===============
* Berechnet Höhe und Azimut von Merkur im Jahreslauf
* Anwendung:
* merkur(JAHR, LÄNGE, BREITE, STUNDE, MINUTE, ZEITZONE);
* Östliche Längen POSITIV, westliche Längen NEGATIV.
* Bsp.:
* merkur(2026, 10.0, 50.0, 17, 0, 1);
*/
function merkur(yrs, lon, lat, hrs, mins, tz = 1) {
const cl = console.log.bind(console);
const PI = Math.PI;
const DEGS = PI / 180;
const range = x => (x % 360 + 360) % 360;
const fpart = x => Math.abs(x % 1);
const sin = x => Math.sin(x * DEGS);
const cos = x => Math.cos(x * DEGS);
const tan = x => Math.tan(x * DEGS);
const arcsin = x => Math.asin(x) / DEGS;
const arccos = x => Math.acos(x) / DEGS;
const arctan2 = (y, x) => Math.atan2(y, x) / DEGS;
const isLeap = x => ((yrs % 4 == 0 && yrs % 100 != 0) || yrs % 400 == 0) ? 1 : 0;
// Bahnelemente
const planetaryElements = [
[ // Merkur
[252.250906, 149474.0722491, 0.00030350, 0.000000018],
[0.387098310, 0, 0, 0],
[0.20563175, 0.000020407, -0.0000000283, -0.00000000018],
[7.004986, 0.0018215, -0.00001810, 0.000000056],
[48.330893, 1.1861883, 0.00017542, 0.000000215],
[77.456119, 1.5564776, 0.00029544, 0.000000009]
],
[ // Erde
[100.466457, 36000.7698278, 0.00030322, 0.000000020],
[1.000001018, 0, 0, 0],
[0.01670863, -0.000042037, -0.0000001267, 0.00000000014],
[0, 0, 0, 0],
[0, 0, 0, 0],
[102.937348, 1.7195366, 0.00045688, -0.000000018]
],
];
// Horner Schema
function horner(c, x, r = 0) {
let i, y;
i = c.length - 1;
if (i <= 0) {
throw "Horner Schema: Array prüfen!";
}
y = c[i];
while (i-- > 0) {
y = y * x + c[i];
}
return r == 1 ? range(y) : y;
}
// Keplergleichung
function solveKepler(M, e) {
const maxIter = 50;
const GOAL = 1e-6;
let E0, E1, corr, iter;
E1 = M;
corr = 1;
iter = 0;
while (Math.abs(corr) > GOAL && iter < maxIter) {
E0 = E1;
corr = (M + 180 * e / Math.PI * sin(E0) - E0) / (1 - e * cos(E0));
E1 = E0 + corr;
}
if (iter === maxIter) {
console.warn("solveKepler: maxIter erreicht, Genauigkeit evtl. nicht erreicht");
}
return E1;
}
// Julianische Tagzahl
function getJD(yrs, mth, dys, hrs, mins, secs) {
mth <= 2 ? (yrs--, mth += 12) : null;
let b = (10000 * yrs + 100 * mth + dys) > 15821004 ? (2 - Math.floor(yrs / 100) + Math.floor(Math.floor(yrs / 100) / 4)) : 0;
dys += (hrs + mins / 60 + secs / 3600) / 24;
return Math.floor(365.25 * (yrs + 4716)) + Math.floor(30.6001 * (mth + 1)) + dys + b - 1524.5;
}
function JDtoCal(jd) {
let Z, F, A, alpha, B, C, D, E, yrs, mth, dys;
jd += 0.5;
Z = Math.trunc(jd);
// F = fpart(jd);
if (Z < 2299161) {
A = Z;
} else {
alpha = Math.trunc((Z - 1867216.25) / 36524.25);
A = Z + 1 + alpha - Math.trunc(alpha / 4);
}
B = A + 1524;
C = Math.trunc((B - 122.1) / 365.25);
D = Math.trunc(365.25 * C);
E = Math.trunc((B - D) / 30.6001);
dys = B - D - Math.trunc(30.6001 * E) // + F;
E < 14 ? mth = E - 1 : mth = E - 13;
mth > 2 ? yrs = C - 4716 : yrs = C - 4715;
return [yrs, mth, dys, hrs, mins];
}
// Schleife für das ganze Jahr
let jd, T, L, a, e, i, O, P, w, M, E, nu, rm, re, xh, yh, zh;
let xs, ys, zs, xg, yg, zg, eps, xe, ye, ze, del, ph, mag, s;
let RA, DEC, LST, H, h, A, RAsun, DECsun, Hsun, hsun, date, dateStr;
const days = isLeap(yrs) ? 367 : 366;
const elements = planetaryElements[0];
const earthElements = planetaryElements[1];
cl(` JD | Datum/Uhrzeit | Höhe | Azimut | Magnitude | Phasenw. | Durchm. | Höhe Sonne`);
for (j = 0; j < days; j++) {
jd = getJD(yrs, 1, 1 + j, hrs - tz, mins, 0);
T = (jd - 2451545.0) / 36525;
// ---------- Merkur ----------
L = horner(elements[0], T, 1);
a = elements[1][0];
e = horner(elements[2], T);
i = horner(elements[3], T);
O = horner(elements[4], T);
P = horner(elements[5], T);
w = P - O;
M = range(L - P);
E = solveKepler(M, e);
nu = 2 * arctan2(Math.sqrt(1 + e) * sin(E / 2), Math.sqrt(1 - e) * cos(E / 2));
rm = a * (1 - e * cos(E));
xh = rm * (cos(O) * cos(nu + w) - sin(O) * sin(nu + w) * cos(i));
yh = rm * (sin(O) * cos(nu + w) + cos(O) * sin(nu + w) * cos(i));
zh = rm * sin(nu + w) * sin(i);
// ---------- Erde ----------
L = horner(earthElements[0], T, 1);
a = earthElements[1][0];
e = horner(earthElements[2], T);
i = horner(earthElements[3], T);
O = horner(earthElements[4], T);
P = horner(earthElements[5], T);
w = P - O;
M = range(L - P);
E = solveKepler(M, e);
nu = 2 * arctan2(Math.sqrt(1 + e) * sin(E / 2), Math.sqrt(1 - e) * cos(E / 2));
re = a * (1 - e * cos(E));
xs = re * (cos(O) * cos(nu + w) - sin(O) * sin(nu + w) * cos(i));
ys = re * (sin(O) * cos(nu + w) + cos(O) * sin(nu + w) * cos(i));
zs = re * sin(nu + w) * sin(i);
// ---------- Geozentrische Koordinaten MERKUR ----------
xg = xh - xs;
yg = yh - ys;
zg = zh - zs;
del = Math.sqrt(xg * xg + yg * yg + zg * zg);
ph = arccos((del * del + rm * rm - re * re) / (2 * rm * del));
mag = -0.42 + 5*Math.log10(rm*del) + 0.0380*ph - 0.000273*ph*ph + 0.000002*ph*ph*ph;
s = 2*3.36/del;
// ---------- Äquatoriale Koordinaten MERKUR ----------
eps = 23.439291 - (46.8150 / 3600) * T;
xe = xg;
ye = yg * cos(eps) - zg * sin(eps);
ze = yg * sin(eps) + zg * cos(eps);
RA = range(arctan2(ye, xe));
DEC = arctan2(ze, Math.sqrt(xe * xe + ye * ye));
// ---------- Lokale Sternzeit ----------
theta0 = horner([280.46061837 + 360.98564736629 * (jd - 2451545.0), 0, 0.000387933, -1 / 38710000], T, 1);
LST = range(theta0 + lon);
H = range(LST - RA);
// ---------- HÖHE + AZIMUT MERKUR ----------
h = arcsin(sin(lat) * sin(DEC) + cos(lat) * cos(DEC) * cos(H));
A = range(arctan2(sin(H), cos(H) * sin(lat) - tan(DEC) * cos(lat)));
// ---------- Sonne ----------
xg = -xs;
yg = -ys;
zg = -zs;
xe = xg;
ye = yg * cos(eps) - zg * sin(eps);
ze = yg * sin(eps) + zg * cos(eps);
RAsun = arctan2(ye, xe);
DECsun = arctan2(ze, Math.sqrt(xe * xe + ye * ye));
Hsun = range(LST - RAsun);
hsun = arcsin(sin(lat) * sin(DECsun) + cos(lat) * cos(DECsun) * cos(Hsun));
date = JDtoCal(jd);
dateStr = `${String(date[2]).padStart(2, '0')}.${String(date[1]).padStart(2, '0')}.${date[0]},${String(date[3]).padStart(2, '0')}:${String(date[4]).padStart(2, '0')}`;
if (h > 0 && hsun < 0) cl(`${jd.toFixed(5)} | ${dateStr} | h = ${h.toFixed(2)}° | Az = ${A.toFixed(2)}° | mag = ${mag.toFixed(1)} | phase = ${ph.toFixed(1)}° | ∅ = ${s.toFixed(2)}" | sun = ${hsun.toFixed(2)}°`);
}
return null;
}
// Test
merkur(2026, 10, 50, 17, 0, 1);