1/* 2Copyright 2012 Alex Greenland 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17//*************************************************** 18//the following scripts are used by andi boesch 2008 19//as basic algorithms in the astro tools: 20//http://www.cybervisuals.ch/astro 21//*************************************************** 22 23;var AGPLANETS = function() { 24 'usde strict'; 25 26 function sunxyz(jday) { 27 // return x,y,z ecliptic coordinates, distance, true longitude 28 // days counted from 1999 Dec 31.0 UT 29 var d = jday - 2451543.5; 30 var w = 282.9404 + 4.70935E-5 * d; 31 // argument of perihelion 32 var e = 0.016709 - 1.151E-9 * d; 33 var M = rev(356.0470 + 0.9856002585 * d); 34 // mean anomaly 35 var E = M + e * RAD2DEG * sind(M) * (1.0 + e * cosd(M)); 36 var xv = cosd(E) - e; 37 var yv = Math.sqrt(1.0 - e * e) * sind(E); 38 var v = atan2d(yv, xv); 39 // true anomaly 40 var r = Math.sqrt(xv * xv + yv * yv); 41 // distance 42 var lonsun = rev(v + w); 43 // true longitude 44 var xs = r * cosd(lonsun); 45 // rectangular coordinates, zs = 0 for sun 46 var ys = r * sind(lonsun); 47 return new Array(xs, ys, 0, r, lonsun, 0); 48 } 49 50 function SunAlt(jday, obs) { 51 // return alt, az, time angle, ra, dec, ecl. long. and lat=0, illum=1, 0, 52 // dist, brightness 53 var sdat = sunxyz(jday); 54 var ecl = 23.4393 - 3.563E-7 * (jday - 2451543.5); 55 var xe = sdat[0]; 56 var ye = sdat[1] * cosd(ecl); 57 var ze = sdat[1] * sind(ecl); 58 var ra = rev(atan2d(ye, xe)); 59 var dec = atan2d(ze, Math.sqrt(xe * xe + ye * ye)); 60 var topo = radec2aa(ra, dec, jday, obs); 61 return new Array(topo[0], topo[1], topo[2], ra, dec, sdat[4], 0, 1, 0, 62 sdat[3], -26.74); 63 } 64 65 // Sun rise and set times (if twilight==-0.833) or desired twilight time. Return 66 // julian days 67 function sunrise(obs, twilight) { 68 // obs is a reference variable make a copy 69 var obscopy = new Object(); 70 for ( var i in obs) { 71 obscopy[i] = obs[i]; 72 } 73 obscopy.hours = 12; 74 obscopy.minutes = 0; 75 obscopy.seconds = 0; 76 var riseset = new Array(0.0, 0.0, false, 0.0, 0.0); 77 var lst = local_sidereal(obscopy); 78 var jday = jd(obscopy); 79 var radec = SunAlt(jday, obscopy); 80 var ra = radec[3]; 81 var dec = radec[4]; 82 var UTsun = 12.0 + ra / 15.0 - lst; 83 if (UTsun < 0.0) { 84 UTsun += 24.0; 85 } 86 if (UTsun > 24.0) { 87 UTsun -= 24.0; 88 } 89 var cosLHA = (sind(twilight) - sind(obs.latitude) * sind(dec)) 90 / (cosd(obs.latitude) * cosd(dec)); 91 // Check for midnight sun and midday night. "riseset[2]" false if no rise 92 // and set found 93 riseset[2] = false; 94 if (cosLHA <= 1.0 && cosLHA >= -1.0) { 95 // rise/set times allowing for not today. 96 riseset[2] = true; 97 var lha = acosd(cosLHA) / 15.0; 98 if ((UTsun - lha) < 0.0) { 99 var rtime = 24.0 + UTsun - lha; 100 } else { 101 var rtime = UTsun - lha; 102 } 103 riseset[0] = jday + rtime / 24.0 - 0.5; 104 if ((UTsun + lha) > 24.0) { 105 var stime = UTsun + lha - 24.0; 106 } else { 107 var stime = UTsun + lha; 108 riseset[4] = stime; 109 } 110 riseset[1] = jday + stime / 24.0 - 0.5; 111 // riseset[3] and [4] are times in UT hours 112 riseset[3] = rtime; 113 riseset[4] = stime; 114 } 115 return (riseset); 116 } 117 118 function MoonPos(jday, obs) { 119 // MoonPos calculates the Moon position and distance, based on Meeus chapter 120 // 47 121 // and the illuminated percentage from Meeus equations 48.4 and 48.1 122 // OPN: This version of MoonPos calculates the position to a precision of 123 // about 2' or so 124 // All T^2, T^3 and T^4 terms skipped. NB: Time is not taken from obs but 125 // from jday (julian day) 126 // Returns alt, az, hour angle, ra, dec (geocentr!), eclip. long and lat 127 // (geocentr!), 128 // illumination, distance, brightness and phase angle 129 var T = (jday - 2451545.0) / 36525; 130 // Moons mean longitude L' 131 var LP = rev(218.3164477 + 481267.88123421 * T); 132 // Moons mean elongation 133 var D = rev(297.8501921 + 445267.1114034 * T); 134 // Suns mean anomaly 135 var M = rev(357.5291092 + 35999.0502909 * T); 136 // Moons mean anomaly M' 137 var MP = rev(134.9633964 + 477198.8675055 * T); 138 // Moons argument of latitude 139 var F = rev(93.2720950 + 483202.0175233 * T); 140 // The "further arguments" A1, A2 and A3 and the term E have been ignored 141 // Sum of most significant terms from table 45.A and 45.B (terms less than 142 // 0.004 deg / 40 km dropped) 143 var Sl = 6288774 * sind(MP) + 1274027 * sind(2 * D - MP) + 658314 144 * sind(2 * D) + 213618 * sind(2 * MP) - 185116 * sind(M) - 114332 145 * sind(2 * F) + 58793 * sind(2 * D - 2 * MP) + 57066 146 * sind(2 * D - M - MP) + 53322 * sind(2 * D + MP) + 45758 147 * sind(2 * D - M) - 40923 * sind(M - MP) - 34720 * sind(D) - 30383 148 * sind(M + MP) + 15327 * sind(2 * D - 2 * F) - 12528 149 * sind(MP + 2 * F) + 10980 * sind(MP - 2 * F) + 10675 150 * sind(4 * D - MP) + 10034 * sind(3 * MP) + 8548 151 * sind(4 * D - 2 * MP) - 7888 * sind(2 * D + M - MP) - 6766 152 * sind(2 * D + M) - 5163 * sind(D - MP) + 4987 * sind(D + M) + 4036 153 * sind(2 * D - M + MP); 154 var Sb = 5128122 * sind(F) + 280602 * sind(MP + F) + 277602 * sind(MP - F) 155 + 173237 * sind(2 * D - F) + 55413 * sind(2 * D - MP + F) + 46271 156 * sind(2 * D - MP - F) + 32573 * sind(2 * D + F) + 17198 157 * sind(2 * MP + F) + 9266 * sind(2 * D + MP - F) + 8822 158 * sind(2 * MP - F) + 8216 * sind(2 * D - M - F) + 4324 159 * sind(2 * D - 2 * MP - F) + 4200 * sind(2 * D + MP + F); 160 var Sr = (-20905355) * cosd(MP) - 3699111 * cosd(2 * D - MP) - 2955968 161 * cosd(2 * D) - 569925 * cosd(2 * MP) + 246158 162 * cosd(2 * D - 2 * MP) - 152138 * cosd(2 * D - M - MP) - 170733 163 * cosd(2 * D + MP) - 204586 * cosd(2 * D - M) - 129620 164 * cosd(M - MP) + 108743 * cosd(D) + 104755 * cosd(M + MP) + 79661 165 * cosd(MP - 2 * F) + 48888 * cosd(M); 166 // geocentric longitude, latitude 167 var mglong = rev(LP + Sl / 1000000.0); 168 var mglat = Sb / 1000000.0; 169 // Obliquity of Ecliptic 170 var obl = 23.4393 - 3.563E-7 * (jday - 2451543.5); 171 var ra = rev(atan2d(sind(mglong) * cosd(obl) - tand(mglat) * sind(obl),
172 cosd(mglong))); 173 var dec = asind(sind(mglat) * cosd(obl) + cosd(mglat) * sind(obl) 174 * sind(mglong)); 175 176 var moondat = radec2aa(ra, dec, jday, obs); 177 // phase angle (48.4) 178 var pa = Math.abs(180.0 - D - 6.289 * sind(MP) + 2.100 * sind(M) - 1.274 179 * sind(2 * D - MP) - 0.658 * sind(2 * D) - 0.214 * sind(2 * MP) 180 - 0.11 * sind(D)); 181 var k = (1 + cosd(pa)) / 2; 182 var mr = Math.round(385000.56 + Sr / 1000.0); 183 var h = moondat[0]; 184 // correct for parallax, equatorial horizontal parallax, see Meeus p. 337 185 h -= asind(6378.14 / mr) * cosd(h); 186 // brightness, use Paul Schlyter's formula (based on common phase law for 187 // Moon) 188 var sdat = sunxyz(jday); 189 var r = sdat[3]; 190 // Earth (= Moon) distance to Sun in AU 191 var R = mr / 149598000; 192 // Moon distance to Earth in AU 193 var mag = 0.23 + 5 * log10(r * R) + 0.026 * pa + 4.0E-9 * pa * pa * pa * pa; 194 return new Array(h, moondat[1], moondat[2], ra, dec, mglong, mglat, k, r, 195 mr, mag); 196 } 197 198 function radec2aa(ra, dec, jday, obs) { 199 // Convert ra/dec to alt/az, also return hour angle, azimut = 0 when north 200 // DOES NOT correct for parallax! 201 // TH0=Greenwich sid. time (eq. 12.4), H=hour angle (chapter 13) 202 var TH0 = 280.46061837 + 360.98564736629 * (jday - 2451545.0); 203 var H = rev(TH0 - obs.longitude - ra); 204 var alt = asind(sind(obs.latitude) * sind(dec) + cosd(obs.latitude) 205 * cosd(dec) * cosd(H)); 206 var az = atan2d(sind(H), (cosd(H) * sind(obs.latitude) - tand(dec) 207 * cosd(obs.latitude))); 208 return new Array(alt, rev(az + 180.0), H); 209 } 210 211 function place(name, latitude, ns, longitude, we, zone, dss, dse) { 212 this.name = name; 213 this.latitude = latitude; 214 this.ns = ns; 215 this.longitude = longitude; 216 this.we = we; 217 this.zone = zone; 218 this.dss = dss; 219 this.dse = dse; 220 } 221 222 // A selection of places 223 // Please leave Greenwich in the first entry as the default 224 // The second entry is my home town, I suggest you change it to yours 225 // is you keep a copy for your personal use. 226 // This database is based on Peter Hayes' original database with several places 227 // added 228 var atlas = new Array(new place("UK:Greenwich", "51:28:38", 0, "00:00:00", 0, 229 0, "3:5:0", "10:5:0"), new place("NL:Rijswijk", "52:02:00", 0, 230 "4:19:00", 1, -60, "3:5:0", "10:5:0"), new place("AT:Vienna", 231 "48:13:00", 0, "16:22:00", 1, -60, "3:5:0", "10:5:0"), 232 new place("AU:Melbourne", "37:48:00", 1, "144:58:00", 1, -600, 233 "10:5:0", "03:5:0"), new place("AU:Perth", "31:58:00", 1, 234 "115:49:00", 1, -480, "10:5:0", "03:5:0"), new place( 235 "BE:Brussels", "50:50:00", 0, "4:21:00", 1, -60, "3:5:0", 236 "10:5:0"), new place("BR:Rio de Janeiro", "22:54:00", 1, 237 "43:16:00", 0, 180, "", ""), new place("CA:Calgary", 238 "51:03:00", 0, "114:05:00", 0, 420, "04:1:0", "10:5:0"), 239 new place("CA:Halifax", "44:35:00", 0, "63:39:00", 0, 240, "04:1:0", 240 "10:5:0"), new place("CA:Toronto", "43:39:00", 0, "79:23:00", 241 0, 300, "04:1:0", "10:5:0"), new place("CH:Zurich", "47:22:40", 242 0, "08:33:04", 1, -60, "3:5:0", "10:5:0"), new place( 243 "CL:Santiago", "33:30:00", 1, "70:40:00", 0, 240, "10:5:0", 244 "03:5:0"), new place("DE:Berlin", "52:32:00", 0, "13:25:00", 1, 245 -60, "3:5:0", "10:5:0"), new place("DE:Frankfurt/Main", 246 "50:06:00", 0, "8:41:00", 1, -60, "3:5:0", "10:5:0"), 247 new place("DE:Hamburg", "53:33:00", 0, "10:00:00", 1, -60, "3:5:0", 248 "10:5:0"), new place("DE:Munich", "48:08:00", 0, "11:35:00", 1, 249 -60, "3:5:0", "10:5:0"), new place("DK:Copenhagen", "55:43:00", 250 0, "12:34:00", 1, -60, "3:5:0", "10:5:0"), new place( 251 "DK:Kolding", "55:31:00", 0, "9:29:00", 1, -60, "3:5:0", 252 "10:5:0"), new place("DK:Aalborg", "57:03:00", 0, "9:51:00", 1, 253 -60, "3:5:0", "10:5:0"), new place("DK:Ãâ¦rhus", "56:10:00", 0, 254 "10:13:00", 1, -60, "3:5:0", "10:5:0"), new place("EG:Cairo", 255 "30:03:00", 0, "31:15:00", 1, -120, "", ""), new place( 256 "ES:Madrid", "40:25:00", 0, "03:42:00", 0, -60, "3:5:0", 257 "10:5:0"), new place("ES:Malaga", "36:43:00", 0, "04:25:00", 0, 258 -60, "3:5:0", "10:5:0"), new place("ES:Las Palmas", "28:08:00", 259 0, "15:27:00", 0, 60, "3:5:0", "10:5:0"), new place( 260 "FI:Helsinki", "60:08:00", 0, "25:00:00", 1, -120, "3:5:0", 261 "10:5:0"), new place("FR:Bordeaux", "44:50:00", 0, "0:34:00", 262 0, -60, "3:5:0", "10:5:0"), new place("FR:Brest", "48:24:00", 263 0, "4:30:00", 0, -60, "3:5:0", "10:5:0"), new place("FR:Lille", 264 "50:38:00", 0, "03:04:00", 1, -60, "3:5:0", "10:5:0"), 265 new place("FR:Lyon", "45:46:00", 0, "04:50:00", 1, -60, "3:5:0", 266 "10:5:0"), new place("FR:Marseille", "43:18:00", 0, "5:22:00", 267 1, -60, "3:5:0", "10:5:0"), new place("FR:Paris", "48:48:00", 268 0, "02:14:00", 1, -60, "3:5:0", "10:5:0"), new place( 269 "FR:Puimichel", "43:58:00", 0, "06:01:00", 1, -60, "3:5:0", 270 "10:5:0"), new place("FR:Strasbourg", "48:35:00", 0, "7:45:00", 271 1, -60, "3:5:0", "10:5:0"), new place("GL:Nuuk", "64:15:00", 0, 272 "51:34:00", 0, 180, "3:5:0", "10:5:0"), new place("GR:Athens", 273 "38:00:00", 0, "23:44:00", 1, -120, "3:5:0", "10:5:0"), 274 new place("HK:Hong Kong", "22:15:00", 0, "114:11:00", 1, -480, "", ""), 275 new place("HR:Zagreb", "45:48:00", 0, "15:58:00", 1, -60, "3:5:0", 276 "10:5:0"), new place("IE:Dublin", "53:19:48", 0, "06:15:00", 0, 277 0, "3:5:0", "10:5:0"), new place("IN:New Delhi", "28:22:00", 0, 278 "77:13:00", 1, -330, "", ""), new place("IQ:Baghdad", 279 "33:20:00", 0, "44:26:00", 1, -180, "", ""), new place( 280 "IR:Teheran", "35:44:00", 0, "51:30:00", 1, -210, "", ""), 281 new place("IS:Reykjavik", "64:09:00", 0, "21:58:00", 0, 60, "3:5:0", 282 "10:5:0"), new place("IT:Milan", "45:28:00", 0, "9:12:00", 1, 283 -60, "3:5:0", "10:5:0"), new place("IT:Palermo", "38:08:00", 0, 284 "13:23:00", 1, -60, "3:5:0", "10:5:0"), new place("IT:Rome", 285 "41:53:00", 0, "12:30:00", 1, -60, "3:5:0", "10:5:0"), 286 new place("JP:Tokyo", "35:70:00", 0, "139:46:00", 1, -540, "3:5:0", 287 "10:5:0"), new place("LU:Luxembourg", "49:36:00", 0, "6:09:00", 288 1, -60, "3:5:0", "10:5:0"), new place("NL:Amsterdam", 289 "52:22:23", 0, "4:53:33", 1, -60, "3:5:0", "10:5:0"), 290 new place("NL:Apeldoorn", "52:13:00", 0, "5:57:00", 1, -60, "3:5:0", 291 "10:5:0"), new place("NL:Maastricht", "50:51:00", 0, "5:04:00", 292 1, -60, "3:5:0", "10:5:0"), new place("NL:Groningen", 293 "53:13:00", 0, "6:33:00", 1, -60, "3:5:0", "10:5:0"), 294 new place("NL:The Hague", "52:05:00", 0, "4:29:00", 1, -60, "3:5:0", 295 "10:5:0"), new place("NL:Utrecht", "52:05:10", 0, "05:07:45", 296 1, -60, "3:5:0", "10:5:0"), new place("NO:Bergen", "60:21:00", 297 0, "5:20:00", 1, -60, "3:5:0", "10:5:0"), new place("NO:Oslo", 298 "59:56:00", 0, "10:45:00", 1, -60, "3:5:0", "10:5:0"), 299 new place("NO:Tromsø", "69:70:00", 0, "19:00:00", 1, -60, "3:5:0", 300 "10:5:0"), new place("NZ:Wellington", "41:17:00", 1, 301 "174:47:00", 1, -720, "10:5:0", "03:5:0"), new place( 302 "PL:Warszawa", "52:15:00", 0, "21:00:00", 1, -60, "3:5:0", 303 "10:5:0"), new place("PT:Faro", "37:01:00", 0, "7:56:00", 0, 0, 304 "3:5:0", "10:5:0"), new place("PT:Lisbon", "38:44:00", 0, 305 "9:08:00", 0, 0, "3:5:0", "10:5:0"), new place("PR:San Juan", 306 "18:28:00", 0, "66:08:00", 0, 240, "04:1:0", "10:5:0"), 307 new place("RO:Bucharest", "44:25:00", 0, "26:07:00", 1, -120, "3:5:0", 308 "10:5:0"), new place("RU:Irkutsk", "52:18:00", 0, "104:15:00", 309 1, -480, "3:5:0", "10:5:0"), new place("RU:Moscow", "55:45:00", 310 0, "37:35:00", 1, -180, "3:5:0", "10:5:0"), new place( 311 "RU:Omsk", "55:00:00", 0, "73:22:00", 1, -360, "3:5:0", 312 "10:5:0"), new place("SE:Gothenburg", "57:43:00", 0, 313 "11:58:00", 1, -60, "3:5:0", "10:5:0"), new place( 314 "SE:Stockholm", "59:35:00", 0, "18:06:00", 1, -60, "3:5:0", 315 "10:5:0"), new place("SE:LuleÃÂ¥", "65:35:00", 0, "22:09:00", 1, 316 -60, "3:5:0", "10:5:0"), new place("SG:Singapore", "01:20:00", 317 0, "103:50:00", 1, -450, "", ""), new place("VC:Kingstown", 318 "13:15:00", 0, "61:12:00", 0, 240, "", ""), new place( 319 "UK:Birmingham", "52:30:00", 0, "01:49:48", 0, 0, "3:5:0", 320 "10:5:0"), new place("UK:Belfast", "54:34:48", 0, "05:55:12", 321 0, 0, "3:5:0", "10:5:0"), new place("UK:Cambridge", "52:10:00", 322 0, "00:06:00", 0, 0, "3:5:0", "10:5:0"), new place( 323 "UK:Cardiff", "51:30:00", 0, "03:12:00", 0, 0, "3:5:0", 324 "10:5:0"), new place("UK:Edinburgh", "55:55:48", 0, "03:13:48", 325 0, 0, "3:5:0", "10:5:0"), new place("UK:London", "51:30:00", 0, 326 "00:10:12", 0, 0, "3:5:0", "10:5:0"), new place("US:Anchorage", 327 "61:10:00", 0, "149:53:00", 0, 560, "04:1:0", "10:5:0"), 328 new place("US:Dallas", "32:48:00", 0, "96:48:00", 0, 360, "04:1:0", 329 "10:5:0"), new place("US:Denver", "39:45:00", 0, "104:59:00", 330 0, 420, "04:1:0", "10:5:0"), new place("US:Honolulu", 331 "21:19:00", 0, "157:86:00", 0, 600, "04:1:0", "10:5:0"), 332 new place("US:Los Angeles", "34:03:15", 0, "118:14:28", 0, 480, 333 "04:1:0", "10:5:0"), new place("US:Miami", "25:47:00", 0, 334 "80:20:00", 0, 300, "04:1:0", "10:5:0"), new place( 335 "US:Minneapolis", "44:58:01", 0, "93:15:00", 0, 360, "04:1:0", 336 "10:5:0"), new place("US:Seattle", "47:36:00", 0, "122:19:00", 337 0, 480, "04:1:0", "10:5:0"), new place("US:Washington DC", 338 "38:53:51", 0, "77:00:33", 0, 300, "04:1:0", "10:5:0"), 339 new place("VC:St Vincent", "13:15:00", 0, "61:12:00", 0, 240, "", ""), 340 new place("ZA:Cape Town", "33:56:00", 1, "18:28:00", 1, -120, "", ""), 341 new place("ZM:Lusaka", "15:26:00", 1, "28:20:00", 1, -120, "", "")); 342 343 function observatory(place, year, month, day, hr, min, sec) { 344 // The observatory object holds local date and time, 345 // timezone correction in minutes with daylight saving if applicable, 346 // latitude and longitude (west is positive) 347 this.name = place.name;
348 this.year = year; 349 this.month = month; 350 this.day = day; 351 this.hours = hr; 352 this.minutes = min; 353 this.seconds = sec; 354 this.tz = place.tz; 355 this.dst = false; 356 // is it DST? 357 this.latitude = place.latitude; 358 this.longitude = place.longitude; 359 } 360 // The default observatory (Greenwich noon Jan 1 2000) 361 // changed by user setting place and time from menu 362 var observer = new observatory(atlas[0], 2000, 1, 1, 12, 0, 0); 363 // Site name returns name and latitude / longitude as a string 364 function sitename() { 365 var sname = observer.name; 366 var latd = Math.abs(observer.latitude) + 0.00001; 367 var latdi = Math.floor(latd); 368 sname += ((latdi < 10) ? " 0" : " ") + latdi; 369 latm = 60 * (latd - latdi); 370 latmi = Math.floor(latm); 371 sname += ((latmi < 10) ? ":0" : ":") + latmi; 372 // lats=60*(latm-latmi); latsi=Math.floor(lats); 373 // sname+=((latsi < 10) ? ":0" : ":") + latsi; 374 sname += ((observer.latitude >= 0) ? " N, " : " S, "); 375 var longd = Math.abs(observer.longitude) + 0.00001; 376 var longdi = Math.floor(longd); 377 sname += ((longdi < 10) ? "0" : "") + longdi; 378 longm = 60 * (longd - longdi); 379 longmi = Math.floor(longm); 380 sname += ((longmi < 10) ? ":0" : ":") + longmi; 381 // longs=60*(longm-longmi); longsi=Math.floor(longs); 382 // sname+=((longsi < 10) ? ":0" : ":") + longsi; 383 sname += ((observer.longitude >= 0) ? " W" : " E"); 384 return sname; 385 } 386 // sitename() 387 function checkdst(obs) { 388 // Check DST is an attempt to check daylight saving, its not perfect. 389 // Returns 0 or -60 that is amount to remove to get to zone time. 390 // this function is now only called when selecting a place from the dropdown 391 // list. No dst check when updating the time! 392 // We only know daylight saving if in the atlas 393 if ((tbl.Place.selectedIndex < 0) 394 || (tbl.Place.selectedIndex >= atlas.length)) { 395 return 0; 396 } 397 var dss = atlas[tbl.Place.selectedIndex].dss; 398 var dse = atlas[tbl.Place.selectedIndex].dse; 399 var ns = atlas[tbl.Place.selectedIndex].ns; 400 if (dss.length == 0) { 401 return 0; 402 } 403 if (dse.length == 0) { 404 return 0; 405 } 406 // parse the daylight saving start & end dates 407 var col1 = dss.indexOf(":"); 408 var col2 = dss.lastIndexOf(":"); 409 var col3 = dss.length; 410 var dssm = parseInt(dss.substring(0, col1), 10); 411 var dssw = parseInt(dss.substring(col1 + 1, col2), 10); 412 var dssd = parseInt(dss.substring(col2 + 1, col3), 10); 413 col1 = dse.indexOf(":"); 414 col2 = dse.lastIndexOf(":"); 415 col3 = dse.length; 416 var dsem = parseInt(dse.substring(0, col1), 10); 417 var dsew = parseInt(dse.substring(col1 + 1, col2), 10); 418 var dsed = parseInt(dse.substring(col2 + 1, col3), 10); 419 // Length of months 420 // year,month,day and day of week 421 var jdt = jd0(obs.year, obs.month, obs.day); 422 var ymd = jdtocd(jdt); 423 // first day of month - we need to know day of week 424 var fymd = jdtocd(jdt - ymd[2] + 1); 425 // look for daylight saving / summertime changes 426 // first the simple month checks 427 // Test for the northern hemisphere 428 if (ns == 0) { 429 if ((ymd[1] > dssm) && (ymd[1] < dsem)) { 430 return -60; 431 } 432 if ((ymd[1] < dssm) || (ymd[1] > dsem)) { 433 return 0; 434 } 435 } else { 436 // Southern hemisphere, New years day is summer. 437 if ((ymd[1] > dssm) || (ymd[1] < dsem)) { 438 return -60; 439 } 440 if ((ymd[1] < dssm) && (ymd[1] > dsem)) { 441 return 0; 442 } 443 } 444 // check if we are in month of change over 445 if (ymd[1] == dssm) { 446 // month of start of summer time 447 // date of change over 448 var ddd = dssd - fymd[3] + 1; 449 ddd = ddd + 7 * dssw; 450 while (ddd > month_length[ymd[1] - 1]) { 451 ddd -= 7; 452 } 453 if (ymd[2] < ddd) { 454 return 0; 455 } 456 // assume its past the change time, its impossible 457 // to know if the change has occured. 458 return -60; 459 } 460 if (ymd[1] == dsem) { 461 // month of end of summer time 462 // date of change over 463 var ddd = dsed - fymd[3] + 1; 464 ddd = ddd + 7 * dsew; 465 while (ddd > month_length[ymd[1] - 1]) { 466 ddd -= 7; 467 } 468 if (ymd[2] < ddd) { 469 return -60; 470 } 471 // see comment above for start time 472 return 0; 473 } 474 return 0; 475 } 476 // checkdst()
477 function jd(obs) { 478 // The Julian date at observer time 479 var j = jd0(obs.year, obs.month, obs.day); 480 j += (obs.hours + ((obs.minutes + obs.tz) / 60.0) + (obs.seconds / 3600.0)) / 24; 481 return j; 482 } 483 // jd() 484 function local_sidereal(obs) { 485 // sidereal time in hours for observer 486 var res = g_sidereal(obs.year, obs.month, obs.day); 487 res += 1.00273790935 * (obs.hours + (obs.minutes + obs.tz + (obs.seconds / 60.0)) / 60.0); 488 res -= obs.longitude / 15.0; 489 while (res < 0) { 490 res += 24.0; 491 } 492 while (res > 24) { 493 res -= 24.0; 494 } 495 return res; 496 } 497 // 498 // 499 // *************************************************** 500 // part 3 501 // 502 // Various date and time functions 503 // Copyright Peter Hayes 1999-2001, Ole Nielsen 2002-2004 504 // must be updated using leapyear() if year changed 505 var month_length = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); 506 var dow = [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ]; 507 function leapyear(year) { 508 var leap = false; 509 if (year % 4 == 0) { 510 leap = true; 511 } 512 if (year % 100 == 0) { 513 leap = false; 514 } 515 if (year % 400 == 0) { 516 leap = true; 517 } 518 return leap; 519 } 520 function jd0(year, month, day) { 521 // The Julian date at 0 hours(*) UT at Greenwich 522 // (*) or actual UT time if day comprises time as fraction 523 var y = year; 524 var m = month; 525 if (m < 3) { 526 m += 12; 527 y -= 1; 528 } 529 var a = Math.floor(y / 100); 530 var b = 2 - a + Math.floor(a / 4); 531 var j = Math.floor(365.25 * (y + 4716)) + Math.floor(30.6001 * (m + 1)) 532 + day + b - 1524.5; 533 return j; 534 } 535 // jd0() 536 function jdtocd(jd) { 537 // The calendar date from julian date, see Meeus p. 63 538 // Returns year, month, day, day of week, hours, minutes, seconds 539 var Z = Math.floor(jd + 0.5); 540 var F = jd + 0.5 - Z; 541 if (Z < 2299161) { 542 var A = Z; 543 } else { 544 var alpha = Math.floor((Z - 1867216.25) / 36524.25); 545 var A = Z + 1 + alpha - Math.floor(alpha / 4); 546 } 547 var B = A + 1524; 548 var C = Math.floor((B - 122.1) / 365.25); 549 var D = Math.floor(365.25 * C); 550 var E = Math.floor((B - D) / 30.6001); 551 var d = B - D - Math.floor(30.6001 * E) + F; 552 if (E < 14) { 553 var month = E - 1; 554 } else { 555 var month = E - 13; 556 } 557 if (month > 2) { 558 var year = C - 4716; 559 } else { 560 var year = C - 4715; 561 } 562 var day = Math.floor(d); 563 var h = (d - day) * 24; 564 var hours = Math.floor(h); 565 var m = (h - hours) * 60; 566 var minutes = Math.floor(m); 567 var seconds = Math.round((m - minutes) * 60); 568 if (seconds >= 60) { 569 minutes = minutes + 1; 570 seconds = seconds - 60; 571 } 572 if (minutes >= 60) { 573 hours = hours + 1; 574 minutes = 0; 575 } 576 var dw = Math.floor(jd + 1.5) - 7 * Math.floor((jd + 1.5) / 7); 577 return new Array(year, month, day, dw, hours, minutes, seconds); 578 } 579 // jdtocd() 580 function g_sidereal(year, month, day) { 581 // sidereal time in hours for Greenwich 582 var T = (jd0(year, month, day) - 2451545.0) / 36525; 583 var res = 100.46061837 + T 584 * (36000.770053608 + T * (0.000387933 - T / 38710000.0)); 585 return rev(res) / 15.0; 586 } 587 // 588 // 589 // *************************************************** 590 // part 4 591 // 592 // Utility functions 593 // Copyright Ole Nielsen 2002-2004, Peter Hayes 1999-2001 594 function datestring(obs) { 595 // datestring provides a locale independent format 596 var datestr = ""; 597 datestr += obs.year; 598 datestr += ((obs.month < 10) ? ":0" : ":") + obs.month; 599 datestr += ((obs.day < 10) ? ":0" : ":") + obs.day; 600 return datestr; 601 } 602 // end datestring() 603 function datestring2(year, month, day) { 604 var datestr = ""; 605 datestr += year; 606 datestr += ((month < 10) ? ":0" : ":") + month; 607 datestr += ((day < 10) ? ":0" : ":") + day; 608 return datestr; 609 } 610 // end datestring2() 611 function adjustTime(obs, amount) { 612 // update date and time, amount is in minutes (may be negative) 613 // added 2004 614 month_length[1] = leapyear(obs.year) ? 29 : 28; 615 if (amount < 0) { 616 amount = Math.abs(amount); 617 obs.minutes -= amount % 60; 618 amount = Math.floor(amount / 60.0); 619 obs.hours -= amount % 24; 620 amount = Math.floor(amount / 24.0); 621 obs.day -= amount; 622 if (obs.minutes < 0) { 623 obs.minutes += 60; 624 obs.hours -= 1; 625 } 626 if (obs.hours < 0) { 627 obs.hours += 24; 628 obs.day -= 1; 629 } 630 while (obs.day < 1) { 631 obs.day += month_length[obs.month - 2 + (obs.month
631== 1 ? 12 : 0)]; 632 obs.month -= 1; 633 if (obs.month == 0) { 634 obs.year -= 1; 635 obs.month = 12; 636 month_length[1] = (leapyear(obs.year) ? 29 : 28); 637 } 638 } 639 } else { 640 obs.minutes += amount % 60; 641 amount = Math.floor(amount / 60.0); 642 obs.hours += amount % 24; 643 amount = Math.floor(amount / 24.0); 644 obs.day += amount; 645 if (obs.minutes > 59) { 646 obs.minutes -= 60; 647 obs.hours += 1; 648 } 649 if (obs.hours > 23) { 650 obs.hours -= 24; 651 obs.day += 1; 652 } 653 while (obs.day > month_length[obs.month - 1]) { 654 obs.day -= month_length[obs.month - 1]; 655 obs.month += 1; 656 if (obs.month == 13) { 657 obs.year += 1; 658 obs.month = 1; 659 month_length[1] = (leapyear(obs.year) ? 29 : 28); 660 } 661 } 662 } 663 } 664 // end adjustTime() 665 function hmsstring(t) { 666 // the caller must add a leading + if required. 667 var hours = Math.abs(t); 668 var minutes = 60.0 * (hours - Math.floor(hours)); 669 hours = Math.floor(hours); 670 var seconds = Math.round(60.0 * (minutes - Math.floor(minutes))); 671 minutes = Math.floor(minutes); 672 if (seconds >= 60) { 673 minutes += 1; 674 seconds -= 60; 675 } 676 if (minutes >= 60) { 677 hour += 1; 678 minutes -= 60; 679 } 680 if (hours >= 24) { 681 hours -= 24; 682 } 683 var hmsstr = (t < 0) ? "-" : ""; 684 hmsstr = ((hours < 10) ? "0" : "") + hours; 685 hmsstr += ((minutes < 10) ? ":0" : ":") + minutes; 686 hmsstr += ((seconds < 10) ? ":0" : ":") + seconds; 687 return hmsstr; 688 } 689 // end hmsstring() 690 function hmstring(t, plus) { 691 // hmstring converts hours to a string (+/-)hours:minutes, used for relative 692 // time (TZ) 693 var hours = Math.abs(t); 694 var minutes = Math.round(60.0 * (hours - Math.floor(hours))); 695 hours = Math.floor(hours); 696 if (minutes >= 60) { 697 hours += 1; 698 minutes -= 60; 699 } 700 // minutes could be 60 due to rounding 701 if (hours >= 24) { 702 hours -= 24; 703 } 704 var hmstr = (t < 0) ? "-" : (plus ? "+" : ""); 705 hmstr += ((hours < 10) ? "0" : "") + hours; 706 hmstr += ((minutes < 10) ? ":0" : ":") + minutes; 707 return hmstr; 708 } 709 // end hmstring() 710 function hmstring2(hours, minutes, seconds) { 711 // hmstring2 returns time as a string HH:MM (added 2004.01.02), seconds 712 // needed for rounding 713 if (seconds >= 30) { 714 minutes++; 715 } 716 if (minutes >= 60) { 717 hours++; 718 minutes = 0; 719 } 720 var timestr = ((hours < 10) ? "0" : "") + hours; 721 timestr += ((minutes < 10) ? ":0" : ":") + minutes; 722 return timestr; 723 } 724 // end hmstring2() 725 function dmsstring(d) { 726 // dmsstring converts lat/long angle to unsigned string d:m:s 727 var deg = Math.abs(d); 728 var minutes = 60.0 * (deg - Math.floor(deg)); 729 deg = Math.floor(deg); 730 var seconds = Math.round(60.0 * (minutes - Math.floor(minutes))); 731 minutes = Math.floor(minutes); 732 if (seconds >= 60) { 733 minutes += 1; 734 seconds -= 60; 735 } 736 if (minutes >= 60) { 737 deg += 1; 738 minutes -= 60; 739 } 740 hmsstr = ((deg < 10) ? "0" : "") + deg; 741 hmsstr += ((minutes < 10) ? ":0" : ":") + minutes; 742 hmsstr += ((seconds < 10) ? ":0" : ":") + seconds; 743 return hmsstr; 744 } 745 // end dmsstring() 746 function dmstring(d) { 747 // dmstring converts lat/long angle to unsigned string d:m 748 var deg = Math.abs(d); 749 var minutes = 60.0 * (deg - Math.floor(deg)); 750 deg = Math.floor(deg); 751 var seconds = Math.round(60.0 * (minutes - Math.floor(minutes))); 752 minutes = Math.floor(minutes); 753 if (seconds >= 30) { 754 minutes += 1; 755 } 756 if (minutes >= 60) { 757 deg += 1; 758 minutes -= 60; 759 } 760 hmstr = ((deg < 10) ? "0" : "") + deg; 761 hmstr += ((minutes < 10) ? ":0" : ":") + minutes; 762 return hmstr; 763 } 764 // end dmstring() 765 function anglestring(a, circle, arcmin) { 766 // Return angle as degrees:minutes. 'circle' is true for range between 0 and 767 // 360 768 // and false for -90 to +90, if 'arcmin' use deg and arcmin symbols 769 var ar = Math.round(a * 60) / 60; 770 var deg = Math.abs(ar); 771 var min = Math.round(60.0 * (deg - Math.floor(deg))); 772 if (min >= 60) { 773 deg += 1; 774 min = 0; 775 } 776 var anglestr = ""; 777 if (!circle) { 778 anglestr += (ar < 0 ? "-" : "+"); 779 } 780 if (circle) { 781 anglestr += ((Math.floor(deg) < 100) ? "0" : ""); 782 } 783 anglestr += ((Math.floor(deg) < 10) ? "0" : "") + Math.floor(deg); 784 if (arcmin) { 785 anglestr += ((min < 10) ? "°0" : "°") + (min) + "' "; 786 } else { 787 anglestr += ((min < 10) ? ":0" : ":") + (min); 788 } 789 return anglestr; 790 } 791 // end anglestring() 792 function fixnum(n, l, d) { 793 // convert float n to right adjusted string of length l with d digits after 794 // decimal point. 795 // the sign always requires one character, allow for that in l! 796 var m = 1; 797 for ( var i = 0; i < d; i++) { 798 m *= 10; 799 } 800 var n1 = Math.round(Math.abs(n) * m); 801 var nint = Math.floor(n1 / m); 802 var nfract = (n1 - m * nint) + ""; 803 // force conversion to string 804 while (nfract.length < d) { 805 nfract = "0" + nfract; 806 } 807 var str = (n < 0 ? "-" : " ") + nint; 808 if (d > 0) { 809 str = str + "." + nfract; 810 } 811 while (str.length < l) { 812 str = " " + str; 813 } 814 return str; 815 } 816 // end fixnum() 817 function fixstr(str, l) { 818 // returns left-adjusted string of length l, pad with spaces or truncate as 819 // necessary 820 if (str.length > l) { 821 return str.substring(0, l); 822 } 823 while (str.length < l) { 824 str += " ";
825 } 826 return str; 827 } 828 // end fixstr() 829 function parsecol(str) { 830 // parsecol converts deg:min:sec or hr:min:sec to a number 831 var col1 = str.indexOf(":"); 832 var col2 = str.lastIndexOf(":"); 833 if (col1 < 0) { 834 return parseInt(str); 835 } 836 if (str.substring(0, 1) == "-") { 837 var res = parseInt(str.substring(1, col1), 10); 838 } else { 839 var res = parseInt(str.substring(0, col1), 10); 840 } 841 if (col2 > col1) { 842 res += (parseInt(str.substring(col1 + 1, col2), 10) / 60.0) 843 + (parseInt(str.substring(col2 + 1, str.length), 10) / 3600.0); 844 } else { 845 res += (parseInt(str.substring(col1 + 1, str.length), 10) / 60.0); 846 } 847 if (str.substring(0, 1) == "-") { 848 return -res; 849 } else { 850 return res; 851 } 852 } 853 // end parsecol() 854 function interpol(n, y1, y2, y3) { 855 // interpolate y (Meeus 3.3) 856 var a = y2 - y1; 857 var b = y3 - y2; 858 var c = b - a; 859 return y2 + (n / 2) * (a + b + n * c); 860 } 861 function nzero(y1, y2, y3) { 862 // Calculate value of interpolation factor for which y=zero. n0 should be 863 // within [-1:1] 864 // Meeus formula (3.7) 865 var a = y2 - y1; 866 var b = y3 - y2; 867 var c = b - a; 868 var n0 = 0; 869 do { 870 dn0 = -(2 * y2 + n0 * (a + b + c * n0)) / (a + b + 2 * c * n0); 871 n0 += dn0; 872 } while (Math.abs(dn0) > 0.0001); 873 return n0; 874 } 875 // end nzero() 876 function nextrem(y1, y2, y3) { 877 // Calculate value of interpolation factor for which y reaches extremum 878 // (-1<n<1); 879 var a = y2 - y1; 880 var b = y3 - y2; 881 var c = b - a; 882 var nm = -(a + b) / (2 * c); 883 // (3.5) 884 return nm; 885 } 886 // end nextrem(); 887 function isort(arr) { 888 // Sort 2D array in ascending order on first column of each element using 889 // insertion sort 890 for ( var c = 0; c < arr.length - 1; c++) { 891 var tmp = arr[c + 1]; 892 var a = c; 893 while (a >= 0 && arr[a][0] > tmp[0]) { 894 arr[a + 1] = arr[a]; 895 a--; 896 } 897 arr[a + 1] = tmp; 898 } 899 } 900 // end isort() 901 // 902 // 903 // *************************************************** 904 // part 5 905 // 906 // Extensions to the Math routines - Trig routines in degrees 907 // Copyright Peter Hayes 1999-2001, Ole Nielsen 2003-2004 908 var DEG2RAD = Math.PI / 180.0; 909 var RAD2DEG = 180.0 / Math.PI; 910 function rev(angle) { 911 return angle - Math.floor(angle / 360.0) * 360.0; 912 } 913 // 0<=a<360 914 function rev2(angle) { 915 var a = rev(angle); 916 return (a >= 180 ? a - 360.0 : a); 917 } 918 // -180<=a<180 919 function sind(angle) { 920 return Math.sin(angle * DEG2RAD); 921 } 922 function cosd(angle) { 923 return Math.cos(angle * DEG2RAD); 924 } 925 function tand(angle) { 926 return Math.tan(angle * DEG2RAD); 927 } 928 function asind(c) { 929 return RAD2DEG * Math.asin(c); 930 } 931 function acosd(c) { 932 return RAD2DEG * Math.acos(c); 933 } 934 function atand(c) { 935 return RAD2DEG * Math.atan(c); 936 } 937 function atan2d(y, x) { 938 return RAD2DEG * Math.atan2(y, x); 939 } 940 function log10(x) { 941 return Math.LOG10E * Math.log(x); 942 } 943 function sqr(x) { 944 return x * x; 945 } 946 function cbrt(x) { 947 return Math.pow(x, 1 / 3.0); 948 } 949 function SGN(x) { 950 return (x < 0) ? -1 : +1; 951 } 952 // 953 // 954 // *************************************************** 955 // part 6 956 // 957 // FUNCTIONS FOR FINDING EVENTS 958 // 959 // Copyright Ole Nielsen 2002-2004 960 // Please read copyright notice in astrotools2.html source 961 // 962 // 'Meeus' means "Astronomical Algorithms", 2nd ed. by Jean Meeus 963 // standard altitudes for rise and set 964 var H0SUN = -0.833; 965 var H0STAR = -0.583; 966 // 967 // 968 function findEvents(obj, jday, obs) { 969 // Version 2 970 // Calculate daily events (rise, transit, set etc) for one day starting at 971 // jday 972 // Returns chronological sorted array of records, each record comprising 973 // time [0<=t<1] relative to jday 974 // and event type. Event type codes are: 975 // 0: transit; -1/1: rise/set; -2/2: civ. twil. start/end; -3/3 naut twil; 976 // -4/4: astr twil
977 // The first record is different: Type code is 0 for object up, 1 for less 978 // than 6 deg below horizon etc 979 // The code is a little bit 'hairy'. Basically, it determines the nearest 980 // transit time of the 981 // object at each side of the middle of the time interval, and from these 982 // transit times it 983 // calculates rise and set times (and twilights for the Sun). 984 // 985 // reference horizon h0 for Moon depends on parallax, see Meeus p. 102 986 if (obj == MOON) { 987 bodies[obj].update(jday + 0.5, obs); 988 var par = asind(6378.14 / bodies[obj].dist); 989 var h0moon = 0.7275 * par - 0.567; 990 } 991 // rise/set altitude depends on object 992 var href0 = ((obj == SUN) ? H0SUN : H0STAR); 993 if (obj == MOON) { 994 href0 = h0moon; 995 } 996 // stores the various events in records of [t, type] 997 var events = new Array(); 998 var count = 0; 999 // find situation at start of interval (not currently used by AstroTools but 1000 // needed by Skyplanner) 1001 bodies[obj].update(jday, obs); 1002 var altaz = radec2aa(bodies[obj].ra, bodies[obj].dec, jday, obs); 1003 var alt = altaz[0]; 1004 var type = 4; 1005 // object is visible 1006 if (alt > href0) { 1007 type = 0; 1008 } else if (alt > -6) { 1009 // civil twilight 1010 type = 1; 1011 } else if (alt > -12) { 1012 // naut. twil. 1013 type = 2; 1014 } else if (alt > -18) { 1015 // astr. twil. 1016 type = 3; 1017 } 1018 events[count++] = new Array(0, type); 1019 bodies[obj].update(jday + 0.5, obs); 1020 var dec1 = bodies[obj].dec; 1021 var altaz = radec2aa(bodies[obj].ra, bodies[obj].dec, jday + 0.5, obs); 1022 // H is hour angle 1023 var H = altaz[2]; 1024 // first transit approx. 1025 var m = -H / 360.0; 1026 // check for events around first and second transit 1027 for ( var i = 0; i < 2; i++) { 1028 bodies[obj].update(jday + 0.5 + m, obs); 1029 var altaz = radec2aa(bodies[obj].ra, bodies[obj].dec, jday + 0.5 + m, 1030 obs); 1031 var H = altaz[2] > 180.0 ? altaz[2] - 360 : altaz[2]; 1032 // correction to transit time (Meeus page 103) 1033 m0 = m - H / 360.0; 1034 if (m0 >= -0.5 && m0 < 0.5) { 1035 // save transit time 1036 events[count++] = new Array(m0 + 0.5, 0); 1037 } 1038 // find rise and set times (and start/end of twilights if sun) 1039 for ( var j = 0; j <= (obj == SUN ? 3 : 0); j++) { 1040 // href is the desired reference horizon 1041 var href = -6.0 * j; 1042 if (href == 0.0) { 1043 href = href0; 1044 } 1045 // (Meeus 15.1) 1046 var cosH0 = (sind(href) - sind(obs.latitude) * sind(dec1)) 1047 / (cosd(obs.latitude) * cosd(dec1)); 1048 if (cosH0 >= -1.0 && cosH0 <= 1.0) { 1049 // this may miss occasional rises/sets in polar regions, 1050 // especially for Moon 1051 var H0 = acosd(cosH0); 1052 // rise (Meeus 15.2) 1053 var m1 = m0 - H0 / 360.0; 1054 bodies[obj].update(jday + 0.5 + m1, obs); 1055 var altaz = radec2aa(bodies[obj].ra, bodies[obj].dec, jday 1056 + 0.5 + m1, obs); 1057 H = altaz[2]; 1058 // correction to rise time 1059 m1 += (altaz[0] - href) 1060 / (360 * cosd(bodies[obj].dec) * cosd(obs.latitude) * sind(H)); 1061 // only keep event within interval of interest 1062 if (m1 >= -0.5 && m1 < 0.5) { 1063 events[count++] = new Array(m1 + 0.5, -j - 1); 1064 } 1065 // set 1066 var m2 = m0 + H0 / 360.0; 1067 bodies[obj].update(jday + 0.5 + m2, obs); 1068 var altaz = radec2aa(bodies[obj].ra, bodies[obj].dec, jday 1069 + 0.5 + m2, obs); 1070 H = altaz[2]; 1071 // correction to set time 1072 m2 += (altaz[0] - href) 1073 / (360 * cosd(bodies[obj].dec) * cosd(obs.latitude) * sind(H)); 1074 if (m2 >= -0.5 && m2 < 0.5) {
1075 events[count++] = new Array(m2 + 0.5, j + 1); 1076 } 1077 } 1078 } 1079 // second transit approx. 1080 m += 1.0; 1081 } 1082 // end marker 1083 events[count++] = new Array(1.0, -9); 1084 // bring in chronological order 1085 isort(events); 1086 return events; 1087 } 1088 // end findEvents() 1089 // 1090 // 1091 // *************************************************** 1092 // part 7 1093 // 1094 // Functions for the planets 1095 // Copyright Ole Nielsen 2002-2004 1096 // Please read copyright notice in astrotools2.html source 1097 // Formulae and elements from Paul Schlyter's article "Computing planetary 1098 // positions" available at 1099 // http://hem.passagen.se/pausch/comp/ppcomp.html 1100 MERCURY = 0; 1101 VENUS = 1; 1102 EARTH = 2; 1103 MARS = 3; 1104 JUPITER = 4; 1105 SATURN = 5; 1106 URANUS = 6; 1107 NEPTUNE = 7; 1108 SUN = 9; 1109 MOON = 10; 1110 COMET = 15; 1111 USER = 20; 1112 // Planet diameters at 1 AU in arcsec (km for Moon) 1113 var ndiam = [ 6.72, 16.68, 1, 9.36, 196.88, 165.46, 70.04, 67.0, 1, 1919.3, 1114 716900000.0 ]; 1115 // The planet object 1116 function planet(name, num, N, i, w, a, e, M) { 1117 this.name = name; 1118 this.num = num; 1119 this.N = N; 1120 // longitude of ascending node 1121 this.i = i; 1122 // inclination 1123 this.w = w; 1124 // argument of perihelion 1125 this.a = a; 1126 // semimajor axis 1127 this.e = e; 1128 // eccentricity 1129 this.M = M; 1130 // mean anomaly 1131 } 1132 // elements from Paul Schlyter 1133 var planets = new Array(); 1134 planets[0] = new planet("Mercury", 0, new Array(48.3313, 3.24587E-5), 1135 new Array(7.0047, 5.00E-8), new Array(29.1241, 1.01444E-5), new Array( 1136 0.387098, 0), new Array(0.205635, 5.59E-10), new Array( 1137 168.6562, 4.0923344368)); 1138 planets[1] = new planet("Venus ", 1, new Array(76.6799, 2.46590E-5), 1139 new Array(3.3946, 2.75E-8), new Array(54.8910, 1.38374E-5), new Array( 1140 0.723330, 0), new Array(0.006773, -1.302E-9), new Array( 1141 48.0052, 1.6021302244)); 1142 planets[2] = new planet("Earth ", 2, new Array(0, 0), new Array(0, 0), 1143 new Array(0, 0), new Array(0.0, 0.0), new Array(0.0, 0.0), new Array(0, 1144 0)); 1145 planets[3] = new planet("Mars ", 3, new Array(49.5574, 2.11081E-5), 1146 new Array(1.8497, -1.78E-8), new Array(286.5016, 2.92961E-5), 1147 new Array(1.523688, 0), new Array(0.093405, 2.516E-9), new Array( 1148 18.6021, 0.5240207766)); 1149 planets[4] = new planet("Jupiter", 4, new Array(100.4542, 2.76854E-5), 1150 new Array(1.3030, -1.557E-7), new Array(273.8777, 1.64505E-5), 1151 new Array(5.20256, 0), new Array(0.048498, 4.469E-9), new Array( 1152 19.8950, 0.0830853001)); 1153 planets[5] = new planet("Saturn ", 5, new Array(113.6634, 2.38980E-5), 1154 new Array(2.4886, -1.081E-7), new Array(339.3939, 2.97661E-5), 1155 new Array(9.55475, 0), new Array(0.055546, -9.499E-9), new Array( 1156 316.9670, 0.0334442282)); 1157 planets[6] = new planet("Uranus ", 6, new Array(74.0005, 1.3978E-5), new Array( 1158 0.7733, 1.9E-8), new Array(96.6612, 3.0565E-5), new Array(19.18171, 1159 -1.55E-8), new Array(0.047318, 7.45E-9), new Array(142.5905, 1160 0.011725806)); 1161 planets[7] = new planet("Neptune", 7, new Array(131.7806, 3.0173E-5), 1162 new Array(1.7700, -2.55E-7), new Array(272.8461, -6.027E-6), new Array( 1163 30.05826, 3.313E-8), new Array(0.008606, 2.15E-9), new Array( 1164 260.2471, 0.005995147)); 1165 // Body holds current data of planet, Sun or Moon), method .update(jday,obs) 1166 function Body(name, number, colour, colleft, colright) { 1167 this.name = name; 1168 this.number = number; 1169 this.colour = colour; 1170 this.colleft = colleft; 1171 this.colright = colright; 1172 this.alt = 0; 1173 this.az = 0; 1174 this.dec = 0; 1175 this.ra = 0; 1176 this.H = 0; 1177 this.eclon = 0; 1178 this.eclat = 0; 1179 this.illum = 1; 1180 this.r = 1; 1181 // heliocentric distance 1182 this.dist = 1; 1183 // geocentric distance 1184 this.mag = -1.0; 1185 this.elong = 0; 1186 this.pa = 0; 1187 this.phase = 1; // for Moon 1188 // position angle (elongation) 1189 this.update = updatePosition; 1190 this.elongupdate = updateElong; 1191 } 1192 1193 bodies = new Array(); 1194 bodies[0] = new Body("Mercury", MERCURY, 0, 24, 25); 1195 bodies[1] = new Body("Venus", VENUS, 1, 24, 25); 1196 // bodies[2] = new Body("Earth", 2, 3, 24, 25); 1197 bodies[2] = new Body("Mars", MARS, 3, 24, 25); 1198 bodies[3] = new Body("Jupiter", JUPITER, 4, 24, 25); 1199 bodies[4] = new Body("Saturn", SATURN, 5, 24, 25); 1200 bodies[5] = new Body("Uranus", URANUS, 6, 24, 25); 1201 bodies[6] = new Body("Neptune", NEPTUNE, 7, 24, 25); 1202 // bodies[8] = new Body("", 8, 0, 0, 0); 1203 bodies[7] = new Body("Sun", SUN, 9, 26, 27); 1204 bodies[8] = new Body("Moon", MOON, 10, 28, 29); 1205 // bodies[COMET] = new Body("Comet ", COMET, 2, 24, 25); 1206 // bodies[20] = new Body("User object", USER, 2, 24, 25); 1207 function updatePosition(jday, obs) { 1208 // update body-object with current positions 1209 // elongation NOT calculated! (use updateElong for that) 1210 this.p = this.number; 1211 if (this.p == USER) { 1212 // fixed/user object 1213 var altaz = radec2aa(this.ra, this.dec, jday, obs); 1214 this.alt = altaz[0]; 1215 this.az = altaz[1]; 1216 this.H = altaz[2]; 1217 return; 1218 } 1219 var dat = PlanetAlt(this.p, jday, obs); 1220 this.alt = dat[0]; 1221 this.az = dat[1]; 1222 this.H = dat[2]; 1223 this.ra = dat[3];
1224 this.dec = dat[4] - (dat[4] > 180.0 ? 360 : 0); 1225 this.eclon = rev(dat[5]); 1226 this.eclat = dat[6]; 1227 this.r = dat[8]; 1228 this.dist = dat[9]; 1229 this.illum = dat[7]; 1230 this.mag = dat[10]; 1231 1232 this.x = dat[11]; 1233 this.y = dat[12]; 1234 this.z = dat[13]; 1235 1236 if (this.p === MOON) { 1237 var j; 1238 var ip, ag; 1239 ip = (jday + 4.867) / 29.53059; 1240 ip = ip - Math.floor(ip); 1241 if(ip < 0.5) 1242 { 1243 ag = ip * 29.53059 + 29.53059 / 2; 1244 } 1245 else 1246 { 1247 ag = ip * 29.53059 - 29.53059 / 2; 1248 } 1249 this.phase = Math.floor(ag) + 1; 1250 } 1251 } 1252 function updateElong(jday, obs) { 1253 // calculate elongation for object 1254 if (this.number == SUN) { 1255 return; 1256 } 1257 bodies[SUN].update(jday, obs); 1258 var ra2 = bodies[SUN].ra; 1259 var dec2 = bodies[SUN].dec; 1260 this.update(jday, obs); 1261 var dat = separation(this.ra, ra2, this.dec, dec2); 1262 this.elong = dat[0]; 1263 this.pa = dat[1]; 1264 } 1265 // heliocentric xyz for planet p 1266 // this is not from Meeus' book, but from Paul Schlyter 1267 // http://hem.passagen.se/pausch/comp/ppcomp.html 1268 // account for pertuberations of Jupiter, Saturn, Uranus (Uranus and Neptune 1269 // mutual pertubs are included in elements) 1270 // returns heliocentric x, y, z, distance, longitude and latitude of object 1271 function helios(p, jday) { 1272 var d = jday - 2451543.5; 1273 var w = p.w[0] + p.w[1] * d; 1274 // argument of perihelion 1275 var e = p.e[0] + p.e[1] * d; 1276 var a = p.a[0] + p.a[1] * d; 1277 var i = p.i[0] + p.i[1] * d; 1278 var N = p.N[0] + p.N[1] * d; 1279 var M = rev(p.M[0] + p.M[1] * d); 1280 // mean anomaly 1281 var E0 = M + RAD2DEG * e * sind(M) * (1.0 + e * cosd(M)); 1282 var E1 = E0 - (E0 - RAD2DEG * e * sind(E0) - M) / (1.0 - e * cosd(E0)); 1283 while (Math.abs(E0 - E1) > 0.0005) { 1284 E0 = E1; 1285 E1 = E0 - (E0 - RAD2DEG * e * sind(E0) - M) / (1.0 - e * cosd(E0)); 1286 } 1287 var xv = a * (cosd(E1) - e); 1288 var yv = a * Math.sqrt(1.0 - e * e) * sind(E1); 1289 var v = rev(atan2d(yv, xv)); 1290 // true anomaly 1291 var r = Math.sqrt(xv * xv + yv * yv); 1292 // distance 1293 var xh = r * (cosd(N) * cosd(v + w) - sind(N) * sind(v + w) * cosd(i)); 1294 var yh = r * (sind(N) * cosd(v + w) + cosd(N) * sind(v + w) * cosd(i)); 1295 var zh = r * (sind(v + w) * sind(i)); 1296 var lonecl = atan2d(yh, xh); 1297 var latecl = atan2d(zh, Math.sqrt(xh * xh + yh * yh + zh * zh)); 1298 if (p.num == JUPITER) { 1299 // Jupiter pertuberations by Saturn 1300 var Ms = rev(planets[SATURN].M[0] + planets[SATURN].M[1] * d); 1301 lonecl += (-0.332) * sind(2 * M - 5 * Ms - 67.6) - 0.056 1302 * sind(2 * M - 2 * Ms + 21) + 0.042 * sind(3 * M - 5 * Ms + 21) 1303 - 0.036 * sind(M - 2 * Ms) + 0.022 * cosd(M - Ms) + 0.023 1304 * sind(2 * M - 3 * Ms + 52) - 0.016 * sind(M - 5 * Ms - 69); 1305 xh = r * cosd(lonecl) * cosd(latecl); 1306 // recalc xh, yh 1307 yh = r * sind(lonecl) * cosd(latecl); 1308 } 1309 if (p.num == SATURN) { 1310 // Saturn pertuberations 1311 var Mj = rev(planets[JUPITER].M[0] + planets[JUPITER].M[1] * d); 1312 lonecl += 0.812 * sind(2 * Mj - 5 * M - 67.6) - 0.229 1313 * cosd(2 * Mj - 4 * M - 2) + 0.119 * sind(Mj - 2 * M - 3) 1314 + 0.046 * sind(2 * Mj - 6 * M - 69) + 0.014 1315 * sind(Mj - 3 * M + 32);
1316 latecl += -0.020 * cosd(2 * Mj - 4 * M - 2) + 0.018 1317 * sind(2 * Mj - 6 * M - 49); 1318 xh = r * cosd(lonecl) * cosd(latecl); 1319 // recalc xh, yh, zh 1320 yh = r * sind(lonecl) * cosd(latecl); 1321 zh = r * sind(latecl); 1322 } 1323 if (p.num == URANUS) { 1324 // Uranus pertuberations 1325 var Mj = rev(planets[JUPITER].M[0] + planets[JUPITER].M[1] * d); 1326 var Ms = rev(planets[SATURN].M[0] + planets[SATURN].M[1] * d); 1327 lonecl += 0.040 * sind(Ms - 2 * M + 6) + 0.035 * sind(Ms - 3 * M + 33) 1328 - 0.015 * sind(Mj - M + 20); 1329 xh = r * cosd(lonecl) * cosd(latecl); 1330 // recalc xh, yh 1331 yh = r * sind(lonecl) * cosd(latecl); 1332 } 1333 return new Array(xh, yh, zh, r, lonecl, latecl); 1334 } 1335 // helios() 1336 function radecr(obj, sun, jday, obs) { 1337 // radecr returns ra, dec and earth distance 1338 // obj and sun comprise Heliocentric Ecliptic Rectangular Coordinates 1339 // (note Sun coords are really Earth heliocentric coordinates with reverse 1340 // signs) 1341 // Equatorial geocentric co-ordinates 1342 var xg = obj[0] + sun[0]; 1343 var yg = obj[1] + sun[1]; 1344 var zg = obj[2]; 1345 // Obliquity of Ecliptic (exponent corrected, was E-9!) 1346 var obl = 23.4393 - 3.563E-7 * (jday - 2451543.5); 1347 // Convert to eq. co-ordinates 1348 var x1 = xg; 1349 var y1 = yg * cosd(obl) - zg * sind(obl); 1350 var z1 = yg * sind(obl) + zg * cosd(obl); 1351 // RA and dec (33.2) 1352 var ra = rev(atan2d(y1, x1)); 1353 var dec = atan2d(z1, Math.sqrt(x1 * x1 + y1 * y1)); 1354 var dist = Math.sqrt(x1 * x1 + y1 * y1 + z1 * z1); 1355 return new Array(ra, dec, dist); 1356 } 1357 function radec2aa(ra, dec, jday, obs) { 1358 // Convert ra/dec to alt/az, also return hour angle, azimut = 0 when north 1359 // DOES NOT correct for parallax! 1360 // TH0=Greenwich sid. time (eq. 12.4), H=hour angle (chapter 13) 1361 var TH0 = 280.46061837 + 360.98564736629 * (jday - 2451545.0); 1362 var H = rev(TH0 - obs.longitude - ra); 1363 var alt = asind(sind(obs.latitude) * sind(dec) + cosd(obs.latitude) 1364 * cosd(dec) * cosd(H)); 1365 var az = atan2d(sind(H), (cosd(H) * sind(obs.latitude) - tand(dec) 1366 * cosd(obs.latitude))); 1367 return new Array(alt, rev(az + 180.0), H); 1368 } 1369 function separation(ra1, ra2, dec1, dec2) { 1370 // ra, dec may also be long, lat, but PA is relative to the chosen 1371 // coordinate system 1372 var d = acosd(sind(dec1) * sind(dec2) + cosd(dec1) * cosd(dec2) 1373 * cosd(ra1 - ra2)); 1374 // (Meeus 17.1) 1375 if (d < 0.1) { 1376 d = Math.sqrt(sqr(rev2(ra1 - ra2) * cosd((dec1 + dec2) / 2)) 1377 + sqr(dec1 - dec2)); 1378 } 1379 // (17.2) 1380 var pa = atan2d(sind(ra1 - ra2), cosd(dec2) * tand(dec1) - sind(dec2) 1381 * cosd(ra1 - ra2)); 1382 // angle 1383 return new Array(d, rev(pa)); 1384 } 1385 // end separation() 1386 function PlanetAlt(p, jday, obs) { 1387 // Alt/Az, hour angle, ra/dec, ecliptic long. and lat, illuminated fraction, 1388 // dist(Sun), dist(Earth), brightness of planet p 1389 if (p == SUN) { 1390 return SunAlt(jday, obs); 1391 } 1392 if (p == MOON) { 1393 return MoonPos(jday, obs); 1394 } 1395 if (p == COMET) { 1396 return CometAlt(jday, obs); 1397 } 1398 var sun_xyz = sunxyz(jday); 1399 var planet_xyz = helios(planets[p], jday); 1400 var dx = planet_xyz[0] + sun_xyz[0]; 1401 var dy = planet_xyz[1] + sun_xyz[1]; 1402 var dz = planet_xyz[2] + sun_xyz[2]; 1403 var lon = rev(atan2d(dy, dx)); 1404 var lat = atan2d(dz, Math.sqrt(dx * dx + dy * dy)); 1405 var radec = radecr(planet_xyz, sun_xyz, jday, obs); 1406 var ra = radec[0]; 1407 var dec = radec[1]; 1408 var altaz = radec2aa(ra, dec, jday, obs); 1409 var dist = radec[2]; 1410 var R = sun_xyz[3]; 1411 // Sun-Earth distance 1412 var r = planet_xyz[3]; 1413 // heliocentric distance 1414 var k = ((r + dist) * (r + dist) - R * R) / (4 * r * dist); 1415 // illuminated fraction (41.2) 1416 // brightness calc according to Meeus p. 285-86 using Astronomical Almanac 1417 // expressions 1418 var absbr = new Array(-0.42, -4.40, 0, -1.52, -9.40, -8.88, -7.19, -6.87); 1419 var i = acosd((r * r + dist * dist - R * R) / (2 * r * dist)); 1420 // phase angle 1421 var mag = absbr[p] + 5 * log10(r * dist); 1422 // common for all planets 1423 switch (p) { 1424 case MERCURY: 1425 mag += i * (0.0380 + i * (-0.000273 + i * 0.000002)); 1426 break; 1427 case VENUS: 1428 mag += i * (0.0009 + i * (0.000239 - i * 0.00000065)); 1429 break; 1430 case MARS: 1431 mag += i * 0.016; 1432 break; 1433 case JUPITER: 1434 mag += i * 0.005; 1435 break; 1436 case SATURN: 1437 // (Ring system needs special treatment, see Meeus Ch. 45) 1438 var T = (jday - 2451545.0) / 36525; 1439 // (22.1) 1440 var incl = 28.075216 - 0.012998 * T + 0.000004 * T * T; 1441 // (45.1) 1442 var omega = 169.508470 + 1.394681 * T + 0.000412 * T * T; 1443 // (45.1) 1444 var B = asind(sind(incl) * cosd(lat) * sind(lon - omega) - cosd(incl) 1445 * sind(lat)); 1446 var l = planet_xyz[4]; 1447 // heliocentric longitude of Saturn 1448 var b = planet_xyz[5]; 1449 // heliocentric latitude (do not confuse with 'b' in step 6, page 319) 1450 // correction for Sun's aberration skipped 1451 var U1 = atan2d(sind(incl) * sind(b) + cosd(incl) * cosd(b) 1452 * sind(l - omega), cosd(b) * cosd(l - omega)); 1453 var U2 = atan2d(sind(incl) * sind(lat) + cosd(incl) * cosd(lat) 1454 * sind(lon - omega), cosd(lat) * cosd(lon - omega)); 1455 var dU = Math.abs(U1 - U2); 1456 mag += 0.044 * dU - 2.60 * sind(Math.abs(B)) + 1.25 * sind(B) * sind(B); 1457 break; 1458 } 1459 return new Array(altaz[0], altaz[1], altaz[2], ra, dec, lon, lat, k, r, 1460 dist, mag, dx, dy, dz); 1461 } 1462 1463 1464 return { 1465 1466 update : function(julianDate, observer) { 1467 var obs = new observatory(atlas[0], 2012, 1, 1, 12, 0, 0); 1468 obs.latitude = observer.getLat(); 1469 obs.longitude = observer.getLon();; 1470 1471 for (i=0;i< bodies.length;i++) { 1472 1473 if (bodies[i].name !== '') { 1474 bodies[i].update(julianDate, obs); 1475 } 1476 } 1477 return bodies; 1478 }, 1479 1480 getPlanets : function() { 1481 return bodies; 1482 } 1483 1484 } 1485};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.