sublunar.almanac/js/old/astro.js

280 lines
9.8 KiB
JavaScript
Raw Normal View History

2018-12-09 13:02:46 +01:00
function findNewMoon( ts ) {
var today = new moment.unix(ts);
var year = parseFloat(today.format('YYYY'));
var ydays = 365;
var spd = 86400;
if (today.isLeapYear() ) ydays++;
var decimal = parseFloat(today.format('DDD')) / ydays * spd;
var secs = parseFloat(today.format('H')) * 3600 + parseFloat(today.format('m')) * 60 + parseFloat(today.format('s'));
decimal = (decimal + secs) / spd;
var Y = year + decimal;
// k is an integer for new moon incremented by 0.25 for first quarter 0.5 for new etc.
var k=Math.floor((parseFloat(today.format('YYYY'))+((parseFloat(today.format('M'))-1)+parseFloat(today.format('D'))/30)/12-2000)*12.3685);
// Time in Julian centuries since 2000.0
var T=k/1236.85;
// Sun's mean anomaly
var M=rev(2.5534+29.10535669*k-0.0000218*T*T);
// Moon's mean anomaly (M' in Meeus)
var MP=rev(201.5643+385.81693528*k+0.0107438*T*T+0.00001239*T*T*T-0.00000011*T*T*T);
var E=1-0.002516*T-0.0000074*T*T;
// Moons argument of latitude
var F=rev(160.7108+390.67050274*k-0.0016341*T*T-0.00000227*T*T*T+0.000000011*T*T*T*T);
// Longitude of ascending node of lunar orbit
var Omega=rev(124.7746-1.56375580*k+0.0020691*T*T+0.00000215*T*T*T);
// The full planetary arguments include 14 terms, only used the 7 most significant
var B = new Array();
B[1]=rev(299.77+ 0.107408*k-0.009173*T*T);
B[2]=rev(251.88+ 0.016321*k);
B[3]=rev(251.83+26.651886*k);
B[4]=rev(349.42+36.412478*k);
B[5]=rev( 84.88+18.206239*k);
B[6]=rev(141.74+53.303771*k);
B[7]=rev(207.14+ 2.453732*k);
// New moon
var JDE0=2451550.09765+29.530588853*k+0.0001337*T*T-0.000000150*T*T*T+0.00000000073*T*T*T*T;
// Correct for TDT since 1 July 2015
JDE0=JDE0-58.184/(24*60*60);
var JDE=JDE0 -0.40720*sind(MP) +0.17241*E*sind(M) +0.01608*sind(2*MP) +0.01039*sind(2*F)
+0.00739*E*sind(MP-M) -0.00514*E*sind(MP+M) +0.00208*E*E*sind(2*M) -0.00111*sind(MP-2*F)
-0.00057*sind(MP+2*F) +0.00056*E*sind(2*MP+M) -0.00042*sind(3*MP) +0.00042*E*sind(M+2*F)
+0.00038*E*sind(M-2*F) -0.00024*E*sind(2*MP-M) -0.00017*sind(Omega) -0.00007*sind(MP+2*M);
var F=0.000325*sind(B[1])+0.000165*sind(B[2])+0.000164*sind(B[3])+0.000126*sind(B[4])
+0.000110*sind(B[5])+0.000062*sind(B[6])+0.000060*sind(B[7]);
var newmoon = new moment(A.JulianDay.jdToDate(JDE + F)).subtract(2, 'h').unix();
if ( ts < newmoon ) newmoon = findNewMoon( new moment.unix(ts).subtract(1, 'h').unix());
return newmoon;
} //End calcMoonPhase
function getZodiac(deg, sidereal = false) {
if ( sidereal == true ) {
deg += 27.74;
if ( deg > 360 ) deg =- 360;
}
var obj = {
sign: Math.ceil(deg / 30),
decan: Math.ceil(deg / 10)
}
return obj;
}
function getLunarMansion(deg, sidereal = false) {
// global variable def needs to be declared before using this function
if (!sidereal) var mansion = def.moon.mansion.tropical;
else var mansion = def.moon.mansion.constellational;
var i = 1;
var m;
while ( deg > zodToDeg(mansion[i]) ) i++;
return i;
}
function sunRiseSet(ts, coord) {
// calculate sunrise and sunset
var today = new moment.unix(ts).startOf('d');
var tomorrow = new moment.unix(ts).startOf('d').add(1, 'd');
//var todaySolarSecs = A.Solar.times(new A.JulianDay(today.toDate()), coord);
//var tomorrowSolarSecs = A.Solar.times(new A.JulianDay(tomorrow.toDate()), coord);
// fixed MeeusJS bug with working Peter Hayes code
var todayHayes = SunRiseSet(parseFloat(today.format('YYYY')),parseFloat(today.format('M')),parseFloat(today.format('D')),parseFloat($('#lat').val()),parseFloat($('#lon').val()));
var tomorrowHayes = SunRiseSet(parseFloat(tomorrow.format('YYYY')),parseFloat(tomorrow.format('M')),parseFloat(tomorrow.format('D')),parseFloat($('#lat').val()),parseFloat($('#lon').val()));
var todaySolarSecs = {};
var tomorrowSolarSecs = {};
todaySolarSecs.rise = todayHayes[0] * 3600;
todaySolarSecs.set = todayHayes[1] * 3600;
tomorrowSolarSecs.rise = tomorrowHayes[0] * 3600;
tomorrowSolarSecs.set = tomorrowHayes[1] * 3600;
// end bugfix
var todayPlanetDayStart = new moment.unix(ts).startOf('day').unix() + todaySolarSecs.rise;
var todayPlanetNightStart = new moment.unix(ts).startOf('day').unix() + todaySolarSecs.set;
var tomorrowPlanetDayStart = new moment.unix(ts).add(1, 'd').startOf('day').unix() + tomorrowSolarSecs.rise;
var tomorrowPlanetNightStart = new moment.unix(ts).add(1, 'd').startOf('day').unix() + tomorrowSolarSecs.set;
var planetaryDayHourSecs = (todayPlanetNightStart - todayPlanetDayStart) / 12;
var planetaryNightHourSecs = (tomorrowPlanetDayStart - todayPlanetNightStart) / 12;
var sol = {
day : {
start : Math.floor(todayPlanetDayStart),
hourSecs : Math.round(planetaryDayHourSecs),
end : Math.floor(todayPlanetNightStart - 1)
},
night : {
start: Math.floor(todayPlanetNightStart),
hourSecs : Math.round(planetaryNightHourSecs),
end : Math.floor(tomorrowPlanetDayStart - 1)
}
}
return sol;
}
function planetaryMoment(lat, lon, ts) {
var sidereal = false;
var coord = A.EclCoord.fromWgs84(lat, lon, 0);
var today = new moment.unix(ts);
var tomorrow = new moment.unix(ts).add(1, 'd');
var yesterday = new moment.unix(ts).subtract(1, 'd');
var date = today.toDate();
var jdo = new A.JulianDay(date);
var suneq = A.Solar.apparentEquatorial(jdo);
var mooneq = A.Moon.apparentEquatorial(jdo);
var suntp = A.Solar.topocentricPosition(jdo, coord, true);
var moontp = A.Moon.topocentricPosition(jdo, coord, true);
var obliquity = A.Nutation.trueObliquity(jdo) * 180 / Math.PI;
// get sun rise and set times
var sol = sunRiseSet(ts, coord);
var ps = sol;
// calculate planetary hour of ts and when it starts and ends
var phour = 0;
var phstart;
var phend;
if ( ts >= ps.day.start && ts < ps.night.start ) {
phour = (ts - ps.day.start) / ps.day.hourSecs;
phstart = ps.day.start + phour * ps.day.hourSecs;
phend = phstart + ps.day.hourSecs - 1;
}
else {
if ( ts < ps.day.start ) {
ps = sunRiseSet(yesterday.unix(), coord);
}
phour = (ts - ps.night.start) / ps.night.hourSecs + 12;
phstart = ps.night.start + (phour - 12) * ps.night.hourSecs;
phend = phstart + ps.night.hourSecs - 1;
}
// calculate planetary day of ts
var pday = parseFloat(new moment.unix(ps.day.start).format('d'));
// planet longitudes
var pldate = {
year: parseFloat(today.format('YYYY')),
month: parseFloat(today.format('M')),
day: parseFloat(today.format('D')),
hours: parseFloat(today.format('H')),
minutes: parseFloat(today.format('m')),
seconds: 0};
$const.tlong = lon // longitude
$const.tlat = lat // latitude
$processor.init ();
var mars = $moshier.body.mars;
var mercury = $moshier.body.mercury;
var jupiter = $moshier.body.jupiter;
var venus = $moshier.body.venus;
var saturn = $moshier.body.saturn;
$processor.calc (pldate, mars);
$processor.calc (pldate, mercury);
$processor.calc (pldate, jupiter);
$processor.calc (pldate, venus);
$processor.calc (pldate, saturn);
// calculate lunar day
var lastNewMoon = findNewMoon(ts);
var nextNewMoon = findNewMoon(new moment.unix(lastNewMoon).add(31, 'd').unix());
var startDate = new moment.unix(lastNewMoon).startOf('d');
var endDate = new moment.unix(nextNewMoon).startOf('d');
var cal = [];
cal[0] = lastNewMoon;
var daycount = 0;
var rise = lastNewMoon + 1;
while ( rise < nextNewMoon && rise < ts ) {
var day = new moment(startDate.toDate()).add(daycount, 'd');
var jdr = new A.JulianDay(day.toDate());
var moontimes = A.Moon.times(jdr, coord);
var hrs = MoonRise(parseFloat(day.format('YYYY')),parseFloat(day.format('M')),parseFloat(day.format('D')),0,parseFloat(lat),parseFloat(lon));
if ( hrs[0] > 0 ) {
var mt = hrs[0] * 60 * 60;
var rise = day.add(mt, 's').unix();
if ( rise > lastNewMoon && rise < nextNewMoon ) {
cal.push(rise);
}
}
daycount++;
}
var lday = 0;
cal.forEach(function(lts, i, o) {
if ( ts >= lts ) {
lday = i;
}
});
var luna = {
day: lday + 1,
start: cal[lday]
}
var suncoords = eqToEclDeg(suneq, obliquity);
var sunlng = suncoords.lng;
var mooncoords = eqToEclDeg(mooneq.eq, obliquity);
var moonlng = mooncoords.lng;
// calculate lunar phase
var i = A.MoonIllum.phaseAngleEq2(moontp.eq, suntp.eq);
var k = A.MoonIllum.illuminated(i);
var chi = A.MoonIllum.positionAngle(moontp.eq, suntp.eq);
var angle = i * 180 / Math.PI;
if ( chi < 0 ) angle = 360 - angle;
var sphase;
if ( angle < 10 ) sphase = 5;
else if ( angle < 80 ) sphase = 6;
else if ( angle < 95 ) sphase = 7;
else if ( angle < 170 ) sphase = 8;
else if ( angle < 190 ) sphase = 1;
else if ( angle < 260 ) sphase = 2;
else if ( angle < 280 ) sphase = 3;
else if ( angle < 350 ) sphase = 4;
else sphase = 5;
var phase = {
simple: sphase,
phase: angle,
angle: chi,
illumination : Math.round(k * 100)
}
var obj = {
ts: ts,
planetary : {
hour : {
number: Math.round(phour),
begin : phstart,
end : phend
},
day : pday
},
solar : {
day : sol,
lng : Math.round(sunlng * 100) / 100
},
lunar : {
day : luna,
lng : Math.round(moonlng * 100) / 100,
phase : phase,
lastnew : lastNewMoon
},
planet : {
mars : {
lng : Math.round(mars.position.apparentLongitude * 100) / 100
},
mercury : {
lng : Math.round(mercury.position.apparentLongitude * 100) / 100
},
jupiter : {
lng : Math.round(jupiter.position.apparentLongitude * 100) / 100
},
venus : {
lng : Math.round(venus.position.apparentLongitude * 100) / 100
},
saturn : {
lng : Math.round(saturn.position.apparentLongitude * 100) / 100
}
}
}
return obj;
}