mirror of
https://github.com/cosinekitty/astronomy.git
synced 2026-05-18 22:01:42 -04:00
Kotlin: obscuration for solar, lunar eclipses.
This commit is contained in:
@@ -1,50 +1,50 @@
|
||||
1988-03-03T16:04:42.484Z Partial eclipse begins.
|
||||
1988-03-03T16:13:29.227Z Peak of partial eclipse.
|
||||
1988-03-03T16:22:15.969Z Partial eclipse ends.
|
||||
1988-03-03T16:05:01.550Z Partial eclipse begins.
|
||||
1988-03-03T16:12:44.158Z Peak of partial eclipse.
|
||||
1988-03-03T16:20:26.766Z Partial eclipse ends.
|
||||
|
||||
1988-08-27T10:07:57.337Z Partial eclipse begins.
|
||||
1988-08-27T11:05:04.752Z Peak of partial eclipse.
|
||||
1988-08-27T12:02:12.167Z Partial eclipse ends.
|
||||
1988-08-27T10:07:28.657Z Partial eclipse begins.
|
||||
1988-08-27T11:04:30.914Z Peak of partial eclipse.
|
||||
1988-08-27T12:01:33.171Z Partial eclipse ends.
|
||||
|
||||
1989-02-20T13:44:07.826Z Partial eclipse begins.
|
||||
1989-02-20T14:56:15.429Z Total eclipse begins.
|
||||
1989-02-20T15:36:04.477Z Peak of total eclipse.
|
||||
1989-02-20T16:15:53.525Z Total eclipse ends.
|
||||
1989-02-20T17:28:01.129Z Partial eclipse ends.
|
||||
1989-02-20T13:43:24.717Z Partial eclipse begins.
|
||||
1989-02-20T14:55:34.838Z Total eclipse begins.
|
||||
1989-02-20T15:35:19.955Z Peak of total eclipse.
|
||||
1989-02-20T16:15:05.072Z Total eclipse ends.
|
||||
1989-02-20T17:27:15.193Z Partial eclipse ends.
|
||||
|
||||
1989-08-17T01:21:19.201Z Partial eclipse begins.
|
||||
1989-08-17T02:20:31.653Z Total eclipse begins.
|
||||
1989-08-17T03:08:46.679Z Peak of total eclipse.
|
||||
1989-08-17T03:57:01.705Z Total eclipse ends.
|
||||
1989-08-17T04:56:14.157Z Partial eclipse ends.
|
||||
1989-08-17T01:20:43.868Z Partial eclipse begins.
|
||||
1989-08-17T02:19:56.975Z Total eclipse begins.
|
||||
1989-08-17T03:08:10.847Z Peak of total eclipse.
|
||||
1989-08-17T03:56:24.718Z Total eclipse ends.
|
||||
1989-08-17T04:55:37.826Z Partial eclipse ends.
|
||||
|
||||
1990-02-09T17:29:19.371Z Partial eclipse begins.
|
||||
1990-02-09T18:50:02.142Z Total eclipse begins.
|
||||
1990-02-09T19:11:46.638Z Peak of total eclipse.
|
||||
1990-02-09T19:33:31.134Z Total eclipse ends.
|
||||
1990-02-09T20:54:13.906Z Partial eclipse ends.
|
||||
1990-02-09T17:28:36.915Z Partial eclipse begins.
|
||||
1990-02-09T18:49:12.803Z Total eclipse begins.
|
||||
1990-02-09T19:11:06.009Z Peak of total eclipse.
|
||||
1990-02-09T19:32:59.214Z Total eclipse ends.
|
||||
1990-02-09T20:53:35.102Z Partial eclipse ends.
|
||||
|
||||
1990-08-06T12:44:54.289Z Partial eclipse begins.
|
||||
1990-08-06T14:13:00.287Z Peak of partial eclipse.
|
||||
1990-08-06T15:41:06.284Z Partial eclipse ends.
|
||||
1990-08-06T12:44:10.958Z Partial eclipse begins.
|
||||
1990-08-06T14:12:20.198Z Peak of partial eclipse.
|
||||
1990-08-06T15:40:29.439Z Partial eclipse ends.
|
||||
|
||||
1991-12-21T10:00:27.418Z Partial eclipse begins.
|
||||
1991-12-21T10:33:39.369Z Peak of partial eclipse.
|
||||
1991-12-21T11:06:51.320Z Partial eclipse ends.
|
||||
1991-12-21T10:00:02.660Z Partial eclipse begins.
|
||||
1991-12-21T10:33:04.083Z Peak of partial eclipse.
|
||||
1991-12-21T11:06:05.507Z Partial eclipse ends.
|
||||
|
||||
1992-06-15T03:27:15.070Z Partial eclipse begins.
|
||||
1992-06-15T04:57:38.272Z Peak of partial eclipse.
|
||||
1992-06-15T06:28:01.473Z Partial eclipse ends.
|
||||
1992-06-15T03:26:36.541Z Partial eclipse begins.
|
||||
1992-06-15T04:56:56.391Z Peak of partial eclipse.
|
||||
1992-06-15T06:27:16.242Z Partial eclipse ends.
|
||||
|
||||
1992-12-09T21:59:59.280Z Partial eclipse begins.
|
||||
1992-12-09T23:07:16.402Z Total eclipse begins.
|
||||
1992-12-09T23:44:42.637Z Peak of total eclipse.
|
||||
1992-12-10T00:22:08.872Z Total eclipse ends.
|
||||
1992-12-10T01:29:25.994Z Partial eclipse ends.
|
||||
1992-12-09T21:59:22.079Z Partial eclipse begins.
|
||||
1992-12-09T23:06:41.497Z Total eclipse begins.
|
||||
1992-12-09T23:44:04.198Z Peak of total eclipse.
|
||||
1992-12-10T00:21:26.898Z Total eclipse ends.
|
||||
1992-12-10T01:28:46.316Z Partial eclipse ends.
|
||||
|
||||
1993-06-04T11:11:48.333Z Partial eclipse begins.
|
||||
1993-06-04T12:12:49.448Z Total eclipse begins.
|
||||
1993-06-04T13:01:01.724Z Peak of total eclipse.
|
||||
1993-06-04T13:49:14.000Z Total eclipse ends.
|
||||
1993-06-04T14:50:15.116Z Partial eclipse ends.
|
||||
1993-06-04T11:11:10.309Z Partial eclipse begins.
|
||||
1993-06-04T12:12:10.636Z Total eclipse begins.
|
||||
1993-06-04T13:00:24.283Z Peak of total eclipse.
|
||||
1993-06-04T13:48:37.931Z Total eclipse ends.
|
||||
1993-06-04T14:49:38.257Z Partial eclipse ends.
|
||||
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
1988-03-03T16:04:42.484Z Partial eclipse begins.
|
||||
1988-03-03T16:13:29.227Z Peak of partial eclipse.
|
||||
1988-03-03T16:22:15.969Z Partial eclipse ends.
|
||||
1988-03-03T16:05:01.550Z Partial eclipse begins.
|
||||
1988-03-03T16:12:44.158Z Peak of partial eclipse.
|
||||
1988-03-03T16:20:26.766Z Partial eclipse ends.
|
||||
|
||||
1988-08-27T10:07:57.337Z Partial eclipse begins.
|
||||
1988-08-27T11:05:04.752Z Peak of partial eclipse.
|
||||
1988-08-27T12:02:12.167Z Partial eclipse ends.
|
||||
1988-08-27T10:07:28.657Z Partial eclipse begins.
|
||||
1988-08-27T11:04:30.914Z Peak of partial eclipse.
|
||||
1988-08-27T12:01:33.171Z Partial eclipse ends.
|
||||
|
||||
1989-02-20T13:44:07.826Z Partial eclipse begins.
|
||||
1989-02-20T14:56:15.429Z Total eclipse begins.
|
||||
1989-02-20T15:36:04.477Z Peak of total eclipse.
|
||||
1989-02-20T16:15:53.525Z Total eclipse ends.
|
||||
1989-02-20T17:28:01.129Z Partial eclipse ends.
|
||||
1989-02-20T13:43:24.717Z Partial eclipse begins.
|
||||
1989-02-20T14:55:34.838Z Total eclipse begins.
|
||||
1989-02-20T15:35:19.955Z Peak of total eclipse.
|
||||
1989-02-20T16:15:05.072Z Total eclipse ends.
|
||||
1989-02-20T17:27:15.193Z Partial eclipse ends.
|
||||
|
||||
1989-08-17T01:21:19.201Z Partial eclipse begins.
|
||||
1989-08-17T02:20:31.653Z Total eclipse begins.
|
||||
1989-08-17T03:08:46.679Z Peak of total eclipse.
|
||||
1989-08-17T03:57:01.705Z Total eclipse ends.
|
||||
1989-08-17T04:56:14.157Z Partial eclipse ends.
|
||||
1989-08-17T01:20:43.868Z Partial eclipse begins.
|
||||
1989-08-17T02:19:56.975Z Total eclipse begins.
|
||||
1989-08-17T03:08:10.847Z Peak of total eclipse.
|
||||
1989-08-17T03:56:24.718Z Total eclipse ends.
|
||||
1989-08-17T04:55:37.826Z Partial eclipse ends.
|
||||
|
||||
1990-02-09T17:29:19.371Z Partial eclipse begins.
|
||||
1990-02-09T18:50:02.142Z Total eclipse begins.
|
||||
1990-02-09T19:11:46.638Z Peak of total eclipse.
|
||||
1990-02-09T19:33:31.134Z Total eclipse ends.
|
||||
1990-02-09T20:54:13.906Z Partial eclipse ends.
|
||||
1990-02-09T17:28:36.915Z Partial eclipse begins.
|
||||
1990-02-09T18:49:12.803Z Total eclipse begins.
|
||||
1990-02-09T19:11:06.009Z Peak of total eclipse.
|
||||
1990-02-09T19:32:59.214Z Total eclipse ends.
|
||||
1990-02-09T20:53:35.102Z Partial eclipse ends.
|
||||
|
||||
1990-08-06T12:44:54.289Z Partial eclipse begins.
|
||||
1990-08-06T14:13:00.287Z Peak of partial eclipse.
|
||||
1990-08-06T15:41:06.284Z Partial eclipse ends.
|
||||
1990-08-06T12:44:10.958Z Partial eclipse begins.
|
||||
1990-08-06T14:12:20.198Z Peak of partial eclipse.
|
||||
1990-08-06T15:40:29.439Z Partial eclipse ends.
|
||||
|
||||
1991-12-21T10:00:27.418Z Partial eclipse begins.
|
||||
1991-12-21T10:33:39.369Z Peak of partial eclipse.
|
||||
1991-12-21T11:06:51.320Z Partial eclipse ends.
|
||||
1991-12-21T10:00:02.660Z Partial eclipse begins.
|
||||
1991-12-21T10:33:04.083Z Peak of partial eclipse.
|
||||
1991-12-21T11:06:05.507Z Partial eclipse ends.
|
||||
|
||||
1992-06-15T03:27:15.070Z Partial eclipse begins.
|
||||
1992-06-15T04:57:38.272Z Peak of partial eclipse.
|
||||
1992-06-15T06:28:01.473Z Partial eclipse ends.
|
||||
1992-06-15T03:26:36.541Z Partial eclipse begins.
|
||||
1992-06-15T04:56:56.391Z Peak of partial eclipse.
|
||||
1992-06-15T06:27:16.242Z Partial eclipse ends.
|
||||
|
||||
1992-12-09T21:59:59.280Z Partial eclipse begins.
|
||||
1992-12-09T23:07:16.402Z Total eclipse begins.
|
||||
1992-12-09T23:44:42.637Z Peak of total eclipse.
|
||||
1992-12-10T00:22:08.872Z Total eclipse ends.
|
||||
1992-12-10T01:29:25.994Z Partial eclipse ends.
|
||||
1992-12-09T21:59:22.079Z Partial eclipse begins.
|
||||
1992-12-09T23:06:41.497Z Total eclipse begins.
|
||||
1992-12-09T23:44:04.198Z Peak of total eclipse.
|
||||
1992-12-10T00:21:26.898Z Total eclipse ends.
|
||||
1992-12-10T01:28:46.316Z Partial eclipse ends.
|
||||
|
||||
1993-06-04T11:11:48.333Z Partial eclipse begins.
|
||||
1993-06-04T12:12:49.448Z Total eclipse begins.
|
||||
1993-06-04T13:01:01.724Z Peak of total eclipse.
|
||||
1993-06-04T13:49:14.000Z Total eclipse ends.
|
||||
1993-06-04T14:50:15.116Z Partial eclipse ends.
|
||||
1993-06-04T11:11:10.309Z Partial eclipse begins.
|
||||
1993-06-04T12:12:10.636Z Total eclipse begins.
|
||||
1993-06-04T13:00:24.283Z Peak of total eclipse.
|
||||
1993-06-04T13:48:37.931Z Total eclipse ends.
|
||||
1993-06-04T14:49:38.257Z Partial eclipse ends.
|
||||
|
||||
|
||||
@@ -2929,7 +2929,7 @@ namespace csharp_test
|
||||
}
|
||||
|
||||
double diff = v(eclipse.obscuration - obscuration);
|
||||
if (diff > tolerance)
|
||||
if (Math.Abs(diff) > tolerance)
|
||||
{
|
||||
Console.WriteLine($"C# LocalSolarCase({year:0000}-{month:00}-{day:00}) FAIL: obscuration diff = {diff:F8}, expected = {obscuration:F8}, calculated = {eclipse.obscuration:F8}.");
|
||||
return 1;
|
||||
@@ -2943,7 +2943,6 @@ namespace csharp_test
|
||||
// Verify global solar eclipse obscurations for annular eclipses only.
|
||||
// This is because they are the only nontrivial values for global solar eclipses.
|
||||
// The trivial values are all validated exactly by GlobalSolarEclipseTest().
|
||||
|
||||
if (0 != GlobalAnnularCase(2023, 10, 14, 0.90638)) return 1; // https://www.eclipsewise.com/solar/SEprime/2001-2100/SE2023Oct14Aprime.html
|
||||
if (0 != GlobalAnnularCase(2024, 10, 2, 0.86975)) return 1; // https://www.eclipsewise.com/solar/SEprime/2001-2100/SE2024Oct02Aprime.html
|
||||
if (0 != GlobalAnnularCase(2027, 2, 6, 0.86139)) return 1; // https://www.eclipsewise.com/solar/SEprime/2001-2100/SE2027Feb06Aprime.html
|
||||
|
||||
@@ -179,9 +179,10 @@ private const val EARTH_MEAN_RADIUS_KM = 6371.0 // mean radius of the Earth's
|
||||
private const val EARTH_ATMOSPHERE_KM = 88.0 // effective atmosphere thickness for lunar eclipses
|
||||
private const val EARTH_ECLIPSE_RADIUS_KM = EARTH_MEAN_RADIUS_KM + EARTH_ATMOSPHERE_KM
|
||||
private const val MOON_EQUATORIAL_RADIUS_KM = 1738.1
|
||||
private const val MOON_EQUATORIAL_RADIUS_AU = (MOON_EQUATORIAL_RADIUS_KM / KM_PER_AU)
|
||||
private const val MOON_MEAN_RADIUS_KM = 1737.4
|
||||
private const val MOON_POLAR_RADIUS_KM = 1736.0
|
||||
private const val MOON_EQUATORIAL_RADIUS_AU = (MOON_EQUATORIAL_RADIUS_KM / KM_PER_AU)
|
||||
private const val MOON_POLAR_RADIUS_AU = (MOON_POLAR_RADIUS_KM / KM_PER_AU)
|
||||
private const val ANGVEL = 7.2921150e-5
|
||||
private const val SOLAR_DAYS_PER_SIDEREAL_DAY = 0.9972695717592592
|
||||
private const val MEAN_SYNODIC_MONTH = 29.530588 // average number of days for Moon to return to the same phase
|
||||
@@ -1790,6 +1791,12 @@ enum class EclipseKind {
|
||||
* The `kind` field thus holds `EclipseKind.Penumbral`, `EclipseKind.Partial`,
|
||||
* or `EclipseKind.Total`, depending on the kind of lunar eclipse found.
|
||||
*
|
||||
* The `obscuration` field holds a value in the range [0, 1] that indicates what fraction
|
||||
* of the Moon's apparent disc area is covered by the Earth's umbra at the eclipse's peak.
|
||||
* This indicates how dark the peak eclipse appears. For penumbral eclipses, the obscuration
|
||||
* is 0, because the Moon does not pass through the Earth's umbra. For partial eclipses,
|
||||
* the obscuration is somewhere between 0 and 1. For total lunar eclipses, the obscuration is 1.
|
||||
*
|
||||
* Field `peak` holds the date and time of the center of the eclipse, when it is at its peak.
|
||||
*
|
||||
* Fields `sdPenum`, `sdPartial`, and `sdTotal` hold the semi-duration of each phase
|
||||
@@ -1804,6 +1811,11 @@ class LunarEclipseInfo(
|
||||
*/
|
||||
val kind: EclipseKind,
|
||||
|
||||
/**
|
||||
* The peak fraction of the Moon's apparent disc that is covered by the Earth's umbra.
|
||||
*/
|
||||
val obscuration: Double,
|
||||
|
||||
/**
|
||||
* The time of the eclipse at its peak.
|
||||
*/
|
||||
@@ -1848,6 +1860,17 @@ class LunarEclipseInfo(
|
||||
* onto the daytime side of the Earth at the instant of the eclipse's peak.
|
||||
* If `kind` has any other value, `latitude` and `longitude` are undefined and should
|
||||
* not be used.
|
||||
*
|
||||
* For total or annular eclipses, the `obscuration` field holds the fraction (0, 1]
|
||||
* of the Sun's apparent disc area that is blocked from view by the Moon's silhouette,
|
||||
* as seen by an observer located at the geographic coordinates `latitude`, `longitude`
|
||||
* at the darkest time `peak`. The value will always be 1 for total eclipses, and less than
|
||||
* 1 for annular eclipses.
|
||||
* For partial eclipses, `obscuration` is undefined and should not be used.
|
||||
* This is because there is little practical use for an obscuration value of
|
||||
* a partial eclipse without supplying a particular observation location.
|
||||
* Developers who wish to find an obscuration value for partial solar eclipses should therefore use
|
||||
* [searchLocalSolarEclipse] and provide the geographic coordinates of an observer.
|
||||
*/
|
||||
class GlobalSolarEclipseInfo(
|
||||
/**
|
||||
@@ -1855,6 +1878,11 @@ class GlobalSolarEclipseInfo(
|
||||
*/
|
||||
val kind: EclipseKind,
|
||||
|
||||
/**
|
||||
* The peak fraction of the Sun's apparent disc area obscured by the Moon (total and annular eclipses only).
|
||||
*/
|
||||
val obscuration: Double,
|
||||
|
||||
/**
|
||||
* The date and time when the solar eclipse is darkest.
|
||||
* This is the instant when the axis of the Moon's shadow cone passes closest to the Earth's center.
|
||||
@@ -1922,6 +1950,13 @@ class EclipseEvent (
|
||||
* A total eclipse occurs when the Moon is close enough to the Earth and aligned with the
|
||||
* Sun just right to completely block all sunlight from reaching the observer.
|
||||
*
|
||||
* The `obscuration` field reports what fraction of the Sun's disc appears blocked
|
||||
* by the Moon when viewed by the observer at the peak eclipse time.
|
||||
* This is a value that ranges from 0 (no blockage) to 1 (total eclipse).
|
||||
* The obscuration value will be between 0 and 1 for partial eclipses and annular eclipses.
|
||||
* The value will be exactly 1 for total eclipses. Obscuration gives an indication
|
||||
* of how dark the eclipse appears.
|
||||
*
|
||||
* There are 5 "event" fields, each of which contains a time and a solar altitude.
|
||||
* Field `peak` holds the date and time of the center of the eclipse, when it is at its peak.
|
||||
* The fields `partialBegin` and `partialEnd` are always set, and indicate when
|
||||
@@ -1937,6 +1972,11 @@ class LocalSolarEclipseInfo (
|
||||
*/
|
||||
val kind: EclipseKind,
|
||||
|
||||
/**
|
||||
* The fraction of the Sun's apparent disc area obscured by the Moon at the eclipse peak.
|
||||
*/
|
||||
val obscuration: Double,
|
||||
|
||||
/**
|
||||
* The time and Sun altitude at the beginning of the eclipse.
|
||||
*/
|
||||
@@ -2054,44 +2094,42 @@ internal fun calcShadow(
|
||||
|
||||
internal fun earthShadow(time: Time): ShadowInfo {
|
||||
// This function helps find when the Earth's shadow falls upon the Moon.
|
||||
val e = helioEarthPos(time)
|
||||
val s = geoVector(Body.Sun, time, Aberration.Corrected)
|
||||
val m = geoMoon(time)
|
||||
return calcShadow(EARTH_ECLIPSE_RADIUS_KM, time, m, e)
|
||||
return calcShadow(EARTH_ECLIPSE_RADIUS_KM, time, m, -s)
|
||||
}
|
||||
|
||||
internal fun moonShadow(time: Time): ShadowInfo {
|
||||
// This function helps find when the Moon's shadow falls upon the Earth.
|
||||
// This is a variation on the logic in EarthShadow().
|
||||
// Instead of a heliocentric Earth and a geocentric Moon,
|
||||
// we want a heliocentric Moon and a lunacentric Earth.
|
||||
|
||||
val e = helioEarthPos(time)
|
||||
val s = geoVector(Body.Sun, time, Aberration.Corrected)
|
||||
val m = geoMoon(time)
|
||||
|
||||
// -m = lunacentric Earth
|
||||
// m+e = heliocentric Moon
|
||||
return calcShadow(MOON_MEAN_RADIUS_KM, time, -m, m+e)
|
||||
// m-s = heliocentric Moon
|
||||
return calcShadow(MOON_MEAN_RADIUS_KM, time, -m, m-s)
|
||||
}
|
||||
|
||||
internal fun localMoonShadow(time: Time, observer: Observer): ShadowInfo {
|
||||
// Calculate observer's geocentric position.
|
||||
// For efficiency, do this first, to populate the earth rotation parameters in 'time'.
|
||||
// That way they can be recycled instead of recalculated.
|
||||
val o = geoPos(time, observer)
|
||||
val h = helioEarthPos(time)
|
||||
|
||||
// Calculate light-travel and aberration corrected Sun.
|
||||
val s = geoVector(Body.Sun, time, Aberration.Corrected)
|
||||
|
||||
// Calculate geocentric Moon.
|
||||
val m = geoMoon(time)
|
||||
|
||||
// o-m = lunacentric observer
|
||||
// m+h = heliocentric Moon
|
||||
return calcShadow(MOON_MEAN_RADIUS_KM, time, o-m, m+h)
|
||||
// m-s = heliocentric Moon
|
||||
return calcShadow(MOON_MEAN_RADIUS_KM, time, o-m, m-s)
|
||||
}
|
||||
|
||||
internal fun planetShadow(body: Body, planetRadiusKm: Double, time: Time): ShadowInfo {
|
||||
// Calculate light-travel-corrected vector from Earth to planet.
|
||||
val g = geoVector(body, time, Aberration.None)
|
||||
val g = geoVector(body, time, Aberration.Corrected)
|
||||
|
||||
// Calculate light-travel-corrected vector from Earth to Sun.
|
||||
val e = geoVector(Body.Sun, time, Aberration.None)
|
||||
val e = geoVector(Body.Sun, time, Aberration.Corrected)
|
||||
|
||||
// -g = planetocentric Earth
|
||||
// g-e = heliocentric planet
|
||||
@@ -2137,7 +2175,6 @@ internal fun peakEarthShadow(searchCenterTime: Time): ShadowInfo {
|
||||
return earthShadow(tx)
|
||||
}
|
||||
|
||||
|
||||
internal val moonShadowSlopeContext = SearchContext { time ->
|
||||
val dt = 1.0 / SECONDS_PER_DAY
|
||||
val t1 = time.addDays(-dt)
|
||||
@@ -2196,6 +2233,69 @@ internal fun planetTransitBoundary(body: Body, planetRadiusKm: Double, t1: Time,
|
||||
} ?: throw InternalError("Planet transit boundary search failed.")
|
||||
}
|
||||
|
||||
internal fun discObscuration(a: Double, b: Double, c: Double): Double {
|
||||
// a = radius of first disc
|
||||
// b = radius of second disc
|
||||
// c = distance between centers of discs
|
||||
if (a <= 0.0) throw InternalError("Radius of first disc must be positive.")
|
||||
if (b <= 0.0) throw InternalError("Radius of second disc must be positive.")
|
||||
if (c < 0.0) throw InternalError("Distance between discs is not allowed to be negative.")
|
||||
|
||||
if (c >= a + b) {
|
||||
// The discs are too far apart to have any overlapping area.
|
||||
return 0.0
|
||||
}
|
||||
|
||||
if (c == 0.0) {
|
||||
// The discs have a common center. Therefore, one disc is inside the other.
|
||||
return if (a <= b) 1.0 else (b*b)/(a*a)
|
||||
}
|
||||
|
||||
val x = (a*a - b*b + c*c) / (2*c)
|
||||
val radicand = a*a - x*x
|
||||
if (radicand <= 0.0) {
|
||||
// The circumferences do not intersect, or are tangent.
|
||||
// We already ruled out the case of non-overlapping discs.
|
||||
// Therefore, one disc is inside the other.
|
||||
return if (a <= b) 1.0 else (b*b)/(a*a)
|
||||
}
|
||||
|
||||
// The discs overlap fractionally in a pair of lens-shaped areas.
|
||||
|
||||
val y = sqrt(radicand)
|
||||
|
||||
// Return the overlapping fractional area.
|
||||
// There are two lens-shaped areas, one to the left of x, the other to the right of x.
|
||||
// Each part is calculated by subtracting a triangular area from a sector's area.
|
||||
val lens1 = a*a*acos(x/a) - x*y
|
||||
val lens2 = b*b*acos((c-x)/b) - (c-x)*y
|
||||
|
||||
// Find the fractional area with respect to the first disc.
|
||||
return (lens1 + lens2) / (PI*a*a)
|
||||
}
|
||||
|
||||
|
||||
internal fun solarEclipseObscuration(hm: Vector, lo: Vector): Double {
|
||||
// Find heliocentric observer.
|
||||
val ho = hm + lo
|
||||
|
||||
// Calculate the apparent angular radius of the Sun for the observer.
|
||||
val sunRadius = asin(SUN_RADIUS_AU / ho.length())
|
||||
|
||||
// Calculate the apparent angular radius of the Moon for the observer.
|
||||
val moonRadius = asin(MOON_POLAR_RADIUS_AU / lo.length())
|
||||
|
||||
// Calculate the apparent angular separation between the Sun's center and the Moon's center.
|
||||
val sunMoonSeparation = lo.angleWith(ho).degreesToRadians()
|
||||
|
||||
// Find the fraction of the Sun's apparent disc area that is covered by the Moon.
|
||||
val obscuration = discObscuration(sunRadius, moonRadius, sunMoonSeparation)
|
||||
|
||||
// HACK: In marginal cases, we need to clamp obscuration to less than 1.0.
|
||||
// This function is never called for total eclipses, so it should never return 1.0.
|
||||
return min(0.9999, obscuration)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Searches for a lunar eclipse.
|
||||
@@ -2234,6 +2334,7 @@ fun searchLunarEclipse(startTime: Time): LunarEclipseInfo {
|
||||
if (shadow.r < shadow.p + MOON_MEAN_RADIUS_KM) {
|
||||
// This is at least a penumbral eclipse. We will return a result.
|
||||
var kind = EclipseKind.Penumbral
|
||||
var obscuration = 0.0
|
||||
val sdPenum = shadowSemiDurationMinutes(shadow.time, shadow.p + MOON_MEAN_RADIUS_KM, 200.0)
|
||||
var sdPartial = 0.0
|
||||
var sdTotal = 0.0
|
||||
@@ -2246,11 +2347,14 @@ fun searchLunarEclipse(startTime: Time): LunarEclipseInfo {
|
||||
if (shadow.r + MOON_MEAN_RADIUS_KM < shadow.k) {
|
||||
// This is a total eclipse.
|
||||
kind = EclipseKind.Total
|
||||
obscuration = 1.0
|
||||
sdTotal = shadowSemiDurationMinutes(shadow.time, shadow.k - MOON_MEAN_RADIUS_KM, sdPartial)
|
||||
} else {
|
||||
obscuration = discObscuration(MOON_MEAN_RADIUS_KM, shadow.k, shadow.r)
|
||||
}
|
||||
}
|
||||
|
||||
return LunarEclipseInfo(kind, shadow.time, sdPenum, sdPartial, sdTotal)
|
||||
return LunarEclipseInfo(kind, obscuration, shadow.time, sdPenum, sdPartial, sdTotal)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2324,6 +2428,7 @@ internal fun eclipseKindFromUmbra(k: Double) = (
|
||||
|
||||
internal fun geoidIntersect(shadow: ShadowInfo): GlobalSolarEclipseInfo {
|
||||
var kind = EclipseKind.Partial
|
||||
var obscuration = Double.NaN
|
||||
var latitude = Double.NaN
|
||||
var longitude = Double.NaN
|
||||
|
||||
@@ -2385,9 +2490,10 @@ internal fun geoidIntersect(shadow: ShadowInfo): GlobalSolarEclipseInfo {
|
||||
throw InternalError("Invalid surface distance from intersection.")
|
||||
|
||||
kind = eclipseKindFromUmbra(surface.k)
|
||||
obscuration = if (kind == EclipseKind.Total) 1.0 else solarEclipseObscuration(shadow.dir, luna)
|
||||
}
|
||||
|
||||
return GlobalSolarEclipseInfo(kind, shadow.time, shadow.r, latitude, longitude)
|
||||
return GlobalSolarEclipseInfo(kind, obscuration, shadow.time, shadow.r, latitude, longitude)
|
||||
}
|
||||
|
||||
|
||||
@@ -2549,7 +2655,8 @@ internal fun localEclipse(shadow: ShadowInfo, observer: Observer): LocalSolarEcl
|
||||
} else {
|
||||
kind = EclipseKind.Partial
|
||||
}
|
||||
return LocalSolarEclipseInfo(kind, partialBegin, totalBegin, peak, totalEnd, partialEnd)
|
||||
val obscuration = if (kind == EclipseKind.Total) 1.0 else solarEclipseObscuration(shadow.dir, shadow.target)
|
||||
return LocalSolarEclipseInfo(kind, obscuration, partialBegin, totalBegin, peak, totalEnd, partialEnd)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -948,7 +948,7 @@ function LocalSolarCase(dateText, latitude, longitude, kind, obscuration, tolera
|
||||
}
|
||||
|
||||
const diff = v(eclipse.obscuration - obscuration);
|
||||
if (diff > tolerance) {
|
||||
if (abs(diff) > tolerance) {
|
||||
console.error(`JS LocalSolarCase(${dateText}) FAIL: obscuration diff = ${diff}, expected = ${obscuration}, actual = ${eclipse.obscuration}.`);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1796,7 +1796,7 @@ def LocalSolarCase(year, month, day, latitude, longitude, kind, obscuration, tol
|
||||
return Fail(funcname, 'expected {} eclipse, but found {}.'.format(kind, eclipse.kind))
|
||||
|
||||
diff = v(eclipse.obscuration - obscuration)
|
||||
if diff > tolerance:
|
||||
if abs(diff) > tolerance:
|
||||
return Fail(funcname, 'obscuration diff = {:0.8f}, expected = {:0.8f}, actual = {:0.8f}'.format(diff, obscuration, eclipse.obscuration))
|
||||
|
||||
Debug('{}: obscuration diff = {:11.8f}'.format(funcname, diff))
|
||||
|
||||
@@ -89,7 +89,7 @@ movement through the Solar System.
|
||||
| [ElongationInfo](doc/-elongation-info/index.md)<br>class [ElongationInfo](doc/-elongation-info/index.md)(time: [Time](doc/-time/index.md), visibility: [Visibility](doc/-visibility/index.md), elongation: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), eclipticSeparation: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Contains information about the visibility of a celestial body at a given date and time. |
|
||||
| [EquatorEpoch](doc/-equator-epoch/index.md)<br>enum [EquatorEpoch](doc/-equator-epoch/index.md) : [Enum](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-enum/index.html)<[EquatorEpoch](doc/-equator-epoch/index.md)> <br>Selects the date for which the Earth's equator is to be used for representing equatorial coordinates. |
|
||||
| [Equatorial](doc/-equatorial/index.md)<br>class [Equatorial](doc/-equatorial/index.md)(ra: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), dec: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), dist: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), vec: [Vector](doc/-vector/index.md))<br>Equatorial angular and cartesian coordinates. |
|
||||
| [GlobalSolarEclipseInfo](doc/-global-solar-eclipse-info/index.md)<br>class [GlobalSolarEclipseInfo](doc/-global-solar-eclipse-info/index.md)(kind: [EclipseKind](doc/-eclipse-kind/index.md), peak: [Time](doc/-time/index.md), distance: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), longitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Reports the time and geographic location of the peak of a solar eclipse. |
|
||||
| [GlobalSolarEclipseInfo](doc/-global-solar-eclipse-info/index.md)<br>class [GlobalSolarEclipseInfo](doc/-global-solar-eclipse-info/index.md)(kind: [EclipseKind](doc/-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), peak: [Time](doc/-time/index.md), distance: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), longitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Reports the time and geographic location of the peak of a solar eclipse. |
|
||||
| [GravitySimulator](doc/-gravity-simulator/index.md)<br>class [GravitySimulator](doc/-gravity-simulator/index.md)<br>A simulation of zero or more small bodies moving through the Solar System. |
|
||||
| [HourAngleInfo](doc/-hour-angle-info/index.md)<br>class [HourAngleInfo](doc/-hour-angle-info/index.md)(time: [Time](doc/-time/index.md), hor: [Topocentric](doc/-topocentric/index.md))<br>Information about a celestial body crossing a specific hour angle. |
|
||||
| [IlluminationInfo](doc/-illumination-info/index.md)<br>class [IlluminationInfo](doc/-illumination-info/index.md)(time: [Time](doc/-time/index.md), mag: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), phaseAngle: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), phaseFraction: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), helioDist: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), ringTilt: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Information about the brightness and illuminated shape of a celestial body. |
|
||||
@@ -97,8 +97,8 @@ movement through the Solar System.
|
||||
| [InvalidBodyException](doc/-invalid-body-exception/index.md)<br>class [InvalidBodyException](doc/-invalid-body-exception/index.md)(body: [Body](doc/-body/index.md)) : [Exception](https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html)<br>An invalid body was specified for the given function. |
|
||||
| [JupiterMoonsInfo](doc/-jupiter-moons-info/index.md)<br>class [JupiterMoonsInfo](doc/-jupiter-moons-info/index.md)(io: [StateVector](doc/-state-vector/index.md), europa: [StateVector](doc/-state-vector/index.md), ganymede: [StateVector](doc/-state-vector/index.md), callisto: [StateVector](doc/-state-vector/index.md))<br>Holds the positions and velocities of Jupiter's major 4 moons. |
|
||||
| [LibrationInfo](doc/-libration-info/index.md)<br>data class [LibrationInfo](doc/-libration-info/index.md)(elat: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), elon: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), mlat: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), mlon: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), distanceKm: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), diamDeg: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Lunar libration angles, returned by [libration](doc/libration.md). |
|
||||
| [LocalSolarEclipseInfo](doc/-local-solar-eclipse-info/index.md)<br>class [LocalSolarEclipseInfo](doc/-local-solar-eclipse-info/index.md)(kind: [EclipseKind](doc/-eclipse-kind/index.md), partialBegin: [EclipseEvent](doc/-eclipse-event/index.md), totalBegin: [EclipseEvent](doc/-eclipse-event/index.md)?, peak: [EclipseEvent](doc/-eclipse-event/index.md), totalEnd: [EclipseEvent](doc/-eclipse-event/index.md)?, partialEnd: [EclipseEvent](doc/-eclipse-event/index.md))<br>Information about a solar eclipse as seen by an observer at a given time and geographic location. |
|
||||
| [LunarEclipseInfo](doc/-lunar-eclipse-info/index.md)<br>class [LunarEclipseInfo](doc/-lunar-eclipse-info/index.md)(kind: [EclipseKind](doc/-eclipse-kind/index.md), peak: [Time](doc/-time/index.md), sdPenum: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdPartial: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdTotal: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Information about a lunar eclipse. |
|
||||
| [LocalSolarEclipseInfo](doc/-local-solar-eclipse-info/index.md)<br>class [LocalSolarEclipseInfo](doc/-local-solar-eclipse-info/index.md)(kind: [EclipseKind](doc/-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), partialBegin: [EclipseEvent](doc/-eclipse-event/index.md), totalBegin: [EclipseEvent](doc/-eclipse-event/index.md)?, peak: [EclipseEvent](doc/-eclipse-event/index.md), totalEnd: [EclipseEvent](doc/-eclipse-event/index.md)?, partialEnd: [EclipseEvent](doc/-eclipse-event/index.md))<br>Information about a solar eclipse as seen by an observer at a given time and geographic location. |
|
||||
| [LunarEclipseInfo](doc/-lunar-eclipse-info/index.md)<br>class [LunarEclipseInfo](doc/-lunar-eclipse-info/index.md)(kind: [EclipseKind](doc/-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), peak: [Time](doc/-time/index.md), sdPenum: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdPartial: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdTotal: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Information about a lunar eclipse. |
|
||||
| [MoonQuarterInfo](doc/-moon-quarter-info/index.md)<br>class [MoonQuarterInfo](doc/-moon-quarter-info/index.md)(quarter: [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html), time: [Time](doc/-time/index.md))<br>A lunar quarter event (new moon, first quarter, full moon, or third quarter) along with its date and time. |
|
||||
| [NodeEventInfo](doc/-node-event-info/index.md)<br>class [NodeEventInfo](doc/-node-event-info/index.md)(time: [Time](doc/-time/index.md), kind: [NodeEventKind](doc/-node-event-kind/index.md))<br>Information about an ascending or descending node of a body. |
|
||||
| [NodeEventKind](doc/-node-event-kind/index.md)<br>enum [NodeEventKind](doc/-node-event-kind/index.md) : [Enum](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-enum/index.html)<[NodeEventKind](doc/-node-event-kind/index.md)> <br>Indicates whether a crossing through the ecliptic plane is ascending or descending. |
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
# GlobalSolarEclipseInfo
|
||||
|
||||
fun [GlobalSolarEclipseInfo](-global-solar-eclipse-info.md)(kind: [EclipseKind](../-eclipse-kind/index.md), peak: [Time](../-time/index.md), distance: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), longitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))
|
||||
fun [GlobalSolarEclipseInfo](-global-solar-eclipse-info.md)(kind: [EclipseKind](../-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), peak: [Time](../-time/index.md), distance: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), longitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# GlobalSolarEclipseInfo
|
||||
|
||||
class [GlobalSolarEclipseInfo](index.md)(kind: [EclipseKind](../-eclipse-kind/index.md), peak: [Time](../-time/index.md), distance: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), longitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))
|
||||
class [GlobalSolarEclipseInfo](index.md)(kind: [EclipseKind](../-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), peak: [Time](../-time/index.md), distance: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), longitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))
|
||||
|
||||
Reports the time and geographic location of the peak of a solar eclipse.
|
||||
|
||||
@@ -14,11 +14,13 @@ The kind field thus holds EclipseKind.Partial, EclipseKind.Annular, or EclipseKi
|
||||
|
||||
If kind is EclipseKind.Total or EclipseKind.Annular, the latitude and longitude fields give the geographic coordinates of the center of the Moon's shadow projected onto the daytime side of the Earth at the instant of the eclipse's peak. If kind has any other value, latitude and longitude are undefined and should not be used.
|
||||
|
||||
For total or annular eclipses, the obscuration field holds the fraction (0, 1] of the Sun's apparent disc area that is blocked from view by the Moon's silhouette, as seen by an observer located at the geographic coordinates latitude, longitude at the darkest time peak. The value will always be 1 for total eclipses, and less than 1 for annular eclipses. For partial eclipses, obscuration is undefined and should not be used. This is because there is little practical use for an obscuration value of a partial eclipse without supplying a particular observation location. Developers who wish to find an obscuration value for partial solar eclipses should therefore use [searchLocalSolarEclipse](../search-local-solar-eclipse.md) and provide the geographic coordinates of an observer.
|
||||
|
||||
## Constructors
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| [GlobalSolarEclipseInfo](-global-solar-eclipse-info.md)<br>fun [GlobalSolarEclipseInfo](-global-solar-eclipse-info.md)(kind: [EclipseKind](../-eclipse-kind/index.md), peak: [Time](../-time/index.md), distance: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), longitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)) |
|
||||
| [GlobalSolarEclipseInfo](-global-solar-eclipse-info.md)<br>fun [GlobalSolarEclipseInfo](-global-solar-eclipse-info.md)(kind: [EclipseKind](../-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), peak: [Time](../-time/index.md), distance: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), longitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)) |
|
||||
|
||||
## Properties
|
||||
|
||||
@@ -28,4 +30,5 @@ If kind is EclipseKind.Total or EclipseKind.Annular, the latitude and longitude
|
||||
| [kind](kind.md)<br>val [kind](kind.md): [EclipseKind](../-eclipse-kind/index.md)<br>The type of solar eclipse: EclipseKind.Partial, EclipseKind.Annular, or EclipseKind.Total. |
|
||||
| [latitude](latitude.md)<br>val [latitude](latitude.md): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)<br>The geographic latitude at the center of the peak eclipse shadow. |
|
||||
| [longitude](longitude.md)<br>val [longitude](longitude.md): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)<br>The geographic longitude at the center of the peak eclipse shadow. |
|
||||
| [obscuration](obscuration.md)<br>val [obscuration](obscuration.md): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)<br>The peak fraction of the Sun's apparent disc area obscured by the Moon (total and annular eclipses only). |
|
||||
| [peak](peak.md)<br>val [peak](peak.md): [Time](../-time/index.md)<br>The date and time when the solar eclipse is darkest. This is the instant when the axis of the Moon's shadow cone passes closest to the Earth's center. |
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
//[astronomy](../../../index.md)/[io.github.cosinekitty.astronomy](../index.md)/[GlobalSolarEclipseInfo](index.md)/[obscuration](obscuration.md)
|
||||
|
||||
# obscuration
|
||||
|
||||
val [obscuration](obscuration.md): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)
|
||||
|
||||
The peak fraction of the Sun's apparent disc area obscured by the Moon (total and annular eclipses only).
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
# LocalSolarEclipseInfo
|
||||
|
||||
fun [LocalSolarEclipseInfo](-local-solar-eclipse-info.md)(kind: [EclipseKind](../-eclipse-kind/index.md), partialBegin: [EclipseEvent](../-eclipse-event/index.md), totalBegin: [EclipseEvent](../-eclipse-event/index.md)?, peak: [EclipseEvent](../-eclipse-event/index.md), totalEnd: [EclipseEvent](../-eclipse-event/index.md)?, partialEnd: [EclipseEvent](../-eclipse-event/index.md))
|
||||
fun [LocalSolarEclipseInfo](-local-solar-eclipse-info.md)(kind: [EclipseKind](../-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), partialBegin: [EclipseEvent](../-eclipse-event/index.md), totalBegin: [EclipseEvent](../-eclipse-event/index.md)?, peak: [EclipseEvent](../-eclipse-event/index.md), totalEnd: [EclipseEvent](../-eclipse-event/index.md)?, partialEnd: [EclipseEvent](../-eclipse-event/index.md))
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# LocalSolarEclipseInfo
|
||||
|
||||
class [LocalSolarEclipseInfo](index.md)(kind: [EclipseKind](../-eclipse-kind/index.md), partialBegin: [EclipseEvent](../-eclipse-event/index.md), totalBegin: [EclipseEvent](../-eclipse-event/index.md)?, peak: [EclipseEvent](../-eclipse-event/index.md), totalEnd: [EclipseEvent](../-eclipse-event/index.md)?, partialEnd: [EclipseEvent](../-eclipse-event/index.md))
|
||||
class [LocalSolarEclipseInfo](index.md)(kind: [EclipseKind](../-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), partialBegin: [EclipseEvent](../-eclipse-event/index.md), totalBegin: [EclipseEvent](../-eclipse-event/index.md)?, peak: [EclipseEvent](../-eclipse-event/index.md), totalEnd: [EclipseEvent](../-eclipse-event/index.md)?, partialEnd: [EclipseEvent](../-eclipse-event/index.md))
|
||||
|
||||
Information about a solar eclipse as seen by an observer at a given time and geographic location.
|
||||
|
||||
@@ -10,19 +10,22 @@ Returned by [searchLocalSolarEclipse](../search-local-solar-eclipse.md) or [next
|
||||
|
||||
When a solar eclipse is found, it is classified as partial, annular, or total. The kind field thus holds EclipseKind.Partial, EclipseKind.Annular, or EclipseKind.Total. A partial solar eclipse is when the Moon does not line up directly enough with the Sun to completely block the Sun's light from reaching the observer. An annular eclipse occurs when the Moon's disc is completely visible against the Sun but the Moon is too far away to completely block the Sun's light; this leaves the Sun with a ring-like appearance. A total eclipse occurs when the Moon is close enough to the Earth and aligned with the Sun just right to completely block all sunlight from reaching the observer.
|
||||
|
||||
The obscuration field reports what fraction of the Sun's disc appears blocked by the Moon when viewed by the observer at the peak eclipse time. This is a value that ranges from 0 (no blockage) to 1 (total eclipse). The obscuration value will be between 0 and 1 for partial eclipses and annular eclipses. The value will be exactly 1 for total eclipses. Obscuration gives an indication of how dark the eclipse appears.
|
||||
|
||||
There are 5 "event" fields, each of which contains a time and a solar altitude. Field peak holds the date and time of the center of the eclipse, when it is at its peak. The fields partialBegin and partialEnd are always set, and indicate when the eclipse begins/ends. If the eclipse reaches totality or becomes annular, totalBegin and totalEnd indicate when the total/annular phase begins/ends. When an event field is valid, the caller must also check its altitude field to see whether the Sun is above the horizon at the time indicated by the time field. </remarks>
|
||||
|
||||
## Constructors
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| [LocalSolarEclipseInfo](-local-solar-eclipse-info.md)<br>fun [LocalSolarEclipseInfo](-local-solar-eclipse-info.md)(kind: [EclipseKind](../-eclipse-kind/index.md), partialBegin: [EclipseEvent](../-eclipse-event/index.md), totalBegin: [EclipseEvent](../-eclipse-event/index.md)?, peak: [EclipseEvent](../-eclipse-event/index.md), totalEnd: [EclipseEvent](../-eclipse-event/index.md)?, partialEnd: [EclipseEvent](../-eclipse-event/index.md)) |
|
||||
| [LocalSolarEclipseInfo](-local-solar-eclipse-info.md)<br>fun [LocalSolarEclipseInfo](-local-solar-eclipse-info.md)(kind: [EclipseKind](../-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), partialBegin: [EclipseEvent](../-eclipse-event/index.md), totalBegin: [EclipseEvent](../-eclipse-event/index.md)?, peak: [EclipseEvent](../-eclipse-event/index.md), totalEnd: [EclipseEvent](../-eclipse-event/index.md)?, partialEnd: [EclipseEvent](../-eclipse-event/index.md)) |
|
||||
|
||||
## Properties
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [kind](kind.md)<br>val [kind](kind.md): [EclipseKind](../-eclipse-kind/index.md)<br>The type of solar eclipse: EclipseKind.Partial, EclipseKind.Annular, or EclipseKind.Total. |
|
||||
| [obscuration](obscuration.md)<br>val [obscuration](obscuration.md): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)<br>The fraction of the Sun's apparent disc area obscured by the Moon at the eclipse peak. |
|
||||
| [partialBegin](partial-begin.md)<br>val [partialBegin](partial-begin.md): [EclipseEvent](../-eclipse-event/index.md)<br>The time and Sun altitude at the beginning of the eclipse. |
|
||||
| [partialEnd](partial-end.md)<br>val [partialEnd](partial-end.md): [EclipseEvent](../-eclipse-event/index.md)<br>The time and Sun altitude at the end of the eclipse. |
|
||||
| [peak](peak.md)<br>val [peak](peak.md): [EclipseEvent](../-eclipse-event/index.md)<br>The time and Sun altitude when the eclipse reaches its peak. |
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
//[astronomy](../../../index.md)/[io.github.cosinekitty.astronomy](../index.md)/[LocalSolarEclipseInfo](index.md)/[obscuration](obscuration.md)
|
||||
|
||||
# obscuration
|
||||
|
||||
val [obscuration](obscuration.md): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)
|
||||
|
||||
The fraction of the Sun's apparent disc area obscured by the Moon at the eclipse peak.
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
# LunarEclipseInfo
|
||||
|
||||
fun [LunarEclipseInfo](-lunar-eclipse-info.md)(kind: [EclipseKind](../-eclipse-kind/index.md), peak: [Time](../-time/index.md), sdPenum: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdPartial: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdTotal: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))
|
||||
fun [LunarEclipseInfo](-lunar-eclipse-info.md)(kind: [EclipseKind](../-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), peak: [Time](../-time/index.md), sdPenum: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdPartial: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdTotal: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# LunarEclipseInfo
|
||||
|
||||
class [LunarEclipseInfo](index.md)(kind: [EclipseKind](../-eclipse-kind/index.md), peak: [Time](../-time/index.md), sdPenum: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdPartial: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdTotal: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))
|
||||
class [LunarEclipseInfo](index.md)(kind: [EclipseKind](../-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), peak: [Time](../-time/index.md), sdPenum: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdPartial: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdTotal: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))
|
||||
|
||||
Information about a lunar eclipse.
|
||||
|
||||
@@ -10,6 +10,8 @@ Returned by [searchLunarEclipse](../search-lunar-eclipse.md) or [nextLunarEclips
|
||||
|
||||
The kind field thus holds EclipseKind.Penumbral, EclipseKind.Partial, or EclipseKind.Total, depending on the kind of lunar eclipse found.
|
||||
|
||||
The obscuration field holds a value in the range 0, 1 that indicates what fraction of the Moon's apparent disc area is covered by the Earth's umbra at the eclipse's peak. This indicates how dark the peak eclipse appears. For penumbral eclipses, the obscuration is 0, because the Moon does not pass through the Earth's umbra. For partial eclipses, the obscuration is somewhere between 0 and 1. For total lunar eclipses, the obscuration is 1.
|
||||
|
||||
Field peak holds the date and time of the center of the eclipse, when it is at its peak.
|
||||
|
||||
Fields sdPenum, sdPartial, and sdTotal hold the semi-duration of each phase of the eclipse, which is half of the amount of time the eclipse spends in each phase (expressed in minutes), or 0.0 if the eclipse never reaches that phase. By converting from minutes to days, and subtracting/adding with peak, the caller may determine the date and time of the beginning/end of each eclipse phase.
|
||||
@@ -18,13 +20,14 @@ Fields sdPenum, sdPartial, and sdTotal hold the semi-duration of each phase of t
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| [LunarEclipseInfo](-lunar-eclipse-info.md)<br>fun [LunarEclipseInfo](-lunar-eclipse-info.md)(kind: [EclipseKind](../-eclipse-kind/index.md), peak: [Time](../-time/index.md), sdPenum: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdPartial: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdTotal: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)) |
|
||||
| [LunarEclipseInfo](-lunar-eclipse-info.md)<br>fun [LunarEclipseInfo](-lunar-eclipse-info.md)(kind: [EclipseKind](../-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), peak: [Time](../-time/index.md), sdPenum: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdPartial: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdTotal: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)) |
|
||||
|
||||
## Properties
|
||||
|
||||
| Name | Summary |
|
||||
|---|---|
|
||||
| [kind](kind.md)<br>val [kind](kind.md): [EclipseKind](../-eclipse-kind/index.md)<br>The type of lunar eclipse found. |
|
||||
| [obscuration](obscuration.md)<br>val [obscuration](obscuration.md): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)<br>The peak fraction of the Moon's apparent disc that is covered by the Earth's umbra. |
|
||||
| [peak](peak.md)<br>val [peak](peak.md): [Time](../-time/index.md)<br>The time of the eclipse at its peak. |
|
||||
| [sdPartial](sd-partial.md)<br>val [sdPartial](sd-partial.md): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)<br>The semi-duration of the partial phase in minutes, or 0.0 if none. |
|
||||
| [sdPenum](sd-penum.md)<br>val [sdPenum](sd-penum.md): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)<br>The semi-duration of the penumbral phase in minutes. |
|
||||
|
||||
7
source/kotlin/doc/-lunar-eclipse-info/obscuration.md
Normal file
7
source/kotlin/doc/-lunar-eclipse-info/obscuration.md
Normal file
@@ -0,0 +1,7 @@
|
||||
//[astronomy](../../../index.md)/[io.github.cosinekitty.astronomy](../index.md)/[LunarEclipseInfo](index.md)/[obscuration](obscuration.md)
|
||||
|
||||
# obscuration
|
||||
|
||||
val [obscuration](obscuration.md): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)
|
||||
|
||||
The peak fraction of the Moon's apparent disc that is covered by the Earth's umbra.
|
||||
@@ -21,7 +21,7 @@
|
||||
| [ElongationInfo](-elongation-info/index.md)<br>class [ElongationInfo](-elongation-info/index.md)(time: [Time](-time/index.md), visibility: [Visibility](-visibility/index.md), elongation: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), eclipticSeparation: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Contains information about the visibility of a celestial body at a given date and time. |
|
||||
| [EquatorEpoch](-equator-epoch/index.md)<br>enum [EquatorEpoch](-equator-epoch/index.md) : [Enum](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-enum/index.html)<[EquatorEpoch](-equator-epoch/index.md)> <br>Selects the date for which the Earth's equator is to be used for representing equatorial coordinates. |
|
||||
| [Equatorial](-equatorial/index.md)<br>class [Equatorial](-equatorial/index.md)(ra: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), dec: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), dist: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), vec: [Vector](-vector/index.md))<br>Equatorial angular and cartesian coordinates. |
|
||||
| [GlobalSolarEclipseInfo](-global-solar-eclipse-info/index.md)<br>class [GlobalSolarEclipseInfo](-global-solar-eclipse-info/index.md)(kind: [EclipseKind](-eclipse-kind/index.md), peak: [Time](-time/index.md), distance: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), longitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Reports the time and geographic location of the peak of a solar eclipse. |
|
||||
| [GlobalSolarEclipseInfo](-global-solar-eclipse-info/index.md)<br>class [GlobalSolarEclipseInfo](-global-solar-eclipse-info/index.md)(kind: [EclipseKind](-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), peak: [Time](-time/index.md), distance: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), longitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Reports the time and geographic location of the peak of a solar eclipse. |
|
||||
| [GravitySimulator](-gravity-simulator/index.md)<br>class [GravitySimulator](-gravity-simulator/index.md)<br>A simulation of zero or more small bodies moving through the Solar System. |
|
||||
| [HourAngleInfo](-hour-angle-info/index.md)<br>class [HourAngleInfo](-hour-angle-info/index.md)(time: [Time](-time/index.md), hor: [Topocentric](-topocentric/index.md))<br>Information about a celestial body crossing a specific hour angle. |
|
||||
| [IlluminationInfo](-illumination-info/index.md)<br>class [IlluminationInfo](-illumination-info/index.md)(time: [Time](-time/index.md), mag: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), phaseAngle: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), phaseFraction: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), helioDist: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), ringTilt: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Information about the brightness and illuminated shape of a celestial body. |
|
||||
@@ -29,8 +29,8 @@
|
||||
| [InvalidBodyException](-invalid-body-exception/index.md)<br>class [InvalidBodyException](-invalid-body-exception/index.md)(body: [Body](-body/index.md)) : [Exception](https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html)<br>An invalid body was specified for the given function. |
|
||||
| [JupiterMoonsInfo](-jupiter-moons-info/index.md)<br>class [JupiterMoonsInfo](-jupiter-moons-info/index.md)(io: [StateVector](-state-vector/index.md), europa: [StateVector](-state-vector/index.md), ganymede: [StateVector](-state-vector/index.md), callisto: [StateVector](-state-vector/index.md))<br>Holds the positions and velocities of Jupiter's major 4 moons. |
|
||||
| [LibrationInfo](-libration-info/index.md)<br>data class [LibrationInfo](-libration-info/index.md)(elat: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), elon: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), mlat: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), mlon: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), distanceKm: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), diamDeg: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Lunar libration angles, returned by [libration](libration.md). |
|
||||
| [LocalSolarEclipseInfo](-local-solar-eclipse-info/index.md)<br>class [LocalSolarEclipseInfo](-local-solar-eclipse-info/index.md)(kind: [EclipseKind](-eclipse-kind/index.md), partialBegin: [EclipseEvent](-eclipse-event/index.md), totalBegin: [EclipseEvent](-eclipse-event/index.md)?, peak: [EclipseEvent](-eclipse-event/index.md), totalEnd: [EclipseEvent](-eclipse-event/index.md)?, partialEnd: [EclipseEvent](-eclipse-event/index.md))<br>Information about a solar eclipse as seen by an observer at a given time and geographic location. |
|
||||
| [LunarEclipseInfo](-lunar-eclipse-info/index.md)<br>class [LunarEclipseInfo](-lunar-eclipse-info/index.md)(kind: [EclipseKind](-eclipse-kind/index.md), peak: [Time](-time/index.md), sdPenum: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdPartial: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdTotal: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Information about a lunar eclipse. |
|
||||
| [LocalSolarEclipseInfo](-local-solar-eclipse-info/index.md)<br>class [LocalSolarEclipseInfo](-local-solar-eclipse-info/index.md)(kind: [EclipseKind](-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), partialBegin: [EclipseEvent](-eclipse-event/index.md), totalBegin: [EclipseEvent](-eclipse-event/index.md)?, peak: [EclipseEvent](-eclipse-event/index.md), totalEnd: [EclipseEvent](-eclipse-event/index.md)?, partialEnd: [EclipseEvent](-eclipse-event/index.md))<br>Information about a solar eclipse as seen by an observer at a given time and geographic location. |
|
||||
| [LunarEclipseInfo](-lunar-eclipse-info/index.md)<br>class [LunarEclipseInfo](-lunar-eclipse-info/index.md)(kind: [EclipseKind](-eclipse-kind/index.md), obscuration: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), peak: [Time](-time/index.md), sdPenum: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdPartial: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), sdTotal: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))<br>Information about a lunar eclipse. |
|
||||
| [MoonQuarterInfo](-moon-quarter-info/index.md)<br>class [MoonQuarterInfo](-moon-quarter-info/index.md)(quarter: [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html), time: [Time](-time/index.md))<br>A lunar quarter event (new moon, first quarter, full moon, or third quarter) along with its date and time. |
|
||||
| [NodeEventInfo](-node-event-info/index.md)<br>class [NodeEventInfo](-node-event-info/index.md)(time: [Time](-time/index.md), kind: [NodeEventKind](-node-event-kind/index.md))<br>Information about an ascending or descending node of a body. |
|
||||
| [NodeEventKind](-node-event-kind/index.md)<br>enum [NodeEventKind](-node-event-kind/index.md) : [Enum](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-enum/index.html)<[NodeEventKind](-node-event-kind/index.md)> <br>Indicates whether a crossing through the ecliptic plane is ascending or descending. |
|
||||
|
||||
@@ -179,9 +179,10 @@ private const val EARTH_MEAN_RADIUS_KM = 6371.0 // mean radius of the Earth's
|
||||
private const val EARTH_ATMOSPHERE_KM = 88.0 // effective atmosphere thickness for lunar eclipses
|
||||
private const val EARTH_ECLIPSE_RADIUS_KM = EARTH_MEAN_RADIUS_KM + EARTH_ATMOSPHERE_KM
|
||||
private const val MOON_EQUATORIAL_RADIUS_KM = 1738.1
|
||||
private const val MOON_EQUATORIAL_RADIUS_AU = (MOON_EQUATORIAL_RADIUS_KM / KM_PER_AU)
|
||||
private const val MOON_MEAN_RADIUS_KM = 1737.4
|
||||
private const val MOON_POLAR_RADIUS_KM = 1736.0
|
||||
private const val MOON_EQUATORIAL_RADIUS_AU = (MOON_EQUATORIAL_RADIUS_KM / KM_PER_AU)
|
||||
private const val MOON_POLAR_RADIUS_AU = (MOON_POLAR_RADIUS_KM / KM_PER_AU)
|
||||
private const val ANGVEL = 7.2921150e-5
|
||||
private const val SOLAR_DAYS_PER_SIDEREAL_DAY = 0.9972695717592592
|
||||
private const val MEAN_SYNODIC_MONTH = 29.530588 // average number of days for Moon to return to the same phase
|
||||
@@ -1790,6 +1791,12 @@ enum class EclipseKind {
|
||||
* The `kind` field thus holds `EclipseKind.Penumbral`, `EclipseKind.Partial`,
|
||||
* or `EclipseKind.Total`, depending on the kind of lunar eclipse found.
|
||||
*
|
||||
* The `obscuration` field holds a value in the range [0, 1] that indicates what fraction
|
||||
* of the Moon's apparent disc area is covered by the Earth's umbra at the eclipse's peak.
|
||||
* This indicates how dark the peak eclipse appears. For penumbral eclipses, the obscuration
|
||||
* is 0, because the Moon does not pass through the Earth's umbra. For partial eclipses,
|
||||
* the obscuration is somewhere between 0 and 1. For total lunar eclipses, the obscuration is 1.
|
||||
*
|
||||
* Field `peak` holds the date and time of the center of the eclipse, when it is at its peak.
|
||||
*
|
||||
* Fields `sdPenum`, `sdPartial`, and `sdTotal` hold the semi-duration of each phase
|
||||
@@ -1804,6 +1811,11 @@ class LunarEclipseInfo(
|
||||
*/
|
||||
val kind: EclipseKind,
|
||||
|
||||
/**
|
||||
* The peak fraction of the Moon's apparent disc that is covered by the Earth's umbra.
|
||||
*/
|
||||
val obscuration: Double,
|
||||
|
||||
/**
|
||||
* The time of the eclipse at its peak.
|
||||
*/
|
||||
@@ -1848,6 +1860,17 @@ class LunarEclipseInfo(
|
||||
* onto the daytime side of the Earth at the instant of the eclipse's peak.
|
||||
* If `kind` has any other value, `latitude` and `longitude` are undefined and should
|
||||
* not be used.
|
||||
*
|
||||
* For total or annular eclipses, the `obscuration` field holds the fraction (0, 1]
|
||||
* of the Sun's apparent disc area that is blocked from view by the Moon's silhouette,
|
||||
* as seen by an observer located at the geographic coordinates `latitude`, `longitude`
|
||||
* at the darkest time `peak`. The value will always be 1 for total eclipses, and less than
|
||||
* 1 for annular eclipses.
|
||||
* For partial eclipses, `obscuration` is undefined and should not be used.
|
||||
* This is because there is little practical use for an obscuration value of
|
||||
* a partial eclipse without supplying a particular observation location.
|
||||
* Developers who wish to find an obscuration value for partial solar eclipses should therefore use
|
||||
* [searchLocalSolarEclipse] and provide the geographic coordinates of an observer.
|
||||
*/
|
||||
class GlobalSolarEclipseInfo(
|
||||
/**
|
||||
@@ -1855,6 +1878,11 @@ class GlobalSolarEclipseInfo(
|
||||
*/
|
||||
val kind: EclipseKind,
|
||||
|
||||
/**
|
||||
* The peak fraction of the Sun's apparent disc area obscured by the Moon (total and annular eclipses only).
|
||||
*/
|
||||
val obscuration: Double,
|
||||
|
||||
/**
|
||||
* The date and time when the solar eclipse is darkest.
|
||||
* This is the instant when the axis of the Moon's shadow cone passes closest to the Earth's center.
|
||||
@@ -1922,6 +1950,13 @@ class EclipseEvent (
|
||||
* A total eclipse occurs when the Moon is close enough to the Earth and aligned with the
|
||||
* Sun just right to completely block all sunlight from reaching the observer.
|
||||
*
|
||||
* The `obscuration` field reports what fraction of the Sun's disc appears blocked
|
||||
* by the Moon when viewed by the observer at the peak eclipse time.
|
||||
* This is a value that ranges from 0 (no blockage) to 1 (total eclipse).
|
||||
* The obscuration value will be between 0 and 1 for partial eclipses and annular eclipses.
|
||||
* The value will be exactly 1 for total eclipses. Obscuration gives an indication
|
||||
* of how dark the eclipse appears.
|
||||
*
|
||||
* There are 5 "event" fields, each of which contains a time and a solar altitude.
|
||||
* Field `peak` holds the date and time of the center of the eclipse, when it is at its peak.
|
||||
* The fields `partialBegin` and `partialEnd` are always set, and indicate when
|
||||
@@ -1937,6 +1972,11 @@ class LocalSolarEclipseInfo (
|
||||
*/
|
||||
val kind: EclipseKind,
|
||||
|
||||
/**
|
||||
* The fraction of the Sun's apparent disc area obscured by the Moon at the eclipse peak.
|
||||
*/
|
||||
val obscuration: Double,
|
||||
|
||||
/**
|
||||
* The time and Sun altitude at the beginning of the eclipse.
|
||||
*/
|
||||
@@ -2054,44 +2094,42 @@ internal fun calcShadow(
|
||||
|
||||
internal fun earthShadow(time: Time): ShadowInfo {
|
||||
// This function helps find when the Earth's shadow falls upon the Moon.
|
||||
val e = helioEarthPos(time)
|
||||
val s = geoVector(Body.Sun, time, Aberration.Corrected)
|
||||
val m = geoMoon(time)
|
||||
return calcShadow(EARTH_ECLIPSE_RADIUS_KM, time, m, e)
|
||||
return calcShadow(EARTH_ECLIPSE_RADIUS_KM, time, m, -s)
|
||||
}
|
||||
|
||||
internal fun moonShadow(time: Time): ShadowInfo {
|
||||
// This function helps find when the Moon's shadow falls upon the Earth.
|
||||
// This is a variation on the logic in EarthShadow().
|
||||
// Instead of a heliocentric Earth and a geocentric Moon,
|
||||
// we want a heliocentric Moon and a lunacentric Earth.
|
||||
|
||||
val e = helioEarthPos(time)
|
||||
val s = geoVector(Body.Sun, time, Aberration.Corrected)
|
||||
val m = geoMoon(time)
|
||||
|
||||
// -m = lunacentric Earth
|
||||
// m+e = heliocentric Moon
|
||||
return calcShadow(MOON_MEAN_RADIUS_KM, time, -m, m+e)
|
||||
// m-s = heliocentric Moon
|
||||
return calcShadow(MOON_MEAN_RADIUS_KM, time, -m, m-s)
|
||||
}
|
||||
|
||||
internal fun localMoonShadow(time: Time, observer: Observer): ShadowInfo {
|
||||
// Calculate observer's geocentric position.
|
||||
// For efficiency, do this first, to populate the earth rotation parameters in 'time'.
|
||||
// That way they can be recycled instead of recalculated.
|
||||
val o = geoPos(time, observer)
|
||||
val h = helioEarthPos(time)
|
||||
|
||||
// Calculate light-travel and aberration corrected Sun.
|
||||
val s = geoVector(Body.Sun, time, Aberration.Corrected)
|
||||
|
||||
// Calculate geocentric Moon.
|
||||
val m = geoMoon(time)
|
||||
|
||||
// o-m = lunacentric observer
|
||||
// m+h = heliocentric Moon
|
||||
return calcShadow(MOON_MEAN_RADIUS_KM, time, o-m, m+h)
|
||||
// m-s = heliocentric Moon
|
||||
return calcShadow(MOON_MEAN_RADIUS_KM, time, o-m, m-s)
|
||||
}
|
||||
|
||||
internal fun planetShadow(body: Body, planetRadiusKm: Double, time: Time): ShadowInfo {
|
||||
// Calculate light-travel-corrected vector from Earth to planet.
|
||||
val g = geoVector(body, time, Aberration.None)
|
||||
val g = geoVector(body, time, Aberration.Corrected)
|
||||
|
||||
// Calculate light-travel-corrected vector from Earth to Sun.
|
||||
val e = geoVector(Body.Sun, time, Aberration.None)
|
||||
val e = geoVector(Body.Sun, time, Aberration.Corrected)
|
||||
|
||||
// -g = planetocentric Earth
|
||||
// g-e = heliocentric planet
|
||||
@@ -2137,7 +2175,6 @@ internal fun peakEarthShadow(searchCenterTime: Time): ShadowInfo {
|
||||
return earthShadow(tx)
|
||||
}
|
||||
|
||||
|
||||
internal val moonShadowSlopeContext = SearchContext { time ->
|
||||
val dt = 1.0 / SECONDS_PER_DAY
|
||||
val t1 = time.addDays(-dt)
|
||||
@@ -2196,6 +2233,69 @@ internal fun planetTransitBoundary(body: Body, planetRadiusKm: Double, t1: Time,
|
||||
} ?: throw InternalError("Planet transit boundary search failed.")
|
||||
}
|
||||
|
||||
internal fun discObscuration(a: Double, b: Double, c: Double): Double {
|
||||
// a = radius of first disc
|
||||
// b = radius of second disc
|
||||
// c = distance between centers of discs
|
||||
if (a <= 0.0) throw InternalError("Radius of first disc must be positive.")
|
||||
if (b <= 0.0) throw InternalError("Radius of second disc must be positive.")
|
||||
if (c < 0.0) throw InternalError("Distance between discs is not allowed to be negative.")
|
||||
|
||||
if (c >= a + b) {
|
||||
// The discs are too far apart to have any overlapping area.
|
||||
return 0.0
|
||||
}
|
||||
|
||||
if (c == 0.0) {
|
||||
// The discs have a common center. Therefore, one disc is inside the other.
|
||||
return if (a <= b) 1.0 else (b*b)/(a*a)
|
||||
}
|
||||
|
||||
val x = (a*a - b*b + c*c) / (2*c)
|
||||
val radicand = a*a - x*x
|
||||
if (radicand <= 0.0) {
|
||||
// The circumferences do not intersect, or are tangent.
|
||||
// We already ruled out the case of non-overlapping discs.
|
||||
// Therefore, one disc is inside the other.
|
||||
return if (a <= b) 1.0 else (b*b)/(a*a)
|
||||
}
|
||||
|
||||
// The discs overlap fractionally in a pair of lens-shaped areas.
|
||||
|
||||
val y = sqrt(radicand)
|
||||
|
||||
// Return the overlapping fractional area.
|
||||
// There are two lens-shaped areas, one to the left of x, the other to the right of x.
|
||||
// Each part is calculated by subtracting a triangular area from a sector's area.
|
||||
val lens1 = a*a*acos(x/a) - x*y
|
||||
val lens2 = b*b*acos((c-x)/b) - (c-x)*y
|
||||
|
||||
// Find the fractional area with respect to the first disc.
|
||||
return (lens1 + lens2) / (PI*a*a)
|
||||
}
|
||||
|
||||
|
||||
internal fun solarEclipseObscuration(hm: Vector, lo: Vector): Double {
|
||||
// Find heliocentric observer.
|
||||
val ho = hm + lo
|
||||
|
||||
// Calculate the apparent angular radius of the Sun for the observer.
|
||||
val sunRadius = asin(SUN_RADIUS_AU / ho.length())
|
||||
|
||||
// Calculate the apparent angular radius of the Moon for the observer.
|
||||
val moonRadius = asin(MOON_POLAR_RADIUS_AU / lo.length())
|
||||
|
||||
// Calculate the apparent angular separation between the Sun's center and the Moon's center.
|
||||
val sunMoonSeparation = lo.angleWith(ho).degreesToRadians()
|
||||
|
||||
// Find the fraction of the Sun's apparent disc area that is covered by the Moon.
|
||||
val obscuration = discObscuration(sunRadius, moonRadius, sunMoonSeparation)
|
||||
|
||||
// HACK: In marginal cases, we need to clamp obscuration to less than 1.0.
|
||||
// This function is never called for total eclipses, so it should never return 1.0.
|
||||
return min(0.9999, obscuration)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Searches for a lunar eclipse.
|
||||
@@ -2234,6 +2334,7 @@ fun searchLunarEclipse(startTime: Time): LunarEclipseInfo {
|
||||
if (shadow.r < shadow.p + MOON_MEAN_RADIUS_KM) {
|
||||
// This is at least a penumbral eclipse. We will return a result.
|
||||
var kind = EclipseKind.Penumbral
|
||||
var obscuration = 0.0
|
||||
val sdPenum = shadowSemiDurationMinutes(shadow.time, shadow.p + MOON_MEAN_RADIUS_KM, 200.0)
|
||||
var sdPartial = 0.0
|
||||
var sdTotal = 0.0
|
||||
@@ -2246,11 +2347,14 @@ fun searchLunarEclipse(startTime: Time): LunarEclipseInfo {
|
||||
if (shadow.r + MOON_MEAN_RADIUS_KM < shadow.k) {
|
||||
// This is a total eclipse.
|
||||
kind = EclipseKind.Total
|
||||
obscuration = 1.0
|
||||
sdTotal = shadowSemiDurationMinutes(shadow.time, shadow.k - MOON_MEAN_RADIUS_KM, sdPartial)
|
||||
} else {
|
||||
obscuration = discObscuration(MOON_MEAN_RADIUS_KM, shadow.k, shadow.r)
|
||||
}
|
||||
}
|
||||
|
||||
return LunarEclipseInfo(kind, shadow.time, sdPenum, sdPartial, sdTotal)
|
||||
return LunarEclipseInfo(kind, obscuration, shadow.time, sdPenum, sdPartial, sdTotal)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2324,6 +2428,7 @@ internal fun eclipseKindFromUmbra(k: Double) = (
|
||||
|
||||
internal fun geoidIntersect(shadow: ShadowInfo): GlobalSolarEclipseInfo {
|
||||
var kind = EclipseKind.Partial
|
||||
var obscuration = Double.NaN
|
||||
var latitude = Double.NaN
|
||||
var longitude = Double.NaN
|
||||
|
||||
@@ -2385,9 +2490,10 @@ internal fun geoidIntersect(shadow: ShadowInfo): GlobalSolarEclipseInfo {
|
||||
throw InternalError("Invalid surface distance from intersection.")
|
||||
|
||||
kind = eclipseKindFromUmbra(surface.k)
|
||||
obscuration = if (kind == EclipseKind.Total) 1.0 else solarEclipseObscuration(shadow.dir, luna)
|
||||
}
|
||||
|
||||
return GlobalSolarEclipseInfo(kind, shadow.time, shadow.r, latitude, longitude)
|
||||
return GlobalSolarEclipseInfo(kind, obscuration, shadow.time, shadow.r, latitude, longitude)
|
||||
}
|
||||
|
||||
|
||||
@@ -2549,7 +2655,8 @@ internal fun localEclipse(shadow: ShadowInfo, observer: Observer): LocalSolarEcl
|
||||
} else {
|
||||
kind = EclipseKind.Partial
|
||||
}
|
||||
return LocalSolarEclipseInfo(kind, partialBegin, totalBegin, peak, totalEnd, partialEnd)
|
||||
val obscuration = if (kind == EclipseKind.Total) 1.0 else solarEclipseObscuration(shadow.dir, shadow.target)
|
||||
return LocalSolarEclipseInfo(kind, obscuration, partialBegin, totalBegin, peak, totalEnd, partialEnd)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1364,19 +1364,34 @@ class Tests {
|
||||
var eclipse: LunarEclipseInfo = searchLunarEclipse(Time(1701, 1, 1, 0, 0, 0.0))
|
||||
for (line in infile.readLines()) {
|
||||
++lnum
|
||||
|
||||
assertTrue(eclipse.obscuration.isFinite())
|
||||
assertTrue(eclipse.sdPartial.isFinite())
|
||||
assertTrue(eclipse.sdPenum.isFinite())
|
||||
assertTrue(eclipse.sdTotal.isFinite())
|
||||
|
||||
val tokens = tokenize(line, 3, filename, lnum)
|
||||
val peakTime = parseDate(tokens[0])
|
||||
val partialMinutes = tokens[1].toDouble()
|
||||
val totalMinutes = tokens[2].toDouble()
|
||||
|
||||
// Verify that the calculated semi-durations are consistent with the kind of eclipse.
|
||||
val valid: Boolean = when (eclipse.kind) {
|
||||
val sd_valid: Boolean = when (eclipse.kind) {
|
||||
EclipseKind.Penumbral -> (eclipse.sdPenum > 0.0) && (eclipse.sdPartial == 0.0) && (eclipse.sdTotal == 0.0)
|
||||
EclipseKind.Partial -> (eclipse.sdPenum > 0.0) && (eclipse.sdPartial > 0.0) && (eclipse.sdTotal == 0.0)
|
||||
EclipseKind.Total -> (eclipse.sdPenum > 0.0) && (eclipse.sdPartial > 0.0) && (eclipse.sdTotal > 0.0)
|
||||
else -> fail("Invalid lunar eclipse kind: ${eclipse.kind}")
|
||||
}
|
||||
assertTrue(valid, "$filename line $lnum: invalid semiduration(s) for kind ${eclipse.kind}")
|
||||
assertTrue(sd_valid, "$filename line $lnum: invalid semiduration(s) for kind ${eclipse.kind}")
|
||||
|
||||
// Verify that obscurations make sense for the eclipse kind.
|
||||
val frac_valid: Boolean = when (eclipse.kind) {
|
||||
EclipseKind.Penumbral -> (eclipse.obscuration == 0.0)
|
||||
EclipseKind.Partial -> (eclipse.obscuration > 0.0) && (eclipse.obscuration < 1.0)
|
||||
EclipseKind.Total -> (eclipse.obscuration == 1.0)
|
||||
else -> fail("Invalid lunar eclipse kind: ${eclipse.kind}")
|
||||
}
|
||||
assertTrue(frac_valid, "$filename line $lnum: invalid obscuration ${eclipse.obscuration} for kind ${eclipse.kind}")
|
||||
|
||||
// Check eclipse peak time
|
||||
val peakDiffDays = eclipse.peak.ut - peakTime.ut
|
||||
@@ -1436,7 +1451,7 @@ class Tests {
|
||||
|
||||
// Validate the eclipse prediction.
|
||||
val diffMinutes = MINUTES_PER_DAY * abs(diffDays)
|
||||
assertTrue(diffMinutes < 6.93, "$filename line $lnum: excessive time error = $diffMinutes minutes; expected $peak, found ${eclipse.peak}")
|
||||
assertTrue(diffMinutes < 7.56, "$filename line $lnum: excessive time error = $diffMinutes minutes; expected $peak, found ${eclipse.peak}")
|
||||
|
||||
// Validate the eclipse kind, but only when it is not a "glancing" eclipse.
|
||||
if (eclipse.distance < 6360.0)
|
||||
@@ -1452,6 +1467,13 @@ class Tests {
|
||||
}
|
||||
}
|
||||
|
||||
when (eclipse.kind) {
|
||||
EclipseKind.Partial -> assertTrue(eclipse.obscuration.isNaN(), "$filename line $lnum: expected NAN obscuration.")
|
||||
EclipseKind.Annular -> assertTrue(eclipse.obscuration > 0.8 && eclipse.obscuration < 1.0, "$filename line $lnum: invalid obscuration ${eclipse.obscuration} for annular eclipse.")
|
||||
EclipseKind.Total -> assertTrue(eclipse.obscuration == 1.0, "$filename line $lnum: invalid obscuration ${eclipse.obscuration} for total eclipse.")
|
||||
else -> fail("$filename line $lnum: invalid eclipse kind ${eclipse.kind}")
|
||||
}
|
||||
|
||||
eclipse = nextGlobalSolarEclipse(eclipse.peak)
|
||||
}
|
||||
|
||||
@@ -1501,8 +1523,20 @@ class Tests {
|
||||
continue
|
||||
}
|
||||
|
||||
when (eclipse.kind) {
|
||||
EclipseKind.Annular,
|
||||
EclipseKind.Partial ->
|
||||
assertTrue(eclipse.obscuration > 0.0 && eclipse.obscuration < 1.0, "$filename line $lnum: Invalid obscuration ${eclipse.obscuration} for ${eclipse.kind} eclipse.")
|
||||
|
||||
EclipseKind.Total ->
|
||||
assertTrue(eclipse.obscuration == 1.0, "$filename line $lnum: Invalid obscuration ${eclipse.obscuration} for {eclipse.kind} eclipse.")
|
||||
|
||||
else ->
|
||||
fail("$filename line $lnum: Invalid eclipse kind ${eclipse.kind}")
|
||||
}
|
||||
|
||||
val diffMinutes = MINUTES_PER_DAY * abs(diffDays)
|
||||
assertTrue(diffMinutes < 7.14, "$filename line $lnum: excessive time error = $diffMinutes minutes")
|
||||
assertTrue(diffMinutes < 7.734, "$filename line $lnum: excessive time error = $diffMinutes minutes")
|
||||
}
|
||||
|
||||
assertTrue(skipCount <= 6, "$filename: excessive skip count = $skipCount")
|
||||
@@ -1573,8 +1607,82 @@ class Tests {
|
||||
assertTrue(evt != null, "$filename line $lnum: eclipse $name was not supposed to be null.")
|
||||
val diffMinutes = MINUTES_PER_DAY * abs(expectedTime.ut - evt.time.ut)
|
||||
assertTrue(diffMinutes < 1.0, "$filename line $lnum: excessive time error for $name: $diffMinutes minutes.")
|
||||
val diffAlt = abs(expectedAltitude - evt.altitude)
|
||||
assertTrue(diffAlt < 0.5, "$filename line $lnum: excessive altitude error for $name: $diffAlt degrees.")
|
||||
// Ignore discrepancies for negative altitudes, because of quirky and irrelevant differences in refraction models.
|
||||
if (expectedAltitude >= 0.0) {
|
||||
val diffAlt = abs(expectedAltitude - evt.altitude)
|
||||
assertTrue(diffAlt < 0.5, "$filename line $lnum: excessive altitude error for $name: $diffAlt degrees.")
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
private fun globalAnnularCase(year: Int, month: Int, day: Int, obscuration: Double) {
|
||||
// Search for the first solar eclipse that occurs after the given date.
|
||||
val time = Time(year, month, day, 0, 0, 0.0)
|
||||
val eclipse = searchGlobalSolarEclipse(time)
|
||||
|
||||
// Verify the eclipse is within 1 day after the search basis time.
|
||||
val dt = eclipse.peak.ut - time.ut
|
||||
assertTrue(dt >= 0.0 && dt <= 1.0, "$time: found eclipse $dt days after search time.")
|
||||
|
||||
// Verify we found an annular solar eclipse.
|
||||
assertTrue(eclipse.kind == EclipseKind.Annular, "$time: expected annular eclipse but found ${eclipse.kind}")
|
||||
|
||||
// Check how accurately we calculated obscuration.
|
||||
val diff = eclipse.obscuration - obscuration
|
||||
assertTrue(abs(diff) < 0.0000904, "$time: excessive obscuration error $diff")
|
||||
}
|
||||
|
||||
private fun localSolarCase(
|
||||
year: Int,
|
||||
month: Int,
|
||||
day: Int,
|
||||
latitude: Double,
|
||||
longitude: Double,
|
||||
kind: EclipseKind,
|
||||
obscuration: Double,
|
||||
tolerance: Double
|
||||
) {
|
||||
val time = Time(year, month, day, 0, 0, 0.0)
|
||||
val observer = Observer(latitude, longitude, 0.0)
|
||||
val eclipse = searchLocalSolarEclipse(time, observer)
|
||||
val dt = eclipse.peak.time.ut - time.ut
|
||||
assertTrue(dt >= 0.0 && dt <= 1.0, "$time: found eclipse $dt days after search time.")
|
||||
assertTrue(eclipse.kind == kind, "$time: expected $kind eclipse, but found ${eclipse.kind}")
|
||||
val diff = eclipse.obscuration - obscuration
|
||||
assertTrue(abs(diff) <= tolerance, "$time: excessive obscuration error $diff")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Solar eclipse obscuration`() {
|
||||
// Verify global solar eclipse obscurations for annular eclipses only.
|
||||
// This is because they are the only nontrivial values for global solar eclipses.
|
||||
// The trivial values are all validated exactly by GlobalSolarEclipseTest().
|
||||
globalAnnularCase(2023, 10, 14, 0.90638) // https://www.eclipsewise.com/solar/SEprime/2001-2100/SE2023Oct14Aprime.html
|
||||
globalAnnularCase(2024, 10, 2, 0.86975) // https://www.eclipsewise.com/solar/SEprime/2001-2100/SE2024Oct02Aprime.html
|
||||
globalAnnularCase(2027, 2, 6, 0.86139) // https://www.eclipsewise.com/solar/SEprime/2001-2100/SE2027Feb06Aprime.html
|
||||
globalAnnularCase(2028, 1, 26, 0.84787) // https://www.eclipsewise.com/solar/SEprime/2001-2100/SE2028Jan26Aprime.html
|
||||
globalAnnularCase(2030, 6, 1, 0.89163) // https://www.eclipsewise.com/solar/SEprime/2001-2100/SE2030Jun01Aprime.html
|
||||
|
||||
// Verify obscuration values for specific locations on the Earth.
|
||||
// Local solar eclipse calculations include obscuration for all types of eclipse, not just annular and total.
|
||||
localSolarCase(2023, 10, 14, 11.3683, -83.1017, EclipseKind.Annular, 0.90638, 0.000080) // https://www.eclipsewise.com/solar/SEprime/2001-2100/SE2023Oct14Aprime.html
|
||||
localSolarCase(2023, 10, 14, 25.78, -80.22, EclipseKind.Partial, 0.578, 0.000023) // https://aa.usno.navy.mil/calculated/eclipse/solar?eclipse=22023&lat=25.78&lon=-80.22&label=Miami%2C+FL&height=0&submit=Get+Data
|
||||
localSolarCase(2023, 10, 14, 30.2666, -97.7000, EclipseKind.Partial, 0.8867, 0.001016) // http://astro.ukho.gov.uk/eclipse/0332023/Austin_TX_United_States_2023Oct14.png
|
||||
localSolarCase(2024, 4, 8, 25.2900, -104.1383, EclipseKind.Total, 1.0, 0.0 ) // https://www.eclipsewise.com/solar/SEprime/2001-2100/SE2024Apr08Tprime.html
|
||||
localSolarCase(2024, 4, 8, 37.76, -122.44, EclipseKind.Partial, 0.340, 0.000604) // https://aa.usno.navy.mil/calculated/eclipse/solar?eclipse=12024&lat=37.76&lon=-122.44&label=San+Francisco%2C+CA&height=0&submit=Get+Data
|
||||
localSolarCase(2024, 10, 2, -21.9533, -114.5083, EclipseKind.Annular, 0.86975, 0.000061) // https://www.eclipsewise.com/solar/SEprime/2001-2100/SE2024Oct02Aprime.html
|
||||
localSolarCase(2024, 10, 2, -33.468, -70.636, EclipseKind.Partial, 0.436, 0.000980) // https://aa.usno.navy.mil/calculated/eclipse/solar?eclipse=22024&lat=-33.468&lon=-70.636&label=Santiago%2C+Chile&height=0&submit=Get+Data
|
||||
localSolarCase(2030, 6, 1, 56.525, 80.0617, EclipseKind.Annular, 0.89163, 0.000067) // https://www.eclipsewise.com/solar/SEprime/2001-2100/SE2030Jun01Aprime.html
|
||||
localSolarCase(2030, 6, 1, 40.388, 49.914, EclipseKind.Partial, 0.67240, 0.000599) // http://xjubier.free.fr/en/site_pages/SolarEclipseCalc_Diagram.html
|
||||
localSolarCase(2030, 6, 1, 40.3667, 49.8333, EclipseKind.Partial, 0.6736, 0.001464) // http://astro.ukho.gov.uk/eclipse/0132030/Baku_Azerbaijan_2030Jun01.png
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
fun `Lunar eclipse obscuration`() {
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user