Last active
September 25, 2023 11:41
-
-
Save houstonhaynes/fcc26d0265d1572fbdb093af88da926a to your computer and use it in GitHub Desktop.
Sundial function to calculate time based on azimuth position of the Sun
This file contains 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
#r "nuget: CoordinateSharp" | |
open System | |
open CoordinateSharp | |
let find_Closest_TimeUnit addTimeFn rangeStart rangeEnd (c : Coordinate) azimuth adjustNegatively = | |
let el = EagerLoad(EagerLoadType.Celestial) | |
el.Extensions <- EagerLoad_Extensions(EagerLoad_ExtensionsType.Solar_Cycle) | |
let mutable closestTime = 0 | |
let mutable minDiff = 999.0 | |
for direction in [1; -1] do | |
if direction = 1 || adjustNegatively then | |
for x in rangeStart .. rangeEnd do | |
let newTime = addTimeFn (float (x * direction)) | |
let nc = Coordinate(c.Latitude.ToDouble(), c.Longitude.ToDouble(), newTime, el) | |
nc.Offset <- c.Offset | |
let currentAzimuth = nc.CelestialInfo.SunAzimuth | |
let diff = Math.Abs(currentAzimuth - azimuth) | |
if diff < minDiff then | |
minDiff <- diff | |
closestTime <- x * direction | |
addTimeFn (float closestTime) | |
let get_Time_At_Solar_Azimuth azimuth (c : Coordinate) = | |
let hour = find_Closest_TimeUnit (c.GeoDate.AddHours) 0 23 c azimuth false | |
let minute = find_Closest_TimeUnit (hour.AddMinutes) 0 59 c azimuth true | |
let second = find_Closest_TimeUnit (minute.AddSeconds) 0 59 c azimuth true | |
second | |
let main () = | |
let lateAzimuth = 202.00 | |
let earlyAzimuth = 158.00 | |
let lat = 35.0 | |
let lon = -82.5 | |
let offset = -5.0 | |
let d = DateTime(2024, 1, 1) | |
let c = Coordinate(lat, lon, d) | |
c.Offset <- offset | |
let timeAtEarlyAzimuth = get_Time_At_Solar_Azimuth earlyAzimuth c | |
let timeAtLateAzimuth = get_Time_At_Solar_Azimuth lateAzimuth c | |
printfn "Time at Sunrise: %A" c.CelestialInfo.SunRise | |
printfn "Time at early azimuth: %A" timeAtEarlyAzimuth | |
printfn "Solar noon: %A" c.CelestialInfo.SolarNoon | |
printfn "Time at late azimuth: %A" timeAtLateAzimuth | |
printfn "Time at Sunset: %A" c.CelestialInfo.SunSet | |
if c.CelestialInfo.SolarNoon.HasValue then | |
let ts = timeAtLateAzimuth - c.CelestialInfo.SolarNoon.Value | |
printfn "Time range from Solar noon: %d:%d" ts.Hours (abs ts.Minutes) | |
let c = Coordinate(lat, lon, timeAtEarlyAzimuth) | |
c.Offset <- offset | |
printfn "Early azimuth at time verification: %A" c.CelestialInfo.SunAzimuth | |
main () | |
(* | |
Time at Sunrise: 1/1/2024 7:39:08 AM | |
Time at early azimuth: 1/1/2024 11:11:47 AM | |
Solar noon: 1/1/2024 12:34:29 PM | |
Time at late azimuth: 1/1/2024 1:59:09 PM | |
Time at Sunset: 1/1/2024 5:29:49 PM | |
Time range from Solar noon: 1:24 | |
Early azimuth at time verification: 157.9994881 | |
*) | |
(* use http://sunfollower.net to verify these dat/time points *) |
I definitely planning to adopt @ijrussell 's further refactor - such a great learning experience! 🧠
https://gist.github.com/ijrussell/e1417ecdf3d2b263abac32fa677c3b89
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Verification using sunnfollower.net
Sunrise: http://sunfollower.net/#1/35.5951,-82.5515,7/2024.01.01/12:39
Early Azimuth (158°): http://sunfollower.net/#1/35.5951,-82.5515,7/2024.01.01/16:11
Solar Noon (180°): http://sunfollower.net/#1/35.5951,-82.5515,12/2024.01.01/17:34
Late Azimuth (202°): http://sunfollower.net/#1/35.5951,-82.5515,7/2024.01.01/18:59
Sunset: http://sunfollower.net/#1/35.5951,-82.5515,7/2024.01.01/22:29