The Math Behind GeoLog’s Ephemeris


GeoLog’s Ephemeris: Reading the Compass Rose

The screenshot above shows GeoLog’s Ephemeris view for Nubble Light, York County, Maine — April 24, 2014 at 9:30 AM Eastern Time. Before diving into the mathematics that make it work, it helps to understand what each element of the display represents.

The photo strip across the top shows the gallery photos associated with this location. Each thumbnail represents a slightly different vantage point — a different GPS coordinate, a different compass heading, or a different moment in time. Tapping any thumbnail updates the entire ephemeris display to that photo’s exact position and orientation. Two photos taken 50 feet apart at the same location may show meaningfully different sun and moon positions relative to the scene. GeoLog’s ephemeris can also run without any photo at all, using the phone’s live GPS position and compass heading — the same data, acquired differently.

The compass rose is the heart of the display. It rotates with the phone’s compass so that what you see in front of you is always at the top. The red triangle at 12 o’clock marks the direction the phone is currently pointing — 91° in this example, nearly due East.

The sun needle (gold/orange) and moon needle (blue-gray) extend from the center of the compass toward the body’s current azimuth — its compass bearing from the observer’s position. In this screenshot the sun is at azimuth 111° (East-Southeast) and altitude 39°, the moon at azimuth 193° (South-Southwest) and altitude 39°. Both values are shown in the data strip below the compass.

The SunPath (outer gold arc) and MoonPath (outer blue-gray arc) trace the full above-horizon trajectory of each body across the sky for the selected day — from rise azimuth, through transit, to set azimuth. A photographer can read at a glance whether the sun will be coming from the left or right of a scene, and roughly when during the day it will be in a useful position.

The DomeArc is the inner arc that bows toward the center of the compass rose. Its depth toward center is proportional to the body’s maximum altitude — how high it climbs above the horizon at transit. A sun that barely clears the horizon in winter produces a shallow arc that hugs the outer ring. A summer sun that climbs steeply produces a deep arc that reaches well toward the center. This gives the photographer an immediate sense of the quality and angle of the light, not just its compass direction.

The time slider at the bottom controls the moment being displayed. Dragging it advances or rewinds time continuously, updating the needle positions and arc shapes in real time. The < and > buttons step by one day at a time; the << and >> buttons jump a month at a time. Stepping through months allows the photographer to see how the sun and moon positions, path directions, and arc heights change throughout the year for their scouted location — revealing at a glance which months offer the best light angle, the highest sun for a particular scene, or the ideal moon position for a planned night shoot.

The Photo button is perhaps the most powerful feature in the ephemeris. Tapping it rewinds the display to the exact moment the selected gallery photo was taken — placing the sun and moon precisely where they were when the shutter fired. A photographer standing at Nubble Light today, looking at a photo taken in April 2014, can see exactly what the light was doing that morning and plan a return to recreate or improve it.

All of this — every needle position, every arc, every rise and set time — is computed in real time from a single source: the equations of Jean Meeus.


Who Is Jean Meeus?

Jean Meeus is a Belgian astronomer, born in 1928, whose book Astronomical Algorithms (1991, second edition 1998) is the definitive reference for anyone computing the positions of celestial bodies with genuine precision. Planetariums, observatories, and navigation systems use it. Most astronomy apps use simplified approximations — fast, adequate at mid-latitudes, increasingly wrong as you approach the poles. Meeus doesn’t approximate. His algorithms work anywhere on Earth.

The foundation of every Meeus calculation is the Julian Day — a continuous count of days since January 1, 4713 BC, independent of months, years, timezones, or calendar reforms. Before doing any astronomy, everything gets converted to JD.


The Julian Day

The conversion from a Gregorian calendar date is one of Meeus’s cleaner formulas. January and February are treated as months 13 and 14 of the previous year, and a Gregorian calendar correction B accounts for the dropped century leap years:

JD = \lfloor 365.25(Y + 4716) \rfloor + \lfloor 30.6001(M + 1) \rfloor + D + B - 1524.5

Where:

A = \lfloor Y / 100 \rfloor \qquad B = 2 - A + \lfloor A/4 \rfloor

The epoch J2000.0 — January 1, 2000 at 12:00 UTC — is JD 2451545.0. Nearly every Meeus formula measures time as Julian centuries T since this epoch:

T = \frac{JD - 2451545.0}{36525}

Every sun and moon calculation in GeoLog starts here. The timestamp from a photo’s EXIF data, anchored to the location’s timezone via Apple’s reverse geocoding, converts to a Julian Day that feeds everything downstream.


Sun Position: From Orbit to Horizon

Finding where the sun is in the sky involves three coordinate systems. First, ecliptic coordinates — the sun’s position relative to Earth’s orbital plane. Then equatorial coordinates — right ascension and declination, the celestial equivalent of longitude and latitude. Finally, horizontal coordinates — azimuth and altitude — which is what GeoLog displays on the compass rose as the sun and moon needles.

Step 1: Ecliptic Longitude

The mean longitude L₀ and mean anomaly M describe where Earth is in its orbit:

L_0 = 280.46646° + 36000.76983° \cdot T
M = 357.52911° + 35999.05029° \cdot T

The equation of center corrects for the elliptical orbit, giving the sun’s true ecliptic longitude λ:

\lambda = L_0 + 1.914602° \sin M + 0.019993° \sin 2M

Step 2: Equatorial Coordinates

The obliquity of the ecliptic ε — Earth’s axial tilt — converts ecliptic longitude to right ascension α and declination δ:

\varepsilon = 23.439° - 0.0000004° \cdot T
\alpha = \arctan\!\left(\frac{\cos\varepsilon \cdot \sin\lambda}{\cos\lambda}\right) \qquad \delta = \arcsin(\sin\varepsilon \cdot \sin\lambda)

Step 3: Horizontal Coordinates

Converting to the observer’s local sky requires the Greenwich Mean Sidereal Time (GMST) and the Local Sidereal Time (LST):

GMST = 280.46061837° + 360.98564736629° \cdot (JD - 2451545.0)
LST = GMST + \lambda_{obs}

Where λ_obs is the observer’s longitude. The Hour Angle HA measures how far the body has moved past the meridian:

HA = LST - \alpha

Finally, altitude h and azimuth A — the values GeoLog displays in the data strip below the compass rose:

\sin h = \sin\phi \cdot \sin\delta + \cos\phi \cdot \cos\delta \cdot \cos HA
\cos A = \frac{\sin\delta - \sin\phi \cdot \sin h}{\cos\phi \cdot \cos h}

With a quadrant correction based on the sign of sin(HA). These equations run in GeoLog every time the phone’s compass moves, every time the time slider advances — a live recalculation producing the azimuth needle and altitude reading on the compass rose.


The Problem That Started Everything

GeoLog’s original ephemeris feature was called “Sun & Moon.” The first implementation worked well enough for most locations. Then I started testing at extreme latitudes — prompted by watching Thomas Heaton film above the Arctic Circle in northern Norway — and everything I thought I understood about rise and set times fell apart.

My rise and set calculation scanned 24 one-hour windows looking for the moment the sun crossed the horizon threshold. At 78°N in June, that crossing never occurs. The scan ran to completion and returned nothing useful.

The underlying geometry is the relationship between the sun’s declination δ and the observer’s latitude φ. The condition for a body to remain permanently above the horizon — what I now call the CircumpolarCondition — is:

\delta > 90° - \phi \quad \text{(always above horizon — midnight sun)}
\delta < -(90° - \phi) \quad \text{(always below horizon — polar night)}

At 78°N the threshold is ±12°. The sun’s declination in June reaches +23.5° — well above it. The sun never sets. Most apps simply fail silently at this point.

The moon adds further complexity. Its orbital plane is tilted 5.1° relative to the ecliptic, which itself tilts up to 23.5° relative to the equator. The moon’s declination swings from approximately −28.5° to +28.5° over its 18.6-year nodal cycle. At high latitudes this means the moon can be circumpolar at various points throughout the year — not just in summer — depending on where it sits in that long cycle. This is the circumpolar moon, less famous than the midnight sun but just as real, and just as capable of breaking a naive ephemeris implementation.


Three-State Detection

The fix was to detect the CircumpolarCondition before scanning for a horizon crossing. This requires finding the body’s maximum and minimum altitude over the full calendar day — 25 hourly samples across a 24-hour window. The horizon threshold of −0.833° accounts for two physical effects:

  • Atmospheric refraction (~0.567°): the atmosphere bends light around the curvature of the Earth, making the sun appear above the geometric horizon when it is physically just below it
  • Solar semidiameter (~0.267°): sunrise is defined as the moment the upper limb clears the horizon, not the center

The three-state logic is then:

h_{max} < -0.833° \implies \text{polar night — body never rises}
h_{min} > -0.833° \implies \text{CircumpolarCondition — body never sets}
\text{otherwise} \implies \text{normal day — scan for horizon crossing}

GeoLog’s compass rose handles all three states. For polar night the SunPath or MoonPath arc is absent. For the CircumpolarCondition the arc completes a full circle. For a normal day the arc spans from rise azimuth to set azimuth through the transit point.


The Bracketing Root-Finder

For normal days, the precise moment of sunrise or sunset is found using a two-stage approach. A coarse scan checks 26 one-hour windows starting at local midnight, scanning for the hour bracket where the altitude sign changes from negative to positive (for sunrise) or positive to negative (for sunset). The window is 26 hours rather than 24 to capture events near midnight at high latitudes.

Once the bracket is found, binary search refinement narrows the crossing to approximately 3-second precision in 15 iterations:

\text{precision} = \frac{3600 \text{ seconds}}{2^{15}} \approx 0.11 \text{ seconds}

At each step the midpoint time is evaluated, the altitude sign is checked, and the bracket is halved. After 15 halvings the bracket is smaller than any meaningful precision requirement for photography planning. The rise and set times shown at the bottom of GeoLog’s ephemeris screen — 05:46:07 AM EDT and 07:35:40 PM EDT in the screenshot — are the direct output of this two-stage finder.


Transit Azimuth and Arc Direction

Knowing when the sun rises and sets gives two compass bearing points. But drawing the correct arc between them — the SunPath and MoonPath in GeoLog — requires knowing which of the two possible paths the body actually travels. This is the transit azimuth: the compass bearing at the body’s highest point between rise and set.

The transit occurs at the midpoint Julian Day:

JD_{transit} = \frac{JD_{rise} + JD_{set}}{2}

The correct arc is whichever clockwise sweep from the rise azimuth to the set azimuth passes through the transit azimuth:

\text{span}_{cw} = (A_{set} - A_{rise} + 360°) \bmod 360°
\text{dist}_{cw} = (A_{transit} - A_{rise} + 360°) \bmod 360°
\text{draw clockwise} \iff \text{dist}_{cw} < \text{span}_{cw}

This matters most for bodies visible for more than 12 hours — the Arctic summer sun, or a full moon near perigee — where the shortest-path assumption picks the wrong arc entirely. In GeoLog, the transit azimuth also determines the depth of the DomeArc: the body’s altitude at the midpoint JD directly controls how far the inner arc bows toward the center of the compass rose.


The Moon’s Timeline Problem

The sun is well-behaved. It rises before it sets, every day, essentially by definition. The moon is not.

The moon’s orbital period is approximately 29.5 days, which means its rise and set times advance by roughly 50 minutes each day. On some calendar days the moon sets before it rises — moonset occurs just after midnight, followed by moonrise in the evening. This creates an ambiguity the original implementation couldn’t handle: which event is “rise” and which is “set” when set happens first? The ephemeris would draw the MoonPath arc on the wrong side of the compass, or display an arc representing the time the moon was below the horizon rather than above it.

The solution is GeoLog’s extended time slider. Rather than constraining the ephemeris to a strict 24-hour calendar day, the slider extends far enough to encompass a complete rise-to-set cycle for the moon. When the required events cross day boundaries — when the relevant moonset belongs to yesterday or the moonrise belongs to tomorrow — GeoLog labels them with Yesterday or Tomorrow badges. The photographer always knows what day the displayed events belong to.


Timezone Anchoring

One critical detail: Meeus’s bracketing functions require local noon as input, not UTC noon. The scan start is defined as JD − 0.5, which should resolve to local midnight. Pass UTC noon instead and the scan window starts at the wrong moment entirely — potentially hours off for observers far from the Greenwich meridian.

GeoLog obtains the correct timezone from Apple’s reverse geocoding, which returns the timezone of the photographed location as part of the placemark metadata. A photo taken at Nubble Light in Maine carries Eastern Time. A photo taken in Sedona carries Mountain Standard Time. Passing the correct local noon Julian Day anchors the scan to the right moment regardless of where the photographer is sitting when they plan their return visit.

This is the bridge between GPS and astronomy. The photograph carries its location and timestamp in EXIF metadata. Reverse geocoding adds the timezone. The timezone anchors the Julian Day. And the Julian Day feeds Jean Meeus.


GeoLog is a free iOS app for photo location scouting.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *