1 const paMacros = require('./pa-macros.js');
  2 const paPlanetData = require('./data/pa-planetdata.js');
  3 const paUtils = require('./pa-utils.js');
  4 
  5 /**
  6  * Calculate approximate position of a planet.
  7  */
  8 function approximatePositionOfPlanet(lctHour, lctMin, lctSec, isDaylightSaving, zoneCorrectionHours, localDateDay, localDateMonth, localDateYear, planetName) {
  9     var daylightSaving = (isDaylightSaving) ? 1 : 0;
 10 
 11     var [planetInfo_name, planetInfo_tp_PeriodOrbit, planetInfo_long_LongitudeEpoch, planetInfo_peri_LongitudePerihelion, planetInfo_ecc_EccentricityOrbit, planetInfo_axis_AxisOrbit, planetInfo_incl_OrbitalInclination, planetInfo_node_LongitudeAscendingNode, planetInfo_theta0_AngularDiameter, planetInfo_v0_VisualMagnitude] = paPlanetData.getPlanetData(planetName);
 12 
 13     var gdateDay = paMacros.localCivilTimeGreenwichDay(lctHour, lctMin, lctSec, daylightSaving, zoneCorrectionHours, localDateDay, localDateMonth, localDateYear);
 14     var gdateMonth = paMacros.localCivilTimeGreenwichMonth(lctHour, lctMin, lctSec, daylightSaving, zoneCorrectionHours, localDateDay, localDateMonth, localDateYear);
 15     var gdateYear = paMacros.localCivilTimeGreenwichYear(lctHour, lctMin, lctSec, daylightSaving, zoneCorrectionHours, localDateDay, localDateMonth, localDateYear);
 16 
 17     var utHours = paMacros.localCivilTimeToUniversalTime(lctHour, lctMin, lctSec, daylightSaving, zoneCorrectionHours, localDateDay, localDateMonth, localDateYear);
 18     var dDays = paMacros.civilDateToJulianDate(gdateDay + (utHours / 24), gdateMonth, gdateYear) - paMacros.civilDateToJulianDate(0, 1, 2010);
 19     var npDeg1 = 360 * dDays / (365.242191 * Number(planetInfo_tp_PeriodOrbit));
 20     var npDeg2 = npDeg1 - 360 * Math.floor(npDeg1 / 360);
 21     var mpDeg = npDeg2 + Number(planetInfo_long_LongitudeEpoch) - Number(planetInfo_peri_LongitudePerihelion);
 22     var lpDeg1 = npDeg2 + (360 * Number(planetInfo_ecc_EccentricityOrbit) * Math.sin(paUtils.degreesToRadians(mpDeg)) / Math.PI) + Number(planetInfo_long_LongitudeEpoch);
 23     var lpDeg2 = lpDeg1 - 360 * Math.floor(lpDeg1 / 360);
 24     var planetTrueAnomalyDeg = lpDeg2 - Number(planetInfo_peri_LongitudePerihelion);
 25     var rAU = Number(planetInfo_axis_AxisOrbit) * (1 - Math.pow(Number(planetInfo_ecc_EccentricityOrbit), 2)) / (1 + Number(planetInfo_ecc_EccentricityOrbit) * Math.cos(paUtils.degreesToRadians(planetTrueAnomalyDeg)));
 26 
 27     var [earthInfo_name, earthInfo_tp_PeriodOrbit, earthInfo_long_LongitudeEpoch, earthInfo_peri_LongitudePerihelion, earthInfo_ecc_EccentricityOrbit, earthInfo_axis_AxisOrbit, earthInfo_incl_OrbitalInclination, earthInfo_node_LongitudeAscendingNode, earthInfo_theta0_AngularDiameter, earthInfo_v0_VisualMagnitude] = paPlanetData.getPlanetData(paPlanetData.planetNames.earth);
 28 
 29     var neDeg1 = 360 * dDays / (365.242191 * Number(earthInfo_tp_PeriodOrbit));
 30     var neDeg2 = neDeg1 - 360 * Math.floor(neDeg1 / 360);
 31     var meDeg = neDeg2 + Number(earthInfo_long_LongitudeEpoch) - Number(earthInfo_peri_LongitudePerihelion);
 32     var leDeg1 = neDeg2 + Number(earthInfo_long_LongitudeEpoch) + 360 * Number(earthInfo_ecc_EccentricityOrbit) * Math.sin(paUtils.degreesToRadians(meDeg)) / Math.PI;
 33     var leDeg2 = leDeg1 - 360 * Math.floor(leDeg1 / 360);
 34     var earthTrueAnomalyDeg = leDeg2 - Number(earthInfo_peri_LongitudePerihelion);
 35     var rAU2 = Number(earthInfo_axis_AxisOrbit) * (1 - Math.pow(Number(earthInfo_ecc_EccentricityOrbit), 2)) / (1 + Number(earthInfo_ecc_EccentricityOrbit) * Math.cos(paUtils.degreesToRadians(earthTrueAnomalyDeg)));
 36     var lpNodeRad = paUtils.degreesToRadians(lpDeg2 - Number(planetInfo_node_LongitudeAscendingNode));
 37     var psiRad = Math.asin(Math.sin(lpNodeRad) * Math.sin(paUtils.degreesToRadians(Number(planetInfo_incl_OrbitalInclination))));
 38     var y = Math.sin(lpNodeRad) * Math.cos(paUtils.degreesToRadians(Number(planetInfo_incl_OrbitalInclination)));
 39     var x = Math.cos(lpNodeRad);
 40     var ldDeg = paMacros.degrees(Math.atan2(y, x)) + Number(planetInfo_node_LongitudeAscendingNode);
 41     var rdAU = rAU * Math.cos(psiRad);
 42     var leLdRad = paUtils.degreesToRadians(leDeg2 - ldDeg);
 43     var atan2Type1 = Math.atan2((rdAU * Math.sin(leLdRad)), (rAU2 - rdAU * Math.cos(leLdRad)));
 44     var atan2Type2 = Math.atan2((rAU2 * Math.sin(-leLdRad)), (rdAU - rAU2 * Math.cos(leLdRad)));
 45     var aRad = (rdAU < 1) ? atan2Type1 : atan2Type2;
 46     var lamdaDeg1 = (rdAU < 1) ? 180 + leDeg2 + paMacros.degrees(aRad) : paMacros.degrees(aRad) + ldDeg;
 47     var lamdaDeg2 = lamdaDeg1 - 360 * Math.floor(lamdaDeg1 / 360);
 48     var betaDeg = paMacros.degrees(Math.atan(rdAU * Math.tan(psiRad) * Math.sin(paUtils.degreesToRadians(lamdaDeg2 - ldDeg)) / (rAU2 * Math.sin(-leLdRad))));
 49     var raHours = paMacros.decimalDegreesToDegreeHours(paMacros.ecRA(lamdaDeg2, 0, 0, betaDeg, 0, 0, gdateDay, gdateMonth, gdateYear));
 50     var decDeg = paMacros.ecDec(lamdaDeg2, 0, 0, betaDeg, 0, 0, gdateDay, gdateMonth, gdateYear);
 51 
 52     var planetRAHour = paMacros.decimalHoursHour(raHours);
 53     var planetRAMin = paMacros.decimalHoursMinute(raHours);
 54     var planetRASec = paMacros.decimalHoursSecond(raHours);
 55     var planetDecDeg = paMacros.decimalDegreesDegrees(decDeg);
 56     var planetDecMin = paMacros.decimalDegreesMinutes(decDeg);
 57     var planetDecSec = paMacros.decimalDegreesSeconds(decDeg);
 58 
 59     return [planetRAHour, planetRAMin, planetRASec, planetDecDeg, planetDecMin, planetDecSec];
 60 }
 61 
 62 /**
 63  * Calculate precise position of a planet.
 64  */
 65 function precisePositionOfPlanet(lctHour, lctMin, lctSec, isDaylightSaving, zoneCorrectionHours, localDateDay, localDateMonth, localDateYear, planetName) {
 66     var daylightSaving = (isDaylightSaving) ? 1 : 0;
 67 
 68     var [planetLongitude, planetLatitude, planetDistanceAU, planetHLong1, planetHLong2, planetHLat, planetRVect] = paMacros.planetCoordinates(lctHour, lctMin, lctSec, daylightSaving, zoneCorrectionHours, localDateDay, localDateMonth, localDateYear, planetName);
 69 
 70     var planetRAHours = paMacros.decimalDegreesToDegreeHours(paMacros.ecRA(planetLongitude, 0, 0, planetLatitude, 0, 0, localDateDay, localDateMonth, localDateYear));
 71     var planetDecDeg1 = paMacros.ecDec(planetLongitude, 0, 0, planetLatitude, 0, 0, localDateDay, localDateMonth, localDateYear);
 72 
 73     var planetRAHour = paMacros.decimalHoursHour(planetRAHours);
 74     var planetRAMin = paMacros.decimalHoursMinute(planetRAHours);
 75     var planetRASec = paMacros.decimalHoursSecond(planetRAHours);
 76     var planetDecDeg = paMacros.decimalDegreesDegrees(planetDecDeg1);
 77     var planetDecMin = paMacros.decimalDegreesMinutes(planetDecDeg1);
 78     var planetDecSec = paMacros.decimalDegreesSeconds(planetDecDeg1);
 79 
 80     return [planetRAHour, planetRAMin, planetRASec, planetDecDeg, planetDecMin, planetDecSec];
 81 }
 82 
 83 /**
 84  * Calculate several visual aspects of a planet.
 85  */
 86 function visualAspectsOfAPlanet(lctHour, lctMin, lctSec, isDaylightSaving, zoneCorrectionHours, localDateDay, localDateMonth, localDateYear, planetName) {
 87     var daylightSaving = (isDaylightSaving) ? 1 : 0;
 88 
 89     var greenwichDateDay = paMacros.localCivilTimeGreenwichDay(lctHour, lctMin, lctSec, daylightSaving, zoneCorrectionHours, localDateDay, localDateMonth, localDateYear);
 90     var greenwichDateMonth = paMacros.localCivilTimeGreenwichMonth(lctHour, lctMin, lctSec, daylightSaving, zoneCorrectionHours, localDateDay, localDateMonth, localDateYear);
 91     var greenwichDateYear = paMacros.localCivilTimeGreenwichYear(lctHour, lctMin, lctSec, daylightSaving, zoneCorrectionHours, localDateDay, localDateMonth, localDateYear);
 92 
 93     var [planetLongitude, planetLatitude, planetDistanceAU, planetHLong1, planetHLong2, planetHLat, planetRVect] = paMacros.planetCoordinates(lctHour, lctMin, lctSec, daylightSaving, zoneCorrectionHours, localDateDay, localDateMonth, localDateYear, planetName);
 94 
 95     var planetRARad = paUtils.degreesToRadians(paMacros.ecRA(planetLongitude, 0, 0, planetLatitude, 0, 0, localDateDay, localDateMonth, localDateYear));
 96     var planetDecRad = paUtils.degreesToRadians(paMacros.ecDec(planetLongitude, 0, 0, planetLatitude, 0, 0, localDateDay, localDateMonth, localDateYear));
 97 
 98     var lightTravelTimeHours = planetDistanceAU * 0.1386;
 99 
100     var [planet_name, tp_PeriodOrbit, long_LongitudeEpoch, peri_LongitudePerihelion, ecc_EccentricityOrbit, axis_AxisOrbit, incl_OrbitalInclination, node_LongitudeAscendingNode, theta0_AngularDiameter, v0_VisualMagnitude] = paPlanetData.getPlanetData(planetName);
101 
102     var angularDiameterArcsec = Number(theta0_AngularDiameter) / planetDistanceAU;
103     var phase1 = 0.5 * (1.0 + Math.cos(paUtils.degreesToRadians(planetLongitude - planetHLong1)));
104 
105     var sunEclLongDeg = paMacros.sunLong(lctHour, lctMin, lctSec, daylightSaving, zoneCorrectionHours, localDateDay, localDateMonth, localDateYear);
106     var sunRARad = paUtils.degreesToRadians(paMacros.ecRA(sunEclLongDeg, 0, 0, 0, 0, 0, greenwichDateDay, greenwichDateMonth, greenwichDateYear));
107     var sunDecRad = paUtils.degreesToRadians(paMacros.ecDec(sunEclLongDeg, 0, 0, 0, 0, 0, greenwichDateDay, greenwichDateMonth, greenwichDateYear));
108 
109     var y = Math.cos(sunDecRad) * Math.sin(sunRARad - planetRARad);
110     var x = Math.cos(planetDecRad) * Math.sin(sunDecRad) - Math.sin(planetDecRad) * Math.cos(sunDecRad) * Math.cos(sunRARad - planetRARad);
111 
112     var chiDeg = paMacros.degrees(Math.atan2(y, x));
113     var radiusVectorAU = planetRVect;
114     var approximateMagnitude1 = 5.0 * Math.log10(radiusVectorAU * planetDistanceAU / (Math.sqrt(phase1))) + Number(v0_VisualMagnitude);
115 
116     var distanceAU = paUtils.round(planetDistanceAU, 5);
117     var angDiaArcsec = paUtils.round(angularDiameterArcsec, 1);
118     var phase = paUtils.round(phase1, 2);
119     var lightTimeHour = paMacros.decimalHoursHour(lightTravelTimeHours);
120     var lightTimeMinutes = paMacros.decimalHoursMinute(lightTravelTimeHours);
121     var lightTimeSeconds = paMacros.decimalHoursSecond(lightTravelTimeHours);
122     var posAngleBrightLimbDeg = paUtils.round(chiDeg, 1);
123     var approximateMagnitude = paUtils.round(approximateMagnitude1, 1);
124 
125     return [distanceAU, angDiaArcsec, phase, lightTimeHour, lightTimeMinutes, lightTimeSeconds, posAngleBrightLimbDeg, approximateMagnitude];
126 }
127 
128 module.exports = {
129     approximatePositionOfPlanet,
130     precisePositionOfPlanet,
131     visualAspectsOfAPlanet
132 };