Fix solar chart to use variable amplitude instead of moving horizon#135
Open
Fix solar chart to use variable amplitude instead of moving horizon#135
Conversation
The chart previously used a fixed-amplitude sine curve (always -1 to +1) and positioned the "horizon" line wherever the curve happened to be at sunrise time, causing the horizon to drift up in winter and down in summer. Now yValue(for:) subtracts the sine value at sunrise so that y=0 is always the horizon. The arc's amplitude above y=0 at solar noon scales naturally with daylight duration: larger on long summer days, smaller on short winter days — matching how the sun actually arcs higher in the sky in summer. The horizonY calculation in chartOverlayContent already derives from yValue(for: safeSunrise), so it automatically locks to y=0 with no additional changes needed. https://claude.ai/code/session_01UmjLxdTg5ZePkPaQDBe4rf
Draws two faint dashed reference arcs alongside the current day's path: one for the summer solstice (longest day) and one for the winter solstice (shortest day). This lets users see at a glance where today falls between the two extremes throughout the year. Implementation: - solsticeNTSolars computes NTSolar for Jun 21 and Dec 21, then labels them longer/shorter by comparing daylightDuration — automatically correct for both hemispheres. - todayEquivalentSunrise maps a solstice's sunrise time-of-day onto today's x-axis as a simple time-offset from midnight, so the path is drawn against the same 24-hour range. Polar day (safeSunrise = endOfDay) and polar night (safeSunrise = noon) both map through cleanly. - yValue(for:withSunriseAt:) applies the same amplitude formula as the main path but with a supplied sunrise reference, keeping the horizon consistent at y=0 across all three curves. - If either solstice NTSolar can't be computed the comparison paths are simply omitted with no visual or runtime impact. https://claude.ai/code/session_01UmjLxdTg5ZePkPaQDBe4rf
Previously the chart used a manually-crafted sine wave whose only relationship to astronomy was the sunrise/sunset times (used to position the horizon and scale the amplitude). The curve was always perfectly sinusoidal regardless of latitude or time of year. This replaces that with actual altitude in degrees above/below the horizon, computed from first principles using the same Schlyter algorithms already present in NTSolar. NTSolar gains altitude(at:) using the standard spherical-astronomy formula: sin(alt) = sin(lat)sin(dec) + cos(lat)cos(dec)cos(HA), where RA/dec come from sun_RA_dec() and the local hour angle is derived from GMST0() + UT + longitude — all existing private helpers, so no new dependencies are introduced. DaylightChart changes: - yValue(for:) now returns solar.altitude(at:) in degrees - yValue(for:solsticeSolar:) maps today's time-of-day to the solstice date and calls solsticeSolar.altitude(at:), replacing the old sine-offset approach for the comparison paths - effectiveYScale auto-sizes from summer solstice noon altitude so the chart scale is stable year-round and location-appropriate - horizonY uses proxy.position(forY: 0.0) directly since 0° altitude is exactly the geometric horizon - yScale is now optional (nil = auto); widget override removed - Dead code removed: progressValue, culminationDelta, noonish, dayLength, endOfDay, daylightProportion, todayEquivalentSunrise, yValue(for:withSunriseAt:) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the manual Path-based drawing in chartBackground with native
LineMark series inside Chart{}, applying .interpolationMethod(.catmullRom)
for smooth curves. This eliminates the jagged appearance at equatorial
locations caused by the low 30-minute sample rate with straight-line segments.
The solstice comparison paths and today's solar path are all now LineMark
series, with .chartLegend(.hidden) suppressing the auto-generated legend.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The chart previously used a fixed-amplitude sine curve (always -1 to +1)
and positioned the "horizon" line wherever the curve happened to be at
sunrise time, causing the horizon to drift up in winter and down in summer.
Now yValue(for:) subtracts the sine value at sunrise so that y=0 is always
the horizon. The arc's amplitude above y=0 at solar noon scales naturally
with daylight duration: larger on long summer days, smaller on short winter
days — matching how the sun actually arcs higher in the sky in summer.
The horizonY calculation in chartOverlayContent already derives from
yValue(for: safeSunrise), so it automatically locks to y=0 with no
additional changes needed.
https://claude.ai/code/session_01UmjLxdTg5ZePkPaQDBe4rf