Something went wrong. Try again.
A Zig library for astronomical calculations: the Sun and Moon from anywhere on Earth, the Moon's phases and libration, and time scales.
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192// SPDX-FileCopyrightText: © 2026 Jeffrey C. Ollie <jeff@ocjtech.us>// SPDX-License-Identifier: MIT
//! The Sun's apparent position, as seen from the Earth's center (Meeus,//! *Astronomical Algorithms*, 2nd ed., ch. 25) and by an observer on its//! surface.
const std = @import("std");const math = std.math;
const Angle = @import("Angle.zig");const coord = @import("coord.zig");const earth = @import("earth.zig");const Instant = @import("time.zig").Instant;const observer_ = @import("observer.zig");const Observer = observer_.Observer;const Topocentric = observer_.Topocentric;
/// Where the Sun appears from the Earth's center at an instant.pub const Position = struct { /// Apparent ecliptic coordinates, referred to the true equinox of date. /// The latitude is always zero: the real one never exceeds 1.2″, well /// inside the accuracy of the longitude. ecliptic: coord.Ecliptic, /// Apparent equatorial coordinates, referred to the true equator and /// equinox of date. equatorial: coord.Equatorial, /// The distance between the centers of the Sun and the Earth, in /// astronomical units. distance_au: f64,};
/// The Sun's apparent position at an instant, in either time scale.////// The geometric position is Meeus's low-accuracy method (pp. 163–164),/// which treats the Earth's orbit as an unperturbed ellipse and is good to/// about 0.01°. It is made apparent as Meeus describes on p. 167: the/// nutation in longitude from `astro.earth` is added, aberration is applied/// as −20.4898″/R (eq. 25.10), and the result is converted to equatorial/// coordinates with the true obliquity. That is the same nutation the Moon's/// position uses, so it cancels exactly where the two are compared.////// NaN if the instant is not finite.pub fn position(instant: Instant) Position { const t = instant.julianCenturies();
// Mean longitude, mean anomaly and eccentricity (eqs. 25.2–25.4). const l0 = 280.46646 + 36000.76983 * t + 0.0003032 * t * t; const m = 357.52911 + 35999.05029 * t - 0.0001537 * t * t; const e = 0.016708634 - 0.000042037 * t - 0.0000001267 * t * t;
// The equation of the center (p. 164). const m_rad = m * math.rad_per_deg; const c = (1.914602 - 0.004817 * t - 0.000014 * t * t) * @sin(m_rad) + (0.019993 - 0.000101 * t) * @sin(2 * m_rad) + 0.000289 * @sin(3 * m_rad);
const true_longitude = l0 + c; const true_anomaly = (m + c) * math.rad_per_deg; // The radius vector (eq. 25.5). const r = 1.000001018 * (1 - e * e) / (1 + e * @cos(true_anomaly));
const nutation = earth.nutation(instant); const longitude = Angle.fromDegrees(true_longitude) .add(nutation.longitude) .add(Angle.fromArcseconds(-20.4898 / r)) .normalized(); const ecliptic: coord.Ecliptic = .{ .longitude = longitude, .latitude = Angle.fromRadians(if (math.isFinite(t)) 0 else math.nan(f64)), }; const obliquity = earth.meanObliquity(instant).add(nutation.obliquity); return .{ .ecliptic = ecliptic, .equatorial = ecliptic.toEquatorial(obliquity), .distance_au = r, };}
/// The Sun's apparent topocentric position at an instant, in either time/// scale: its apparent position passed through `astro.observer.topocentric`./// The Sun's parallax is under 9″, inside the 0.01° accuracy of its/// position, but it is applied all the same, so that the Sun and the Moon/// are seen from the same place. NaN if the instant is not finite or the/// observer is not valid.pub fn topocentric(instant: Instant, observer: Observer) Topocentric { const p = position(instant); return observer_.topocentric(instant, observer, p.equatorial, p.distance_au * km_per_au);}
const km_per_au = 149597870.7;