1 const paMacros = require('./pa-macros.js'); 2 const paTypes = require('./pa-types.js'); 3 const paUtils = require('./pa-utils.js'); 4 5 /** 6 * Calculate approximate position of the sun for a local date and time. 7 */ 8 function approximatePositionOfSun(lctHours, lctMinutes, lctSeconds, localDay, localMonth, localYear, isDaylightSaving, zoneCorrection) { 9 var daylightSaving = (isDaylightSaving == true) ? 1 : 0; 10 11 var greenwichDateDay = paMacros.localCivilTimeGreenwichDay(lctHours, lctMinutes, lctSeconds, daylightSaving, zoneCorrection, localDay, localMonth, localYear); 12 var greenwichDateMonth = paMacros.localCivilTimeGreenwichMonth(lctHours, lctMinutes, lctSeconds, daylightSaving, zoneCorrection, localDay, localMonth, localYear); 13 var greenwichDateYear = paMacros.localCivilTimeGreenwichYear(lctHours, lctMinutes, lctSeconds, daylightSaving, zoneCorrection, localDay, localMonth, localYear); 14 var utHours = paMacros.localCivilTimeToUniversalTime(lctHours, lctMinutes, lctSeconds, daylightSaving, zoneCorrection, localDay, localMonth, localYear); 15 var utDays = utHours / 24; 16 var jdDays = paMacros.civilDateToJulianDate(greenwichDateDay, greenwichDateMonth, greenwichDateYear) + utDays; 17 var dDays = jdDays - paMacros.civilDateToJulianDate(0, 1, 2010); 18 var nDeg = 360 * dDays / 365.242191; 19 var mDeg1 = nDeg + paMacros.sunELong(0, 1, 2010) - paMacros.sunPeri(0, 1, 2010); 20 var mDeg2 = mDeg1 - 360 * Math.floor(mDeg1 / 360); 21 var eCDeg = 360 * paMacros.sunEcc(0, 1, 2010) * Math.sin(paUtils.degreesToRadians(mDeg2)) / Math.PI; 22 var lSDeg1 = nDeg + eCDeg + paMacros.sunELong(0, 1, 2010); 23 var lSDeg2 = lSDeg1 - 360 * Math.floor(lSDeg1 / 360); 24 var raDeg = paMacros.ecRA(lSDeg2, 0, 0, 0, 0, 0, greenwichDateDay, greenwichDateMonth, greenwichDateYear); 25 var raHours = paMacros.decimalDegreesToDegreeHours(raDeg); 26 var decDeg = paMacros.ecDec(lSDeg2, 0, 0, 0, 0, 0, greenwichDateDay, greenwichDateMonth, greenwichDateYear); 27 28 var sunRAHour = paMacros.decimalHoursHour(raHours); 29 var sunRAMin = paMacros.decimalHoursMinute(raHours); 30 var sunRASec = paMacros.decimalHoursSecond(raHours); 31 var sunDecDeg = paMacros.decimalDegreesDegrees(decDeg); 32 var sunDecMin = paMacros.decimalDegreesMinutes(decDeg); 33 var sunDecSec = paMacros.decimalDegreesSeconds(decDeg); 34 35 return [sunRAHour, sunRAMin, sunRASec, sunDecDeg, sunDecMin, sunDecSec]; 36 } 37 38 /** 39 * Calculate precise position of the sun for a local date and time. 40 */ 41 function precisePositionOfSun(lctHours, lctMinutes, lctSeconds, localDay, localMonth, localYear, isDaylightSaving, zoneCorrection) { 42 var daylightSaving = (isDaylightSaving == true) ? 1 : 0; 43 44 var gDay = paMacros.localCivilTimeGreenwichDay(lctHours, lctMinutes, lctSeconds, daylightSaving, zoneCorrection, localDay, localMonth, localYear); 45 var gMonth = paMacros.localCivilTimeGreenwichMonth(lctHours, lctMinutes, lctSeconds, daylightSaving, zoneCorrection, localDay, localMonth, localYear); 46 var gYear = paMacros.localCivilTimeGreenwichYear(lctHours, lctMinutes, lctSeconds, daylightSaving, zoneCorrection, localDay, localMonth, localYear); 47 var sunEclipticLongitudeDeg = paMacros.sunLong(lctHours, lctMinutes, lctSeconds, daylightSaving, zoneCorrection, localDay, localMonth, localYear); 48 var raDeg = paMacros.ecRA(sunEclipticLongitudeDeg, 0, 0, 0, 0, 0, gDay, gMonth, gYear); 49 var raHours = paMacros.decimalDegreesToDegreeHours(raDeg); 50 var decDeg = paMacros.ecDec(sunEclipticLongitudeDeg, 0, 0, 0, 0, 0, gDay, gMonth, gYear); 51 52 var sunRAHour = paMacros.decimalHoursHour(raHours); 53 var sunRAMin = paMacros.decimalHoursMinute(raHours); 54 var sunRASec = paMacros.decimalHoursSecond(raHours); 55 var sunDecDeg = paMacros.decimalDegreesDegrees(decDeg); 56 var sunDecMin = paMacros.decimalDegreesMinutes(decDeg); 57 var sunDecSec = paMacros.decimalDegreesSeconds(decDeg); 58 59 return [sunRAHour, sunRAMin, sunRASec, sunDecDeg, sunDecMin, sunDecSec]; 60 } 61 62 /** 63 * Calculate distance to the Sun (in km), and angular size. 64 */ 65 function sunDistanceAndAngularSize(lctHours, lctMinutes, lctSeconds, localDay, localMonth, localYear, isDaylightSaving, zoneCorrection) { 66 var daylightSaving = (isDaylightSaving) ? 1 : 0; 67 68 var gDay = paMacros.localCivilTimeGreenwichDay(lctHours, lctMinutes, lctSeconds, daylightSaving, zoneCorrection, localDay, localMonth, localYear); 69 var gMonth = paMacros.localCivilTimeGreenwichMonth(lctHours, lctMinutes, lctSeconds, daylightSaving, zoneCorrection, localDay, localMonth, localYear); 70 var gYear = paMacros.localCivilTimeGreenwichYear(lctHours, lctMinutes, lctSeconds, daylightSaving, zoneCorrection, localDay, localMonth, localYear); 71 var trueAnomalyDeg = paMacros.sunTrueAnomaly(lctHours, lctMinutes, lctSeconds, daylightSaving, zoneCorrection, localDay, localMonth, localYear); 72 var trueAnomalyRad = paUtils.degreesToRadians(trueAnomalyDeg); 73 var eccentricity = paMacros.sunEcc(gDay, gMonth, gYear); 74 var f = (1 + eccentricity * Math.cos(trueAnomalyRad)) / (1 - eccentricity * eccentricity); 75 var rKm = 149598500 / f; 76 var thetaDeg = f * 0.533128; 77 78 var sunDistKm = paUtils.round(rKm, 0); 79 var sunAngSizeDeg = paMacros.decimalDegreesDegrees(thetaDeg); 80 var sunAngSizeMin = paMacros.decimalDegreesMinutes(thetaDeg); 81 var sunAngSizeSec = paMacros.decimalDegreesSeconds(thetaDeg); 82 83 return [sunDistKm, sunAngSizeDeg, sunAngSizeMin, sunAngSizeSec]; 84 } 85 86 /** 87 * Calculate local sunrise and sunset. 88 */ 89 function sunriseAndSunset(localDay, localMonth, localYear, isDaylightSaving, zoneCorrection, geographicalLongDeg, geographicalLatDeg) { 90 var daylightSaving = (isDaylightSaving) ? 1 : 0; 91 92 var localSunriseHours = paMacros.sunriseLCT(localDay, localMonth, localYear, daylightSaving, zoneCorrection, geographicalLongDeg, geographicalLatDeg); 93 var localSunsetHours = paMacros.sunsetLCT(localDay, localMonth, localYear, daylightSaving, zoneCorrection, geographicalLongDeg, geographicalLatDeg); 94 95 var sunRiseSetStatus = paMacros.eSunRS(localDay, localMonth, localYear, daylightSaving, zoneCorrection, geographicalLongDeg, geographicalLatDeg); 96 97 var adjustedSunriseHours = localSunriseHours + 0.008333; 98 var adjustedSunsetHours = localSunsetHours + 0.008333; 99 100 var azimuthOfSunriseDeg1 = paMacros.sunriseAZ(localDay, localMonth, localYear, daylightSaving, zoneCorrection, geographicalLongDeg, geographicalLatDeg); 101 var azimuthOfSunsetDeg1 = paMacros.sunsetAZ(localDay, localMonth, localYear, daylightSaving, zoneCorrection, geographicalLongDeg, geographicalLatDeg); 102 103 var localSunriseHour = (sunRiseSetStatus == paTypes.RiseSetCalcStatus.OK) ? paMacros.decimalHoursHour(adjustedSunriseHours) : 0; 104 var localSunriseMinute = (sunRiseSetStatus == paTypes.RiseSetCalcStatus.OK) ? paMacros.decimalHoursMinute(adjustedSunriseHours) : 0; 105 106 var localSunsetHour = (sunRiseSetStatus == paTypes.RiseSetCalcStatus.OK) ? paMacros.decimalHoursHour(adjustedSunsetHours) : 0; 107 var localSunsetMinute = (sunRiseSetStatus == paTypes.RiseSetCalcStatus.OK) ? paMacros.decimalHoursMinute(adjustedSunsetHours) : 0; 108 109 var azimuthOfSunriseDeg = (sunRiseSetStatus == paTypes.RiseSetCalcStatus.OK) ? paUtils.round(azimuthOfSunriseDeg1, 2) : 0; 110 var azimuthOfSunsetDeg = (sunRiseSetStatus == paTypes.RiseSetCalcStatus.OK) ? paUtils.round(azimuthOfSunsetDeg1, 2) : 0; 111 112 var status = sunRiseSetStatus; 113 114 return [localSunriseHour, localSunriseMinute, localSunsetHour, localSunsetMinute, azimuthOfSunriseDeg, azimuthOfSunsetDeg, status]; 115 } 116 117 /** 118 * Calculate times of morning and evening twilight. 119 */ 120 function morningAndEveningTwilight(localDay, localMonth, localYear, isDaylightSaving, zoneCorrection, geographicalLongDeg, geographicalLatDeg, twilightType) { 121 var daylightSaving = (isDaylightSaving) ? 1 : 0; 122 123 var startOfAMTwilightHours = paMacros.twilightAMLCT(localDay, localMonth, localYear, daylightSaving, zoneCorrection, geographicalLongDeg, geographicalLatDeg, twilightType); 124 125 var endOfPMTwilightHours = paMacros.twilightPMLCT(localDay, localMonth, localYear, daylightSaving, zoneCorrection, geographicalLongDeg, geographicalLatDeg, twilightType); 126 127 var twilightStatus = paMacros.eTwilight(localDay, localMonth, localYear, daylightSaving, zoneCorrection, geographicalLongDeg, geographicalLatDeg, twilightType); 128 129 var adjustedAMStartTime = startOfAMTwilightHours + 0.008333; 130 var adjustedPMStartTime = endOfPMTwilightHours + 0.008333; 131 132 var amTwilightBeginsHour = (twilightStatus == paTypes.TwilightStatus.OK) ? paMacros.decimalHoursHour(adjustedAMStartTime) : -99; 133 var amTwilightBeginsMin = (twilightStatus == paTypes.TwilightStatus.OK) ? paMacros.decimalHoursMinute(adjustedAMStartTime) : -99; 134 135 var pmTwilightEndsHour = (twilightStatus == paTypes.TwilightStatus.OK) ? paMacros.decimalHoursHour(adjustedPMStartTime) : -99; 136 var pmTwilightEndsMin = (twilightStatus == paTypes.TwilightStatus.OK) ? paMacros.decimalHoursMinute(adjustedPMStartTime) : -99; 137 138 var status = twilightStatus; 139 140 return [amTwilightBeginsHour, amTwilightBeginsMin, pmTwilightEndsHour, pmTwilightEndsMin, status]; 141 } 142 143 /** 144 * Calculate the equation of time. (The difference between the real Sun time and the mean Sun time.) 145 */ 146 function equationOfTime(gwdateDay, gwdateMonth, gwdateYear) { 147 var sunLongitudeDeg = paMacros.sunLong(12, 0, 0, 0, 0, gwdateDay, gwdateMonth, gwdateYear); 148 var sunRAHours = paMacros.decimalDegreesToDegreeHours(paMacros.ecRA(sunLongitudeDeg, 0, 0, 0, 0, 0, gwdateDay, gwdateMonth, gwdateYear)); 149 var equivalentUTHours = paMacros.greenwichSiderealTimeToUniversalTime(sunRAHours, 0, 0, gwdateDay, gwdateMonth, gwdateYear); 150 var equationOfTimeHours = equivalentUTHours - 12; 151 152 var equationOfTimeMin = paMacros.decimalHoursMinute(equationOfTimeHours); 153 var equationOfTimeSec = paMacros.decimalHoursSecond(equationOfTimeHours); 154 155 return [equationOfTimeMin, equationOfTimeSec]; 156 } 157 158 /** 159 * Calculate solar elongation for a celestial body. 160 * 161 * Solar elongation is the angle between the lines of sight from the Earth to the Sun and from the Earth to the celestial body. 162 */ 163 function solarElongation(raHour, raMin, raSec, decDeg, decMin, decSec, gwdateDay, gwdateMonth, gwdateYear) { 164 var sunLongitudeDeg = paMacros.sunLong(0, 0, 0, 0, 0, gwdateDay, gwdateMonth, gwdateYear); 165 var sunRAHours = paMacros.decimalDegreesToDegreeHours(paMacros.ecRA(sunLongitudeDeg, 0, 0, 0, 0, 0, gwdateDay, gwdateMonth, gwdateYear)); 166 var sunDecDeg = paMacros.ecDec(sunLongitudeDeg, 0, 0, 0, 0, 0, gwdateDay, gwdateMonth, gwdateYear); 167 var solarElongationDeg = paMacros.angle(sunRAHours, 0, 0, sunDecDeg, 0, 0, raHour, raMin, raSec, decDeg, decMin, decSec, paTypes.AngleMeasure.Hours); 168 169 return paUtils.round(solarElongationDeg, 2); 170 } 171 172 173 module.exports = { 174 approximatePositionOfSun, 175 precisePositionOfSun, 176 sunDistanceAndAngularSize, 177 sunriseAndSunset, 178 morningAndEveningTwilight, 179 equationOfTime, 180 solarElongation 181 };