Compare commits

..

No commits in common. "main" and "v1.0.0" have entirely different histories.
main ... v1.0.0

2 changed files with 111 additions and 20 deletions

126
README.md
View file

@ -3,11 +3,8 @@
[![pub package](https://img.shields.io/pub/v/moon_sighting.svg)](https://pub.dev/packages/moon_sighting) [![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) [![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) [![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. Moon phase, topocentric position, illumination, and Yallop/Odeh crescent criteria using Meeus algorithms. Zero dependencies. Lunar crescent visibility for Dart and Flutter. Computes moon phase, topocentric position, illumination, and Yallop/Odeh crescent visibility 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 ## Installation
@ -25,16 +22,18 @@ import 'package:moon_sighting/moon_sighting.dart';
final phase = getMoonPhase(); final phase = getMoonPhase();
print('${phase.phaseName} ${phase.phaseSymbol}'); print('${phase.phaseName} ${phase.phaseSymbol}');
print('Illumination: ${phase.illumination.toStringAsFixed(1)}%'); print('Illumination: ${phase.illumination.toStringAsFixed(1)}%');
print('Age: ${phase.age.toStringAsFixed(1)} hours');
// Moon position for an observer // Moon position for an observer
final pos = getMoonPosition(DateTime.now(), 51.5074, -0.1278, elevation: 10); 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('Altitude: ${pos.altitude.toStringAsFixed(1)}');
print('Distance: ${pos.distance.toStringAsFixed(0)} km');
// Crescent visibility estimate (pass a post-sunset time) // Crescent visibility estimate (pass a post-sunset time)
final vis = getMoonVisibilityEstimate( final vis = getMoonVisibilityEstimate(
DateTime.utc(2025, 3, 31, 18, 30), DateTime.utc(2025, 3, 31, 18, 30),
21.4225, 39.8262, // Makkah 21.4225, 39.8262, // Mecca
); );
print('Zone: ${vis.zone.label}'); // A through D print('Zone: ${vis.zone.label}'); // A through D
print('Visible naked eye: ${vis.isVisibleNakedEye}'); print('Visible naked eye: ${vis.isVisibleNakedEye}');
@ -42,33 +41,124 @@ print('Visible naked eye: ${vis.isVisibleNakedEye}');
## API ## API
Five public functions. See the [API Reference](https://github.com/acamarata/moon-sighting-dart/wiki/API-Reference) for full field tables. ### getMoonPhase([DateTime? date])
| Function | Returns | Description | Returns `MoonPhaseResult` with:
| Field | Type | Description |
| --- | --- | --- | | --- | --- | --- |
| `getMoonPhase([DateTime?])` | `MoonPhaseResult` | Phase name, illumination, age, next events | | `phase` | `MoonPhaseName` | Enum: newMoon, waxingCrescent, firstQuarter, etc. |
| `getMoonPosition(DateTime?, lat, lon)` | `MoonPosition` | Topocentric az/alt, distance | | `phaseName` | `String` | Human-readable name |
| `getMoonIllumination([DateTime?])` | `MoonIlluminationResult` | Fraction, phase cycle, bright limb angle | | `phaseSymbol` | `String` | Moon emoji |
| `getMoonVisibilityEstimate(DateTime?, lat, lon)` | `MoonVisibilityEstimate` | Odeh V parameter, visibility zone A-D | | `illumination` | `double` | Percent illuminated (0-100) |
| `getMoon(DateTime?, lat, lon)` | `MoonSnapshot` | All four results combined | | `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.
## Accuracy ## Accuracy
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. 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
## Related ## Related
- [moon-sighting](https://github.com/acamarata/moon-sighting) (TypeScript) - Full accuracy with DE442S ephemeris - [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) - NREL Solar Position Algorithm - [nrel-spa](https://github.com/acamarata/nrel-spa) (TypeScript) - Pure JS NREL Solar Position Algorithm
- [pray-calc](https://github.com/acamarata/pray-calc) (TypeScript) - Islamic prayer times - [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
## Acknowledgments ## Acknowledgments
Crescent visibility criteria from: Crescent visibility criteria implemented from:
- B.D. Yallop, "A Method for Predicting the First Sighting of the New Crescent Moon," NAO Technical Note No. 69, 1997. - 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. - M.Sh. Odeh, "New Criterion for Lunar Crescent Visibility," Experimental Astronomy 18(1), 39-64, 2006.
- Jean Meeus, "Astronomical Algorithms," 2nd ed., Chapters 47 and 48.
Meeus positions from: Jean Meeus, "Astronomical Algorithms," 2nd ed., Chapters 47 and 48.
## License ## License

View file

@ -7,6 +7,7 @@ version: 1.0.0
homepage: https://github.com/acamarata/moon-sighting-dart homepage: https://github.com/acamarata/moon-sighting-dart
repository: https://github.com/acamarata/moon-sighting-dart repository: https://github.com/acamarata/moon-sighting-dart
issue_tracker: https://github.com/acamarata/moon-sighting-dart/issues issue_tracker: https://github.com/acamarata/moon-sighting-dart/issues
publisher: ariccamarata.com
topics: topics:
- moon - moon
- lunar - lunar