From 7895dc7ee6d9c78c1dac49704a7af6114a6527f9 Mon Sep 17 00:00:00 2001 From: Aric Camarata Date: Sat, 30 May 2026 18:39:39 -0400 Subject: [PATCH] chore: polish README for P1 E6 --- README.md | 130 +++++++++--------------------------------------------- 1 file changed, 20 insertions(+), 110 deletions(-) diff --git a/README.md b/README.md index 3a2ac08..3925b4e 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,11 @@ [![pub package](https://img.shields.io/pub/v/moon_sighting.svg)](https://pub.dev/packages/moon_sighting) [![CI](https://github.com/acamarata/moon-sighting-dart/actions/workflows/ci.yml/badge.svg)](https://github.com/acamarata/moon-sighting-dart/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) +[![Wiki](https://img.shields.io/badge/docs-wiki-blue)](https://github.com/acamarata/moon-sighting-dart/wiki) -Lunar crescent visibility for Dart and Flutter. Computes moon phase, topocentric position, illumination, and Yallop/Odeh crescent visibility criteria using Meeus algorithms. Zero dependencies. +Lunar crescent visibility for Dart and Flutter. Moon phase, topocentric position, illumination, and Yallop/Odeh crescent criteria using Meeus algorithms. Zero dependencies. + +Uses Meeus lite algorithms (~0.3 degree accuracy). The companion TypeScript package (`moon-sighting` on npm) uses JPL DE442S ephemeris for sub-arcminute precision. ## Installation @@ -22,143 +25,50 @@ import 'package:moon_sighting/moon_sighting.dart'; final phase = getMoonPhase(); print('${phase.phaseName} ${phase.phaseSymbol}'); print('Illumination: ${phase.illumination.toStringAsFixed(1)}%'); -print('Age: ${phase.age.toStringAsFixed(1)} hours'); // Moon position for an observer final pos = getMoonPosition(DateTime.now(), 51.5074, -0.1278, elevation: 10); -print('Azimuth: ${pos.azimuth.toStringAsFixed(1)}'); +print('Azimuth: ${pos.azimuth.toStringAsFixed(1)}'); print('Altitude: ${pos.altitude.toStringAsFixed(1)}'); -print('Distance: ${pos.distance.toStringAsFixed(0)} km'); // Crescent visibility estimate (pass a post-sunset time) final vis = getMoonVisibilityEstimate( DateTime.utc(2025, 3, 31, 18, 30), - 21.4225, 39.8262, // Mecca + 21.4225, 39.8262, // Makkah ); -print('Zone: ${vis.zone.label}'); // A through D +print('Zone: ${vis.zone.label}'); // A through D print('Visible naked eye: ${vis.isVisibleNakedEye}'); ``` ## API -### getMoonPhase([DateTime? date]) +Five public functions. See the [API Reference](https://github.com/acamarata/moon-sighting-dart/wiki/API-Reference) for full field tables. -Returns `MoonPhaseResult` with: - -| Field | Type | Description | +| Function | Returns | Description | | --- | --- | --- | -| `phase` | `MoonPhaseName` | Enum: newMoon, waxingCrescent, firstQuarter, etc. | -| `phaseName` | `String` | Human-readable name | -| `phaseSymbol` | `String` | Moon emoji | -| `illumination` | `double` | Percent illuminated (0-100) | -| `age` | `double` | Hours since last new moon | -| `elongationDeg` | `double` | Moon-Sun elongation in degrees | -| `isWaxing` | `bool` | True when illumination is increasing | -| `nextNewMoon` | `DateTime` | Next new moon (UTC) | -| `nextFullMoon` | `DateTime` | Next full moon (UTC) | -| `prevNewMoon` | `DateTime` | Previous new moon (UTC) | - -### getMoonPosition(DateTime? date, double lat, double lon, {double elevation = 0}) - -Returns `MoonPosition` with: - -| Field | Type | Description | -| --- | --- | --- | -| `azimuth` | `double` | Degrees from North, clockwise | -| `altitude` | `double` | Degrees above horizon (refraction applied) | -| `distance` | `double` | Earth-Moon distance in km | -| `parallacticAngle` | `double` | Parallactic angle in radians | - -### getMoonIllumination([DateTime? date]) - -Returns `MoonIlluminationResult` with: - -| Field | Type | Description | -| --- | --- | --- | -| `fraction` | `double` | Illuminated fraction (0-1) | -| `phase` | `double` | Phase cycle (0=new, 0.25=Q1, 0.5=full, 0.75=Q3) | -| `angle` | `double` | Bright limb position angle (radians) | -| `isWaxing` | `bool` | True when waxing | - -### getMoonVisibilityEstimate(DateTime? date, double lat, double lon, {double elevation = 0}) - -Returns `MoonVisibilityEstimate` with: - -| Field | Type | Description | -| --- | --- | --- | -| `v` | `double` | Odeh V parameter | -| `zone` | `OdehZone` | Visibility zone (a through d) | -| `description` | `String` | Zone description | -| `isVisibleNakedEye` | `bool` | True for zone A | -| `isVisibleWithOpticalAid` | `bool` | True for zones A and B | -| `arcl` | `double` | Sun-Moon elongation (degrees) | -| `arcv` | `double` | Arc of vision (degrees) | -| `w` | `double` | Crescent width (arc minutes) | -| `moonAboveHorizon` | `bool` | Moon above horizon at given time | - -### getMoon(DateTime? date, double lat, double lon, {double elevation = 0}) - -Returns `MoonSnapshot` combining all four results: `phase`, `position`, `illumination`, `visibility`. - -## Visibility Criteria - -The Odeh criterion (2006) classifies crescent visibility into four zones: - -| Zone | V threshold | Meaning | -| --- | --- | --- | -| A | V >= 5.65 | Visible with naked eye | -| B | V >= 2.00 | Visible with optical aid, may be seen naked eye | -| C | V >= -0.96 | Visible with optical aid only | -| D | V < -0.96 | Not visible even with optical aid | - -The Yallop q-test (1997) uses six categories A through F with different threshold semantics. Both criteria use the same underlying polynomial for the minimum arc of vision as a function of crescent width. +| `getMoonPhase([DateTime?])` | `MoonPhaseResult` | Phase name, illumination, age, next events | +| `getMoonPosition(DateTime?, lat, lon)` | `MoonPosition` | Topocentric az/alt, distance | +| `getMoonIllumination([DateTime?])` | `MoonIlluminationResult` | Fraction, phase cycle, bright limb angle | +| `getMoonVisibilityEstimate(DateTime?, lat, lon)` | `MoonVisibilityEstimate` | Odeh V parameter, visibility zone A-D | +| `getMoon(DateTime?, lat, lon)` | `MoonSnapshot` | All four results combined | ## Accuracy -All positions use Meeus (1998) approximations: - -- **Sun:** < 0.01 deg ecliptic longitude error -- **Moon:** < 0.3 deg longitude, < 0.2 deg latitude -- **Distance:** ~300 km error (~0.08%) -- **New/full moon times:** within ~2 hours - -The GCRS-to-topocentric conversion uses a simplified Earth rotation (ERA only, no nutation/precession), adding ~1 deg systematic error. This is acceptable for phase displays, illumination calculations, and approximate visibility estimates. - -For high-precision crescent sighting reports with DE442S ephemeris accuracy, see the TypeScript [moon-sighting](https://github.com/acamarata/moon-sighting) package. - -## Lite Mode vs Full Mode - -This Dart package implements lite mode only. It covers moon phase, position, illumination, and quick visibility estimates using analytical Meeus algorithms with no external data files. - -The full-mode features (DE442S JPL ephemeris, sub-arcsecond accuracy, rise/set event finding, best-time optimization, full sighting reports) are available in the TypeScript package. - -## Architecture - -Two-mode design: lite mode uses Jean Meeus Chapters 47 and 48 for moon phase, position, and illumination: zero dependencies, no file I/O, works in any Dart environment. The GCRS-to-topocentric conversion applies ERA-only Earth rotation (no full nutation/precession), which introduces a ~1 degree systematic error acceptable for display and quick-estimate use cases. - -Full-mode features (DE442S ephemeris, sub-arcsecond accuracy, rise/set event finding) are in the TypeScript [moon-sighting](https://github.com/acamarata/moon-sighting) package. - -## Compatibility - -- Dart SDK >= 3.7.0 -- Works in Flutter, Dart CLI, and server-side Dart -- Zero runtime dependencies +All positions use Meeus (1998) approximations: Moon longitude < 0.3 deg, latitude < 0.2 deg, distance ~300 km. New/full moon times are within ~2 hours. ## Related -- [moon-sighting](https://github.com/acamarata/moon-sighting) (TypeScript) - Full-accuracy lunar crescent visibility with DE442S ephemeris -- [nrel-spa](https://github.com/acamarata/nrel-spa) (TypeScript) - Pure JS NREL Solar Position Algorithm -- [pray-calc](https://github.com/acamarata/pray-calc) (JavaScript) - Islamic prayer time calculation -- [luxon-hijri](https://github.com/acamarata/luxon-hijri) (TypeScript) - Hijri/Gregorian calendar conversion +- [moon-sighting](https://github.com/acamarata/moon-sighting) (TypeScript) - Full accuracy with DE442S ephemeris +- [nrel-spa](https://github.com/acamarata/nrel-spa) (TypeScript) - NREL Solar Position Algorithm +- [pray-calc](https://github.com/acamarata/pray-calc) (TypeScript) - Islamic prayer times ## Acknowledgments -Crescent visibility criteria implemented from: +Crescent visibility criteria from: - B.D. Yallop, "A Method for Predicting the First Sighting of the New Crescent Moon," NAO Technical Note No. 69, 1997. - M.Sh. Odeh, "New Criterion for Lunar Crescent Visibility," Experimental Astronomy 18(1), 39-64, 2006. - -Meeus positions from: Jean Meeus, "Astronomical Algorithms," 2nd ed., Chapters 47 and 48. +- Jean Meeus, "Astronomical Algorithms," 2nd ed., Chapters 47 and 48. ## License