[astro] Factor standard Meeus calculations (#20138)

* Factor standard meeus calculations

Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
Gaël L'hopital
2026-04-28 10:37:21 +02:00
committed by GitHub
parent 2cf478ff3e
commit 7abaa16af8
7 changed files with 213 additions and 146 deletions
@@ -1,54 +0,0 @@
/*
* Copyright (c) 2010-2026 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.astro.internal.calc;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.astro.internal.util.DateTimeUtils;
/**
* Calculates the eclipses for the astro object
*
* @author Gerhard Riegler - Initial contribution
* @author Gaël L'hopital - Extracted from MoonCalc
*/
@NonNullByDefault
public class AstroCalc {
protected static double varF(double k, double t) {
return 160.7108 + 390.67050274 * k - .0016341 * t * t - .00000227 * t * t * t + .000000011 * t * t * t * t;
}
protected static double varO(double k, double t) {
return 124.7746 - 1.5637558 * k + .0020691 * t * t + .00000215 * t * t * t;
}
protected static double varE(double t) {
return 1 - .002516 * t - .0000074 * t * t;
}
protected static double varM1(double k, double t) {
return 201.5643 + 385.81693528 * k + .1017438 * t * t + .00001239 * t * t * t - .000000058 * t * t * t * t;
}
protected static double varM(double k, double t) {
return 2.5534 + 29.10535669 * k - .0000218 * t * t - .00000011 * t * t * t;
}
protected static double varJde(double k, double t) {
return 2451550.09765 + 29.530588853 * k + .0001337 * t * t - .00000015 * t * t * t
+ .00000000073 * t * t * t * t;
}
protected static double varK(double jd, double tz) {
return ((jd + tz - DateTimeUtils.JD_2000_01_01) / 365.0) * 12.3685;
}
}
@@ -19,6 +19,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.astro.internal.calc.moon.LunationArguments;
import org.openhab.binding.astro.internal.model.EclipseKind; import org.openhab.binding.astro.internal.model.EclipseKind;
import org.openhab.binding.astro.internal.model.Position; import org.openhab.binding.astro.internal.model.Position;
import org.openhab.binding.astro.internal.util.DateTimeUtils; import org.openhab.binding.astro.internal.util.DateTimeUtils;
@@ -30,7 +31,7 @@ import org.openhab.binding.astro.internal.util.DateTimeUtils;
* @author Gaël L'hopital - Extracted from MoonCalc * @author Gaël L'hopital - Extracted from MoonCalc
*/ */
@NonNullByDefault @NonNullByDefault
public abstract class EclipseCalc extends AstroCalc { public abstract class EclipseCalc {
public record Eclipse(EclipseKind kind, double when) { public record Eclipse(EclipseKind kind, double when) {
public LocalizedEclipse withPosition(Position position) { public LocalizedEclipse withPosition(Position position) {
return new LocalizedEclipse(this, position.getElevationAsDouble()); return new LocalizedEclipse(this, position.getElevationAsDouble());
@@ -59,9 +60,9 @@ public abstract class EclipseCalc extends AstroCalc {
double tz = 0; double tz = 0;
double eclipseJd = 0; double eclipseJd = 0;
do { do {
double k = varK(midnightJd, tz); double k = LunationArguments.varK(midnightJd, tz);
tz += 1; tz += 1;
eclipseJd = getEclipse(Math.floor(k) + getJDAjust(), eclipse); eclipseJd = getEclipse(k, getJDAjust(), eclipse);
} while (eclipseJd <= midnightJd); } while (eclipseJd <= midnightJd);
return eclipseJd; return eclipseJd;
} }
@@ -75,32 +76,30 @@ public abstract class EclipseCalc extends AstroCalc {
/** /**
* Calculates the eclipse. * Calculates the eclipse.
*/ */
protected double getEclipse(double kMod, EclipseKind eclipse) { protected double getEclipse(double k, double adjust, EclipseKind eclipse) {
double t = kMod / 1236.85; LunationArguments la = new LunationArguments(k, adjust);
double f = varF(kMod, t);
if (sinDeg(Math.abs(f)) > .36) { if (sinDeg(Math.abs(la.f)) > .36) {
return 0; return 0;
} }
double o = varO(kMod, t); double f1 = la.f - .02665 * sinDeg(la.o);
double f1 = f - .02665 * sinDeg(o); double a1 = 299.77 + .107408 * la.kMod - .009173 * la.t2;
double a1 = 299.77 + .107408 * kMod - .009173 * t * t; double p = .207 * la.e * sinDeg(la.m) + .0024 * la.e * sinDeg(2 * la.m) - .0392 * sinDeg(la.m1)
double e = varE(t); + .0116 * sinDeg(2 * la.m1) - .0073 * la.e * sinDeg(la.m1 + la.m) + .0067 * la.e * sinDeg(la.m1 - la.m)
double m = varM(kMod, t); + .0118 * sinDeg(2 * f1);
double m1 = varM1(kMod, t); double q = 5.2207 - .0048 * la.e * cosDeg(la.m) + .002 * la.e * cosDeg(2 * la.m) - .3299 * cosDeg(la.m1)
double p = .207 * e * sinDeg(m) + .0024 * e * sinDeg(2 * m) - .0392 * sinDeg(m1) + .0116 * sinDeg(2 * m1) - .006 * la.e * cosDeg(la.m1 + la.m) + .0041 * la.e * cosDeg(la.m1 - la.m);
- .0073 * e * sinDeg(m1 + m) + .0067 * e * sinDeg(m1 - m) + .0118 * sinDeg(2 * f1);
double q = 5.2207 - .0048 * e * cosDeg(m) + .002 * e * cosDeg(2 * m) - .3299 * cosDeg(m1)
- .006 * e * cosDeg(m1 + m) + .0041 * e * cosDeg(m1 - m);
double g = (p * cosDeg(f1) + q * sinDeg(f1)) * (1 - .0048 * cosDeg(Math.abs(f1))); double g = (p * cosDeg(f1) + q * sinDeg(f1)) * (1 - .0048 * cosDeg(Math.abs(f1)));
double u = .0059 + .0046 * e * cosDeg(m) - .0182 * cosDeg(m1) + .0004 * cosDeg(2 * m1) - .0005 * cosDeg(m + m1); double u = .0059 + .0046 * la.e * cosDeg(la.m) - .0182 * cosDeg(la.m1) + .0004 * cosDeg(2 * la.m1)
double jd = varJde(kMod, t); - .0005 * cosDeg(la.m + la.m1);
jd += .0161 * sinDeg(2 * m1) - .0097 * sinDeg(2 * f1) + .0073 * e * sinDeg(m1 - m) - .005 * e * sinDeg(m1 + m)
- .0023 * sinDeg(m1 - 2 * f1) + .0021 * e * sinDeg(2 * m); double jd = la.jde;
jd += .0012 * sinDeg(m1 + 2 * f1) + .0006 * e * sinDeg(2 * m1 + m) - .0004 * sinDeg(3 * m1) jd += .0161 * sinDeg(2 * la.m1) - .0097 * sinDeg(2 * f1) + .0073 * la.e * sinDeg(la.m1 - la.m)
- .0003 * e * sinDeg(m + 2 * f1) + .0003 * sinDeg(a1) - .0002 * e * sinDeg(m - 2 * f1) - .005 * la.e * sinDeg(la.m1 + la.m) - .0023 * sinDeg(la.m1 - 2 * f1) + .0021 * la.e * sinDeg(2 * la.m);
- .0002 * e * sinDeg(2 * m1 - m) - .0002 * sinDeg(o); jd += .0012 * sinDeg(la.m1 + 2 * f1) + .0006 * la.e * sinDeg(2 * la.m1 + la.m) - .0004 * sinDeg(3 * la.m1)
return astroAdjust(eclipse, e, m, m1, g, u, jd); - .0003 * la.e * sinDeg(la.m + 2 * f1) + .0003 * sinDeg(a1) - .0002 * la.e * sinDeg(la.m - 2 * f1)
- .0002 * la.e * sinDeg(2 * la.m1 - la.m) - .0002 * sinDeg(la.o);
return astroAdjust(eclipse, la.e, la.m, la.m1, g, u, jd);
} }
} }
@@ -42,7 +42,7 @@ import org.openhab.binding.astro.internal.util.MathUtils;
* zodiac based on http://lexikon.astronomie.info/java/sunmoon/ * zodiac based on http://lexikon.astronomie.info/java/sunmoon/
*/ */
@NonNullByDefault @NonNullByDefault
public class MoonCalc extends AstroCalc { public class MoonCalc {
private static final double FL = 1.0 - AstroConstants.WGS84_EARTH_FLATTENING; private static final double FL = 1.0 - AstroConstants.WGS84_EARTH_FLATTENING;
private static final EclipseCalc ECLIPSE_CALC = new MoonEclipseCalc(); private static final EclipseCalc ECLIPSE_CALC = new MoonEclipseCalc();
@@ -15,10 +15,9 @@ package org.openhab.binding.astro.internal.calc;
import static java.lang.Math.*; import static java.lang.Math.*;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.astro.internal.calc.moon.LunarArguments;
import org.openhab.binding.astro.internal.model.DistanceType; import org.openhab.binding.astro.internal.model.DistanceType;
import org.openhab.binding.astro.internal.model.MoonDistance; import org.openhab.binding.astro.internal.model.MoonDistance;
import org.openhab.binding.astro.internal.util.AstroConstants;
import org.openhab.binding.astro.internal.util.DateTimeUtils;
/** /**
* Moon Distance Calculator * Moon Distance Calculator
@@ -50,15 +49,8 @@ public class MoonDistanceCalc {
* Calculates the distance from the moon to earth in metres * Calculates the distance from the moon to earth in metres
*/ */
public static MoonDistance calculate(double jd) { public static MoonDistance calculate(double jd) {
double t = DateTimeUtils.toJulianCenturies(jd); LunarArguments la = new LunarArguments(jd);
double t2 = t * t; return new MoonDistance(jd, 385000560 + getCoefficient(la.d, la.m, la.m1, la.f));
double t3 = t2 * t;
double t4 = t3 * t;
double d = toRadians(297.8502042 + 445267.11151686 * t - .00163 * t2 + t3 / 545868 - t4 / 113065000);
double m = toRadians(AstroConstants.E05_0 + 35999.0502909 * t - .0001536 * t2 + t3 / 24490000);
double m1 = toRadians(134.9634114 + 477198.8676313 * t + .008997 * t2 + t3 / 69699 - t4 / 14712000);
double f = toRadians(93.2720993 + 483202.0175273 * t - .0034029 * t2 - t3 / 3526000 + t4 / 863310000);
return new MoonDistance(jd, 385000560 + getCoefficient(d, m, m1, f));
} }
public static MoonDistance get(DistanceType type, double julianDate) { public static MoonDistance get(DistanceType type, double julianDate) {
@@ -20,10 +20,10 @@ import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.astro.internal.calc.moon.LunarArguments;
import org.openhab.binding.astro.internal.calc.moon.LunationArguments;
import org.openhab.binding.astro.internal.model.MoonPhase; import org.openhab.binding.astro.internal.model.MoonPhase;
import org.openhab.binding.astro.internal.model.MoonPhaseSet; import org.openhab.binding.astro.internal.model.MoonPhaseSet;
import org.openhab.binding.astro.internal.util.AstroConstants;
import org.openhab.binding.astro.internal.util.DateTimeUtils;
/** /**
* Moon Phase Calculator * Moon Phase Calculator
@@ -31,7 +31,7 @@ import org.openhab.binding.astro.internal.util.DateTimeUtils;
* @author Gaël L'hopital - Initial contribution * @author Gaël L'hopital - Initial contribution
*/ */
@NonNullByDefault @NonNullByDefault
public class MoonPhaseCalc extends AstroCalc { public class MoonPhaseCalc {
public static MoonPhaseSet calculate(InstantSource instantSource, double julianDate, MoonPhaseSet previousMP, public static MoonPhaseSet calculate(InstantSource instantSource, double julianDate, MoonPhaseSet previousMP,
ZoneId zone) { ZoneId zone) {
final MoonPhaseSet result; final MoonPhaseSet result;
@@ -58,16 +58,12 @@ public class MoonPhaseCalc extends AstroCalc {
* Calculates the illumination. * Calculates the illumination.
*/ */
private static double getIllumination(double jd) { private static double getIllumination(double jd) {
double t = DateTimeUtils.toJulianCenturies(jd); LunarArguments la = new LunarArguments(jd);
double t2 = t * t; double i = Math.PI - la.d - Math.toRadians(6.289) * Math.sin(la.m1) + Math.toRadians(2.1) * Math.sin(la.m)
double t3 = t2 * t; - Math.toRadians(1.274) * Math.sin(2 * la.d - la.m1) - Math.toRadians(0.658) * Math.sin(2 * la.d)
double t4 = t3 * t; - Math.toRadians(0.241) * Math.sin(2 * la.m1) - Math.toRadians(0.110) * Math.sin(la.d);
double d = 297.8502042 + 445267.11151686 * t - .00163 * t2 + t3 / 545868 - t4 / 113065000;
double m = AstroConstants.E05_0 + 35999.0502909 * t - .0001536 * t2 + t3 / 24490000; return (1 + Math.cos(i)) / 2;
double m1 = 134.9634114 + 477198.8676313 * t + .008997 * t2 + t3 / 69699 - t4 / 14712000;
double i = 180 - d - 6.289 * sinDeg(m1) + 2.1 * sinDeg(m) - 1.274 * sinDeg(2 * d - m1) - .658 * sinDeg(2 * d)
- .241 * sinDeg(2 * m1) - .110 * sinDeg(d);
return (1 + cosDeg(i)) / 2;
} }
/** /**
@@ -77,7 +73,7 @@ public class MoonPhaseCalc extends AstroCalc {
double tz = 0; double tz = 0;
double phaseJd = 0; double phaseJd = 0;
do { do {
double k = varK(jd, tz); double k = LunationArguments.varK(jd, tz);
tz += forward ? 1 : -1; tz += forward ? 1 : -1;
phaseJd = calcMoonPhase(k, phase); phaseJd = calcMoonPhase(k, phase);
} while (forward ? phaseJd <= jd : phaseJd > jd); } while (forward ? phaseJd <= jd : phaseJd > jd);
@@ -88,55 +84,58 @@ public class MoonPhaseCalc extends AstroCalc {
* Calculates the moon phase. * Calculates the moon phase.
*/ */
private static double calcMoonPhase(double k, MoonPhase phase) { private static double calcMoonPhase(double k, MoonPhase phase) {
double kMod = Math.floor(k) + phase.cycleProgress; LunationArguments la = new LunationArguments(k, phase.cycleProgress);
double t = kMod / 1236.85; double jd = la.jde;
double e = varE(t);
double m = varM(kMod, t);
double m1 = varM1(kMod, t);
double f = varF(kMod, t);
double o = varO(kMod, t);
double jd = varJde(kMod, t);
switch (phase) { switch (phase) {
case NEW: case NEW:
jd += -.4072 * sinDeg(m1) + .17241 * e * sinDeg(m) + .01608 * sinDeg(2 * m1) + .01039 * sinDeg(2 * f) jd += -.4072 * sinDeg(la.m1) + .17241 * la.e * sinDeg(la.m) + .01608 * sinDeg(2 * la.m1)
+ .00739 * e * sinDeg(m1 - m) - .00514 * e * sinDeg(m1 + m) + .00208 * e * e * sinDeg(2 * m) + .01039 * sinDeg(2 * la.f) + .00739 * la.e * sinDeg(la.m1 - la.m)
- .00111 * sinDeg(m1 - 2 * f) - .00057 * sinDeg(m1 + 2 * f); - .00514 * la.e * sinDeg(la.m1 + la.m) + .00208 * la.e * la.e * sinDeg(2 * la.m)
jd += .00056 * e * sinDeg(2 * m1 + m) - .00042 * sinDeg(3 * m1) + .00042 * e * sinDeg(m + 2 * f) - .00111 * sinDeg(la.m1 - 2 * la.f) - .00057 * sinDeg(la.m1 + 2 * la.f);
+ .00038 * e * sinDeg(m - 2 * f) - .00024 * e * sinDeg(2 * m1 - m) - .00017 * sinDeg(o) jd += .00056 * la.e * sinDeg(2 * la.m1 + la.m) - .00042 * sinDeg(3 * la.m1)
- .00007 * sinDeg(m1 + 2 * m) + .00004 * sinDeg(2 * m1 - 2 * f); + .00042 * la.e * sinDeg(la.m + 2 * la.f) + .00038 * la.e * sinDeg(la.m - 2 * la.f)
jd += .00004 * sinDeg(3 * m) + .00003 * sinDeg(m1 + m - 2 * f) + .00003 * sinDeg(2 * m1 + 2 * f) - .00024 * la.e * sinDeg(2 * la.m1 - la.m) - .00017 * sinDeg(la.o)
- .00003 * sinDeg(m1 + m + 2 * f) + .00003 * sinDeg(m1 - m + 2 * f) - .00007 * sinDeg(la.m1 + 2 * la.m) + .00004 * sinDeg(2 * la.m1 - 2 * la.f);
- .00002 * sinDeg(m1 - m - 2 * f) - .00002 * sinDeg(3 * m1 + m); jd += .00004 * sinDeg(3 * la.m) + .00003 * sinDeg(la.m1 + la.m - 2 * la.f)
jd += .00002 * sinDeg(4 * m1); + .00003 * sinDeg(2 * la.m1 + 2 * la.f) - .00003 * sinDeg(la.m1 + la.m + 2 * la.f)
+ .00003 * sinDeg(la.m1 - la.m + 2 * la.f) - .00002 * sinDeg(la.m1 - la.m - 2 * la.f)
- .00002 * sinDeg(3 * la.m1 + la.m);
jd += .00002 * sinDeg(4 * la.m1);
break; break;
case FULL: case FULL:
jd += -.40614 * sinDeg(m1) + .17302 * e * sinDeg(m) + .01614 * sinDeg(2 * m1) + .01043 * sinDeg(2 * f) jd += -.40614 * sinDeg(la.m1) + .17302 * la.e * sinDeg(la.m) + .01614 * sinDeg(2 * la.m1)
+ .00734 * e * sinDeg(m1 - m) - .00515 * e * sinDeg(m1 + m) + .00209 * e * e * sinDeg(2 * m) + .01043 * sinDeg(2 * la.f) + .00734 * la.e * sinDeg(la.m1 - la.m)
- .00111 * sinDeg(m1 - 2 * f) - .00057 * sinDeg(m1 + 2 * f); - .00515 * la.e * sinDeg(la.m1 + la.m) + .00209 * la.e * la.e * sinDeg(2 * la.m)
jd += .00056 * e * sinDeg(2 * m1 + m) - .00042 * sinDeg(3 * m1) + .00042 * e * sinDeg(m + 2 * f) - .00111 * sinDeg(la.m1 - 2 * la.f) - .00057 * sinDeg(la.m1 + 2 * la.f);
+ .00038 * e * sinDeg(m - 2 * f) - .00024 * e * sinDeg(2 * m1 - m) - .00017 * sinDeg(o) jd += .00056 * la.e * sinDeg(2 * la.m1 + la.m) - .00042 * sinDeg(3 * la.m1)
- .00007 * sinDeg(m1 + 2 * m) + .00004 * sinDeg(2 * m1 - 2 * f); + .00042 * la.e * sinDeg(la.m + 2 * la.f) + .00038 * la.e * sinDeg(la.m - 2 * la.f)
jd += .00004 * sinDeg(3 * m) + .00003 * sinDeg(m1 + m - 2 * f) + .00003 * sinDeg(2 * m1 + 2 * f) - .00024 * la.e * sinDeg(2 * la.m1 - la.m) - .00017 * sinDeg(la.o)
- .00003 * sinDeg(m1 + m + 2 * f) + .00003 * sinDeg(m1 - m + 2 * f) - .00007 * sinDeg(la.m1 + 2 * la.m) + .00004 * sinDeg(2 * la.m1 - 2 * la.f);
- .00002 * sinDeg(m1 - m - 2 * f) - .00002 * sinDeg(3 * m1 + m); jd += .00004 * sinDeg(3 * la.m) + .00003 * sinDeg(la.m1 + la.m - 2 * la.f)
jd += .00002 * sinDeg(4 * m1); + .00003 * sinDeg(2 * la.m1 + 2 * la.f) - .00003 * sinDeg(la.m1 + la.m + 2 * la.f)
+ .00003 * sinDeg(la.m1 - la.m + 2 * la.f) - .00002 * sinDeg(la.m1 - la.m - 2 * la.f)
- .00002 * sinDeg(3 * la.m1 + la.m);
jd += .00002 * sinDeg(4 * la.m1);
break; break;
default: default:
jd += -.62801 * sinDeg(m1) + .17172 * e * sinDeg(m) - .01183 * e * sinDeg(m1 + m) jd += -.62801 * sinDeg(la.m1) + .17172 * la.e * sinDeg(la.m) - .01183 * la.e * sinDeg(la.m1 + la.m)
+ .00862 * sinDeg(2 * m1) + .00804 * sinDeg(2 * f) + .00454 * e * sinDeg(m1 - m) + .00862 * sinDeg(2 * la.m1) + .00804 * sinDeg(2 * la.f) + .00454 * la.e * sinDeg(la.m1 - la.m)
+ .00204 * e * e * sinDeg(2 * m) - .0018 * sinDeg(m1 - 2 * f) - .0007 * sinDeg(m1 + 2 * f); + .00204 * la.e * la.e * sinDeg(2 * la.m) - .0018 * sinDeg(la.m1 - 2 * la.f)
jd += -.0004 * sinDeg(3 * m1) - .00034 * e * sinDeg(2 * m1 - m) + .00032 * e * sinDeg(m + 2 * f) - .0007 * sinDeg(la.m1 + 2 * la.f);
+ .00032 * e * sinDeg(m - 2 * f) - .00028 * e * e * sinDeg(m1 + 2 * m) jd += -.0004 * sinDeg(3 * la.m1) - .00034 * la.e * sinDeg(2 * la.m1 - la.m)
+ .00027 * e * sinDeg(2 * m1 + m) - .00017 * sinDeg(o); + .00032 * la.e * sinDeg(la.m + 2 * la.f) + .00032 * la.e * sinDeg(la.m - 2 * la.f)
jd += -.00005 * sinDeg(m1 - m - 2 * f) + .00004 * sinDeg(2 * m1 + 2 * f) - .00028 * la.e * la.e * sinDeg(la.m1 + 2 * la.m) + .00027 * la.e * sinDeg(2 * la.m1 + la.m)
- .00004 * sinDeg(m1 + m + 2 * f) + .00004 * sinDeg(m1 - 2 * m) - .00017 * sinDeg(la.o);
+ .00003 * sinDeg(m1 + m - 2 * f) + .00003 * sinDeg(3 * m) + .00002 * sinDeg(2 * m1 - 2 * f); jd += -.00005 * sinDeg(la.m1 - la.m - 2 * la.f) + .00004 * sinDeg(2 * la.m1 + 2 * la.f)
jd += .00002 * sinDeg(m1 - m + 2 * f) - .00002 * sinDeg(3 * m1 + m); - .00004 * sinDeg(la.m1 + la.m + 2 * la.f) + .00004 * sinDeg(la.m1 - 2 * la.m)
double w = .00306 - .00038 * e * cosDeg(m) + .00026 * cosDeg(m1) - .00002 * cosDeg(m1 - m) + .00003 * sinDeg(la.m1 + la.m - 2 * la.f) + .00003 * sinDeg(3 * la.m)
+ .00002 * cosDeg(m1 + m) + .00002 * cosDeg(2 * f); + .00002 * sinDeg(2 * la.m1 - 2 * la.f);
jd += .00002 * sinDeg(la.m1 - la.m + 2 * la.f) - .00002 * sinDeg(3 * la.m1 + la.m);
double w = .00306 - .00038 * la.e * cosDeg(la.m) + .00026 * cosDeg(la.m1)
- .00002 * cosDeg(la.m1 - la.m) + .00002 * cosDeg(la.m1 + la.m) + .00002 * cosDeg(2 * la.f);
jd += MoonPhase.FIRST_QUARTER.equals(phase) ? w : -w; jd += MoonPhase.FIRST_QUARTER.equals(phase) ? w : -w;
} }
return moonCorrection(jd, t, kMod); return moonCorrection(jd, la.t, la.kMod);
} }
private static double moonCorrection(double jd, double t, double k) { private static double moonCorrection(double jd, double t, double k) {
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2010-2026 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.astro.internal.calc.moon;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.astro.internal.util.AstroConstants;
import org.openhab.binding.astro.internal.util.DateTimeUtils;
/**
* Represents the fundamental lunar arguments used in analytical
* Moon position and phase calculations.
* <p>
* These angles are defined according to the classical formulation
* described in Jean Meeus, <i>Astronomical Algorithms</i>, and are
* functions of the time expressed in Julian centuries since J2000.0.
* </p>
*
* <p>
* All angular values are expressed in <strong>radians</strong>.
* </p>
*
* <ul>
* <li><b>D</b> Mean elongation of the Moon from the Sun</li>
* <li><b>M</b> Mean anomaly of the Sun (Earth)</li>
* <li><b>M</b> Mean anomaly of the Moon</li>
* <li><b>F</b> Argument of latitude of the Moon</li>
* </ul>
*
*
* <p>
* This class is immutable and serves as a shared intermediate
* representation for lunar calculations.
* </p>
*
* @see <a href="https://en.wikipedia.org/wiki/Elongation_(astronomy)">Elongation (astronomy)</a>
* @see Jean Meeus, Astronomical Algorithms, Chapter 47
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class LunarArguments {
public final double d;
public final double m;
public final double m1;
public final double f;
public LunarArguments(double jd) {
double t = DateTimeUtils.toJulianCenturies(jd);
double t2 = t * t;
double t3 = t2 * t;
double t4 = t3 * t;
this.d = Math.toRadians(297.8502042 + 445267.11151686 * t - 0.00163 * t2 + t3 / 545868 - t4 / 113065000);
this.m = Math.toRadians(AstroConstants.E05_0 + 35999.0502909 * t - 0.0001536 * t2 + t3 / 24490000);
this.m1 = Math.toRadians(134.9634114 + 477198.8676313 * t + 0.008997 * t2 + t3 / 69699 - t4 / 14712000);
this.f = Math.toRadians(93.2720993 + 483202.0175273 * t - 0.0034029 * t2 - t3 / 3526000 + t4 / 863310000);
}
}
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2010-2026 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.astro.internal.calc.moon;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.astro.internal.util.AstroConstants;
import org.openhab.binding.astro.internal.util.DateTimeUtils;
/**
* Fundamental arguments of a lunar lunation as defined by
* Jean Meeus, Astronomical Algorithms.
* <p>
* These parameters are common to the computation of:
* </p>
* <ul>
* <li>lunar phases</li>
* <li>solar eclipses</li>
* <li>lunar eclipses</li>
* </ul>
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class LunationArguments {
public final double kMod;
public final double t; // Time in Julian centuries since J2000.0.
public final double t2;
public final double m; // Mean anomaly of the Sun (degrees).
public final double m1; // Mean anomaly of the Moon (degrees).
public final double f; // Argument of latitude of the Moon (degrees).
public final double o; // Longitude of the ascending node of the Moon's orbit (degrees).
public final double e; // Earth orbital eccentricity correction factor.
public final double jde; // Mean Julian Ephemeris Day of the lunation.
public LunationArguments(double k, double adjust) {
this.kMod = Math.floor(k) + adjust;
this.t = kMod / 1236.85;
this.t2 = t * t;
double t3 = t2 * t;
double t4 = t3 * t;
this.m = 2.5534 + 29.10535669 * kMod - 0.0000218 * t2 - 0.00000011 * t3;
this.m1 = 201.5643 + 385.81693528 * kMod + 0.1017438 * t2 + 0.00001239 * t3 - 0.000000058 * t4;
this.f = 160.7108 + 390.67050274 * kMod - 0.0016341 * t2 - 0.00000227 * t3 + 0.000000011 * t4;
this.o = 124.7746 - 1.5637558 * kMod + 0.0020691 * t2 + 0.00000215 * t3;
this.e = 1 - 0.002516 * t - 0.0000074 * t2;
this.jde = 2451550.09765 + 29.530588853 * kMod + 0.0001337 * t2 - 0.00000015 * t3 + 0.00000000073 * t4;
}
public static double varK(double jd, double tz) {
return (jd + tz - DateTimeUtils.JD_2000_01_01) / AstroConstants.LUNAR_SYNODIC_MONTH_DAYS;
}
}