elevation.go (2310B)
1 package sunrise 2 3 import ( 4 "math" 5 "time" 6 ) 7 8 // TimeOfElevation calculates the times of day when the sun is at a given elevation 9 // above the horizon on a given day at the specified location. 10 // Returns time.Time{} if there sun does not reach the elevation 11 func TimeOfElevation(latitude, longitude, elevation float64, year int, month time.Month, day int) (time.Time, time.Time) { 12 var ( 13 d = MeanSolarNoon(longitude, year, month, day) 14 solarAnomaly = SolarMeanAnomaly(d) 15 equationOfCenter = EquationOfCenter(solarAnomaly) 16 eclipticLongitude = EclipticLongitude(solarAnomaly, equationOfCenter, d) 17 solarTransit = SolarTransit(d, solarAnomaly, eclipticLongitude) 18 declination = Declination(eclipticLongitude) 19 // https://solarsena.com/solar-elevation-angle-altitude/ 20 numerator = math.Sin(elevation*Degree) - (math.Sin(latitude*Degree) * math.Sin(declination*Degree)) 21 denominator = math.Cos(latitude*Degree) * math.Cos(declination*Degree) 22 hourAngle = math.Acos(numerator / denominator) 23 frac = hourAngle / (2 * math.Pi) 24 morning = solarTransit - frac 25 evening = solarTransit + frac 26 ) 27 28 // Check for cases where the sun never reaches the given elevation. 29 if math.IsNaN(hourAngle) { 30 return time.Time{}, time.Time{} 31 } 32 33 return JulianDayToTime(morning), JulianDayToTime(evening) 34 } 35 36 // Elevation calculates the angle of the sun above the horizon at a given moment 37 // at the specified location. 38 func Elevation(latitude, longitude float64, when time.Time) float64 { 39 var ( 40 d = MeanSolarNoon(longitude, when.Year(), when.Month(), when.Day()) 41 solarAnomaly = SolarMeanAnomaly(d) 42 equationOfCenter = EquationOfCenter(solarAnomaly) 43 eclipticLongitude = EclipticLongitude(solarAnomaly, equationOfCenter, d) 44 solarTransit = SolarTransit(d, solarAnomaly, eclipticLongitude) 45 declination = Declination(eclipticLongitude) 46 frac = solarTransit - TimeToJulianDay(when) 47 hourAngle = 2 * math.Pi * frac 48 // https://solarsena.com/solar-elevation-angle-altitude/ 49 firstPart = math.Sin(latitude*Degree) * math.Sin(declination*Degree) 50 secondPart = math.Cos(latitude*Degree) * math.Cos(declination*Degree) * math.Cos(hourAngle) 51 ) 52 53 return math.Asin(firstPart+secondPart) / Degree 54 }