src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

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 }