279 lines
9.8 KiB
JavaScript
279 lines
9.8 KiB
JavaScript
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;
|
|
}
|