- Zig 96.2%
- Shell 3.4%
- Nix 0.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
moon.libration.topocentric is Meeus's direct calculation (p. 375): the libration and the position angle of the axis found as for the Earth's center, from the Moon's topocentric ecliptic coordinates and right ascension. The geocentric libration and it now share one function. Against Horizons from Palomar, Tromso and Cerro Paranal, up to the last measured Delta T: 0.0082 deg in longitude and 0.0081 deg in the position angle; in latitude the same 0.0224 deg lunar frame tilt as from the center, and 0.0049 deg with it taken out. The topocentric libration is up to 0.989 deg from the geocentric at these sites. Closes #15 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_014UMaGEwDffMoTp1d9BKsaz |
||
| .forgejo/workflows | ||
| docs | ||
| LICENSES | ||
| src | ||
| tests | ||
| tools | ||
| .gitignore | ||
| AGENTS.md | ||
| build.zig | ||
| build.zig.zon | ||
| CONTRIBUTING.md | ||
| flake.lock | ||
| flake.nix | ||
| GLOSSARY.md | ||
| README.md | ||
| REUSE.toml | ||
zig-astro
Astronomical calculations for Zig 0.17.
The Earth's Moon is the first target. The Sun, the planets, and other natural and artificial satellites are to follow.
What is here so far is the foundation everything else stands on:
astro.time |
Instants, the time scales they are counted in (TT and UT), Julian and Gregorian calendar dates, Unix time, and ΔT |
astro.Angle |
Angles, read and written in radians, degrees, arcseconds, hours, and sexagesimal, so that one is never mistaken for another |
astro.coord |
Ecliptic, equatorial and horizontal coordinates, and the conversions between them |
astro.earth |
Nutation, the mean and true obliquity of the ecliptic, and mean and apparent sidereal time at Greenwich |
astro.observer |
An observer on the Earth's surface, by geodetic latitude, east longitude and height on the WGS 84 ellipsoid, and the topocentric position — right ascension and declination, ecliptic coordinates, hour angle, azimuth and altitude, and distance — of any body whose geocentric position is known; and atmospheric refraction, from airless to observed altitude and back |
astro.sun |
The Sun's apparent position and distance, to about 0.01°, from the Earth's center or from an observer |
astro.moon |
The Moon's apparent position and distance, to about 10″ in longitude and 4″ in latitude, from the Earth's center or from an observer, from whom it can be a degree away |
astro.moon.phase |
The Moon's phase at an instant — elongation, phase angle, illuminated fraction, the bright limb, waxing or waning, and its named phase — and the instants of new Moon, first quarter, full Moon and last quarter, to within seconds, with the lunar age |
astro.moon.libration |
The Moon's optical, physical and total libration and the position angle of its axis, from the Earth's center or from an observer, the subsolar point, and the colongitude that tells which craters the Sun is rising on |
const astro = @import("astro");
// 1957 October 4, 19:26:24 UT, the launch of Sputnik 1.
const launch = astro.time.Instant.fromCalendar(
.gregorian,
.init(1957, .october, 4, 19, 26, 24),
.ut,
);
const tt = launch.to(.tt, .model); // about 32 s later, by the ΔT model
Where the Moon is in the sky, seen from Palomar Observatory:
const palomar: astro.observer.Observer = .{
.latitude = astro.Angle.fromDegrees(33.3561),
.longitude = astro.Angle.fromDegrees(-116.8625), // east is positive
.height_m = 1706,
};
const now = astro.time.Instant.fromCalendar(
.gregorian,
.init(2026, .october, 23, 4, 0, 0),
.ut,
);
const moon = astro.moon.topocentric(now, palomar);
// moon.horizontal.azimuth.degrees() is about 153.0, a little east of
// south, and moon.horizontal.altitude.degrees() about 51.1.
Longitude counts positive east of Greenwich, and azimuth from the north
through the east, as almost everyone counts them; Meeus counts both
differently, and the conversions from his conventions are made inside the
library. Altitudes are airless; astro.observer.observedAltitude adds the
refraction that lifts a body to where it is seen, about half a degree at
the horizon, and airlessAltitude takes it away again.
Every calculation takes an Instant, which says whether it is counted in TT,
the uniform scale the theories use, or UT, which civil time follows. UTC is
counted as UT. ΔT, the difference, comes from the Espenak–Meeus polynomials
for the past, the U.S. Naval Observatory's measurements since 2005, and a
prediction joining them to the long-term trend, unless a caller supplies a
value of their own. Calendar dates say which calendar
they are in: there is no automatic switch at 1582, because countries changed
calendars at different times.
The API documentation is generated
from the doc comments and rebuilt from main on every push.
Where this lives
The Forgejo instance at https://git.jcollie.dev/jeff/zig-astro is the main home of the repository:
$ git clone https://git.jcollie.dev/jeff/zig-astro.git
and it is mirrored on Tangled at https://tangled.org/jcollie.dev/zig-astro.
Adding it to a project
$ zig fetch --save git+https://git.jcollie.dev/jeff/zig-astro.git
then, in build.zig:
const astro = b.dependency("astro", .{ .target = target, .optimize = optimize });
exe.root_module.addImport("astro", astro.module("astro"));
Building
The Nix flake's development shell has everything, Zig 0.17.0 included:
$ nix develop
$ zig build test --summary all # the tests
$ zig build check # compile everything without running it
$ zig build fuzz --fuzz # fuzz every calculation with any f64 at all
$ zig build docs-serve # the API documentation, at http://127.0.0.1:8000/
Without Nix, Zig 0.17.0 is all that is needed; the library has no dependencies.
The tests check every calculation two ways: against the worked examples in
Meeus's Astronomical Algorithms, which shows the code does what the book
says, and against ephemerides from JPL Horizons over 1900–2100, which shows
the book agrees with the sky. The Horizons tables are kept in
tests/reference/ exactly as Horizons sent them, and tools/horizons.sh is
the query that fetches them again. The instants of the phases are checked
against all 9,895 in NASA's table of the phases of 1901–2100, which
tools/nasa-phases.sh fetches.
The documentation has to be served rather than opened: what Zig emits is a
WebAssembly viewer that fetches the source it shows from a tar file beside it,
and a browser refuses to fetch anything from a file:// page.
tools/docs_server.zig is that server, for one person on the loopback
interface.
Reporting issues and contributing
Report issues and send pull requests to the Tangled mirror, https://tangled.org/jcollie.dev/zig-astro. CONTRIBUTING.md covers setting up, the checks a change has to pass, and how the code is laid out.
References cited
- Espenak, F. (2007). Historical Values of Delta T (ΔT). NASA Eclipse Web Site. https://eclipse.gsfc.nasa.gov/SEhelp/deltat2004.html
- Espenak, F. (2007). Polynomial Expressions for Delta T (ΔT). NASA Eclipse Web Site. https://eclipse.gsfc.nasa.gov/SEhelp/deltatpoly2004.html
- Espenak, F. Phases of the Moon: 1901 to 2000 and 2001 to 2100. NASA Eclipse Web Site. https://eclipse.gsfc.nasa.gov/phase/phases1901.html, https://eclipse.gsfc.nasa.gov/phase/phases2001.html
- Jet Propulsion Laboratory. Horizons On-Line Ephemeris System. Solar System Dynamics Group. https://ssd.jpl.nasa.gov/horizons/
- Meeus, J. (1998). Astronomical Algorithms (2nd ed.). Willmann-Bell.
- National Imagery and Mapping Agency (2000). Department of Defense World Geodetic System 1984: Its Definition and Relationships with Local Geodetic Systems (Technical Report TR8350.2, 3rd ed., Amendment 1).
- U.S. Naval Observatory. Delta T: Monthly Values. https://maia.usno.navy.mil/ser7/deltat.data
License
MIT. See LICENSES/MIT.txt. This project follows the
REUSE specification.