not really known
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

430 lines
20 KiB

  1. /*!
  2. * Virtual Sky add on to display planets without
  3. * needing a file regularly updated from JPL Horizons
  4. * Written by Stuart Lowe (http://www.strudel.org.uk/)
  5. */
  6. (function ($) {
  7. // An init function for the plugin
  8. function init(){
  9. // Attach a callback to the loadedPlanets event to calculate and draw the planets
  10. this.bind("loadedPlanets",function(d){
  11. this.jd = this.times.JD;
  12. var p = new Planets();
  13. var days = 365.25;
  14. this.planets = p.build(Math.floor(this.jd)-days*0.25,days*1.25);
  15. var loadtime = this.times.JD;
  16. var i = this.calendarevents.length;
  17. this.calendarevents.push(function(){
  18. if(Math.abs(loadtime-this.times.JD) >= days*0.25){
  19. this.calendarevents.splice(i,1); // Remove this one-time event
  20. this.trigger('loadedPlanets');
  21. this.draw();
  22. }
  23. })
  24. this.draw();
  25. });
  26. }
  27. // Create an object to deal with planet ephemerides
  28. function Planets(){
  29. // Heliocentric Osculating Orbital Elements Referred to the Mean Equinox and Ecliptic of Date for 2013: http://asa.usno.navy.mil/static/files/2013/Osculating_Elements_2013.txt
  30. // Values of the Osculating Orbital Elements for 8th August 1997: http://www.stargazing.net/kepler/ellipse.html
  31. this.planets = [{
  32. "name": "Me",
  33. "radius":2439.7, // km
  34. "interval": 0.5,
  35. "colour": "rgb(170,150,170)",
  36. "magnitude": function(d){ return -0.36 + 5*log10(d.r*d.R) + 0.027 * d.FV + 2.2E-13 * Math.pow(d.FV,6); },
  37. "elements": [
  38. {"jd":2456280.5,"i":7.0053,"o":48.485,"p":77.658,"a":0.387100,"n":4.09232,"e":0.205636,"L":191.7001},
  39. {"jd":2456320.5,"i":7.0052,"o":48.486,"p":77.661,"a":0.387097,"n":4.09236,"e":0.205644,"L":355.3943},
  40. {"jd":2456360.5,"i":7.0052,"o":48.487,"p":77.663,"a":0.387098,"n":4.09235,"e":0.205646,"L":159.0899},
  41. {"jd":2456400.5,"i":7.0052,"o":48.489,"p":77.665,"a":0.387097,"n":4.09236,"e":0.205649,"L":322.7854},
  42. {"jd":2456440.5,"i":7.0052,"o":48.490,"p":77.665,"a":0.387097,"n":4.09236,"e":0.205650,"L":126.4812},
  43. {"jd":2456480.5,"i":7.0052,"o":48.492,"p":77.667,"a":0.387098,"n":4.09235,"e":0.205645,"L":290.1771},
  44. {"jd":2456520.5,"i":7.0052,"o":48.493,"p":77.669,"a":0.387098,"n":4.09235,"e":0.205645,"L":93.8725},
  45. {"jd":2456560.5,"i":7.0052,"o":48.494,"p":77.671,"a":0.387098,"n":4.09235,"e":0.205642,"L":257.5683},
  46. {"jd":2456600.5,"i":7.0052,"o":48.495,"p":77.672,"a":0.387099,"n":4.09234,"e":0.205635,"L":61.2628},
  47. {"jd":2456640.5,"i":7.0052,"o":48.497,"p":77.674,"a":0.387099,"n":4.09233,"e":0.205635,"L":224.9579},
  48. {"jd":2456680.5,"i":7.0052,"o":48.498,"p":77.677,"a":0.387098,"n":4.09234,"e":0.205633,"L":28.6524}
  49. ]
  50. },{
  51. "name": "V",
  52. "radius": 6051.9, // km
  53. "interval": 1,
  54. "colour": "rgb(245,222,179)",
  55. "magnitude": function(d){ return -4.34 + 5*log10(d.a*d.R) + 0.013 * d.FV + 4.2E-7*Math.pow(d.FV,3); },
  56. "elements": [
  57. {"jd":2456280.5,"i":3.3949,"o":76.797,"p":132.00,"a":0.723328,"n":1.60214,"e":0.006777,"L":209.0515},
  58. {"jd":2456320.5,"i":3.3949,"o":76.798,"p":132.05,"a":0.723332,"n":1.60213,"e":0.006780,"L":273.1380},
  59. {"jd":2456360.5,"i":3.3949,"o":76.799,"p":132.07,"a":0.723327,"n":1.60215,"e":0.006787,"L":337.2248},
  60. {"jd":2456400.5,"i":3.3949,"o":76.801,"p":132.03,"a":0.723331,"n":1.60214,"e":0.006785,"L":41.3121},
  61. {"jd":2456440.5,"i":3.3949,"o":76.802,"p":131.97,"a":0.723333,"n":1.60213,"e":0.006780,"L":105.3980},
  62. {"jd":2456480.5,"i":3.3949,"o":76.803,"p":131.96,"a":0.723325,"n":1.60216,"e":0.006769,"L":169.4851},
  63. {"jd":2456520.5,"i":3.3949,"o":76.804,"p":131.99,"a":0.723327,"n":1.60215,"e":0.006769,"L":233.5729},
  64. {"jd":2456560.5,"i":3.3949,"o":76.806,"p":132.03,"a":0.723328,"n":1.60214,"e":0.006770,"L":297.6598},
  65. {"jd":2456600.5,"i":3.3949,"o":76.807,"p":132.03,"a":0.723326,"n":1.60215,"e":0.006775,"L":1.7475},
  66. {"jd":2456640.5,"i":3.3949,"o":76.808,"p":131.89,"a":0.723337,"n":1.60211,"e":0.006775,"L":65.8345},
  67. {"jd":2456680.5,"i":3.3948,"o":76.808,"p":131.63,"a":0.723345,"n":1.60209,"e":0.006770,"L":129.9169}
  68. ]
  69. },{
  70. "name":"E",
  71. "elements" : [
  72. {"jd":2450680.5,"i":0.00041,"o":349.2,"p":102.8517,"a":1.0000200,"n":0.9855796,"e":0.0166967,"L":328.40353},
  73. {"jd":2456280.5,"i":0.0,"o":349.2,"p":103.042,"a":1.000008,"n":0.985598,"e":0.016703,"L":87.9950},
  74. {"jd":2456320.5,"i":0.0,"o":349.2,"p":103.005,"a":0.999986,"n":0.985631,"e":0.016682,"L":127.4201},
  75. {"jd":2456360.5,"i":0.0,"o":349.2,"p":102.990,"a":0.999978,"n":0.985642,"e":0.016675,"L":166.8472},
  76. {"jd":2456400.5,"i":0.0,"o":349.2,"p":103.022,"a":0.999987,"n":0.985630,"e":0.016677,"L":206.2740},
  77. {"jd":2456440.5,"i":0.0,"o":349.2,"p":103.077,"a":1.000000,"n":0.985611,"e":0.016677,"L":245.6993},
  78. {"jd":2456480.5,"i":0.0,"o":349.2,"p":103.119,"a":1.000005,"n":0.985603,"e":0.016675,"L":285.1238},
  79. {"jd":2456520.5,"i":0.0,"o":349.2,"p":103.147,"a":1.000000,"n":0.985611,"e":0.016679,"L":324.5489},
  80. {"jd":2456560.5,"i":0.0,"o":349.2,"p":103.161,"a":0.999995,"n":0.985618,"e":0.016682,"L":3.9752},
  81. {"jd":2456600.5,"i":0.0,"o":349.2,"p":103.146,"a":1.000002,"n":0.985608,"e":0.016690,"L":43.4020},
  82. {"jd":2456640.5,"i":0.0,"o":349.2,"p":103.135,"a":1.000010,"n":0.985596,"e":0.016698,"L":82.8279},
  83. {"jd":2456680.5,"i":0.0,"o":349.2,"p":103.166,"a":1.000005,"n":0.985603,"e":0.016693,"L":122.2544}
  84. ]
  85. },{
  86. "name":"Ma",
  87. "radius": 3386, // km
  88. "interval": 1,
  89. "colour": "rgb(255,50,50)",
  90. "magnitude": function(d){ return -1.51 + 5*log10(d.r*d.R) + 0.016 * d.FV; },
  91. "elements":[
  92. {"jd":2450680.5,"i":1.84992,"o":49.5664,"p":336.0882,"a":1.5236365,"n":0.5240613,"e":0.0934231,"L":262.42784},
  93. {"jd":2456280.5,"i":1.8497,"o":49.663,"p":336.246,"a":1.523624,"n":0.524069,"e":0.093285,"L":317.1847},
  94. {"jd":2456320.5,"i":1.8497,"o":49.664,"p":336.249,"a":1.523605,"n":0.524079,"e":0.093274,"L":338.1493},
  95. {"jd":2456360.5,"i":1.8497,"o":49.665,"p":336.255,"a":1.523601,"n":0.524081,"e":0.093269,"L":359.1150},
  96. {"jd":2456400.5,"i":1.8497,"o":49.666,"p":336.268,"a":1.523627,"n":0.524068,"e":0.093276,"L":20.0806},
  97. {"jd":2456440.5,"i":1.8497,"o":49.667,"p":336.287,"a":1.523678,"n":0.524041,"e":0.093292,"L":41.0443},
  98. {"jd":2456480.5,"i":1.8496,"o":49.668,"p":336.306,"a":1.523731,"n":0.524014,"e":0.093316,"L":62.0048},
  99. {"jd":2456520.5,"i":1.8496,"o":49.668,"p":336.322,"a":1.523762,"n":0.523998,"e":0.093346,"L":82.9625},
  100. {"jd":2456560.5,"i":1.8495,"o":49.666,"p":336.329,"a":1.523748,"n":0.524005,"e":0.093385,"L":103.9196},
  101. {"jd":2456600.5,"i":1.8495,"o":49.665,"p":336.333,"a":1.523709,"n":0.524025,"e":0.093425,"L":124.8784},
  102. {"jd":2456640.5,"i":1.8495,"o":49.665,"p":336.333,"a":1.523665,"n":0.524048,"e":0.093458,"L":145.8405},
  103. {"jd":2456680.5,"i":1.8495,"o":49.665,"p":336.330,"a":1.523631,"n":0.524066,"e":0.093482,"L":166.8051}
  104. ]
  105. },{
  106. "name":"J",
  107. "radius": 69173, // km
  108. "interval": 10,
  109. "colour": "rgb(255,150,150)",
  110. "magnitude": function(d){ return -9.25 + 5*log10(d.r*d.R) + 0.014 * d.FV; },
  111. "elements":[
  112. {"jd":2456280.5,"i":1.3033,"o":100.624,"p":14.604,"a":5.20269,"n":0.083094,"e":0.048895,"L":68.0222},
  113. {"jd":2456320.5,"i":1.3033,"o":100.624,"p":14.591,"a":5.20263,"n":0.083095,"e":0.048893,"L":71.3469},
  114. {"jd":2456360.5,"i":1.3033,"o":100.625,"p":14.588,"a":5.20262,"n":0.083095,"e":0.048895,"L":74.6719},
  115. {"jd":2456400.5,"i":1.3033,"o":100.626,"p":14.589,"a":5.20262,"n":0.083095,"e":0.048896,"L":77.9971},
  116. {"jd":2456440.5,"i":1.3033,"o":100.627,"p":14.586,"a":5.20259,"n":0.083096,"e":0.048892,"L":81.3228},
  117. {"jd":2456480.5,"i":1.3033,"o":100.628,"p":14.568,"a":5.20250,"n":0.083098,"e":0.048888,"L":84.6481},
  118. {"jd":2456520.5,"i":1.3033,"o":100.629,"p":14.556,"a":5.20245,"n":0.083099,"e":0.048892,"L":87.9728},
  119. {"jd":2456560.5,"i":1.3033,"o":100.630,"p":14.555,"a":5.20245,"n":0.083099,"e":0.048901,"L":91.2973},
  120. {"jd":2456600.5,"i":1.3033,"o":100.631,"p":14.576,"a":5.20254,"n":0.083097,"e":0.048907,"L":94.6223},
  121. {"jd":2456640.5,"i":1.3033,"o":100.632,"p":14.593,"a":5.20261,"n":0.083096,"e":0.048901,"L":97.9485},
  122. {"jd":2456680.5,"i":1.3033,"o":100.633,"p":14.592,"a":5.20259,"n":0.083096,"e":0.048891,"L":101.2751}
  123. ]
  124. },{
  125. "name":"S",
  126. "radius": 57316, // km
  127. "interval": 10,
  128. "colour": "rgb(200,150,150)",
  129. "magnitude": function(d){
  130. var slon = Math.atan2(d.y,d.x);
  131. var slat = Math.atan2(d.z, Math.sqrt(d.x*d.x + d.y*d.y));
  132. while(slon < 0) slon += 2*Math.PI;
  133. while(slon >= 360) slon -= 2*Math.PI;
  134. var ir = d.d2r*28.06;
  135. var Nr = d.d2r*(169.51 + 3.82E-5 * (d.jd-2451543.5)); // Compared to J2000 epoch
  136. var B = Math.asin(Math.sin(slat) * Math.cos(ir) - Math.cos(slat) * Math.sin(ir) * Math.sin(slon-Nr));
  137. return -9.0 + 5*log10(d.r*d.R) + 0.044 * d.FV + (-2.6 * Math.sin(Math.abs(B)) + 1.2 * Math.pow(Math.sin(B),2));
  138. },
  139. "elements":[
  140. {"jd":2456280.5,"i":2.4869,"o":113.732,"p":90.734,"a":9.51836,"n":0.033583,"e":0.055789,"L":208.6057},
  141. {"jd":2456320.5,"i":2.4869,"o":113.732,"p":90.856,"a":9.51931,"n":0.033578,"e":0.055791,"L":209.9430},
  142. {"jd":2456360.5,"i":2.4869,"o":113.732,"p":90.979,"a":9.52024,"n":0.033574,"e":0.055794,"L":211.2797},
  143. {"jd":2456400.5,"i":2.4869,"o":113.733,"p":91.105,"a":9.52121,"n":0.033568,"e":0.055793,"L":212.6162},
  144. {"jd":2456440.5,"i":2.4869,"o":113.732,"p":91.245,"a":9.52234,"n":0.033562,"e":0.055779,"L":213.9525},
  145. {"jd":2456480.5,"i":2.4869,"o":113.732,"p":91.380,"a":9.52349,"n":0.033556,"e":0.055750,"L":215.2901},
  146. {"jd":2456520.5,"i":2.4869,"o":113.732,"p":91.500,"a":9.52450,"n":0.033551,"e":0.055724,"L":216.6279},
  147. {"jd":2456560.5,"i":2.4870,"o":113.732,"p":91.611,"a":9.52541,"n":0.033546,"e":0.055704,"L":217.9654},
  148. {"jd":2456600.5,"i":2.4870,"o":113.732,"p":91.727,"a":9.52630,"n":0.033541,"e":0.055691,"L":219.3014},
  149. {"jd":2456640.5,"i":2.4870,"o":113.732,"p":91.870,"a":9.52748,"n":0.033535,"e":0.055657,"L":220.6368},
  150. {"jd":2456680.5,"i":2.4870,"o":113.733,"p":92.021,"a":9.52885,"n":0.033528,"e":0.055600,"L":221.9730}
  151. ]
  152. },{
  153. "name":"U",
  154. "radius": 25266, // km
  155. "interval": 20,
  156. "colour": "rgb(130,150,255)",
  157. "magnitude": function(d){ return -7.15 + 5*log10(d.r*d.R) + 0.001 * d.FV; },
  158. "elements":[
  159. {"jd":2456280.5,"i":0.7726,"o":74.004,"p":169.227,"a":19.2099,"n":0.011713,"e":0.046728,"L":9.1400},
  160. {"jd":2456320.5,"i":0.7727,"o":74.001,"p":169.271,"a":19.2064,"n":0.011716,"e":0.046913,"L":9.6133},
  161. {"jd":2456360.5,"i":0.7727,"o":73.997,"p":169.314,"a":19.2030,"n":0.011720,"e":0.047102,"L":10.0873},
  162. {"jd":2456400.5,"i":0.7727,"o":73.991,"p":169.364,"a":19.1994,"n":0.011723,"e":0.047297,"L":10.5610},
  163. {"jd":2456440.5,"i":0.7728,"o":73.989,"p":169.434,"a":19.1953,"n":0.011727,"e":0.047509,"L":11.0340},
  164. {"jd":2456480.5,"i":0.7728,"o":73.989,"p":169.522,"a":19.1916,"n":0.011730,"e":0.047703,"L":11.5048},
  165. {"jd":2456520.5,"i":0.7728,"o":73.989,"p":169.602,"a":19.1882,"n":0.011733,"e":0.047874,"L":11.9756},
  166. {"jd":2456560.5,"i":0.7728,"o":73.989,"p":169.674,"a":19.1850,"n":0.011736,"e":0.048035,"L":12.4470},
  167. {"jd":2456600.5,"i":0.7728,"o":73.985,"p":169.740,"a":19.1816,"n":0.011739,"e":0.048215,"L":12.9200},
  168. {"jd":2456640.5,"i":0.7728,"o":73.984,"p":169.836,"a":19.1774,"n":0.011743,"e":0.048431,"L":13.3920},
  169. {"jd":2456680.5,"i":0.7728,"o":73.983,"p":169.962,"a":19.1729,"n":0.011747,"e":0.048650,"L":13.8617}
  170. ]
  171. },{
  172. "name":"N",
  173. "radius": 24553, // km
  174. "interval": 20,
  175. "colour": "rgb(100,100,255)",
  176. "magnitude": function(d){ return -6.90 + 5*log10(d.r*d.R) + 0.001 * d.FV; },
  177. "elements":[
  178. {"jd":2456280.5,"i":1.7686,"o":131.930,"p":53.89,"a":30.0401,"n":0.005990,"e":0.010281,"L":333.6121},
  179. {"jd":2456320.5,"i":1.7687,"o":131.932,"p":55.15,"a":30.0331,"n":0.005992,"e":0.010207,"L":333.8487},
  180. {"jd":2456360.5,"i":1.7688,"o":131.935,"p":56.47,"a":30.0259,"n":0.005994,"e":0.010138,"L":334.0856},
  181. {"jd":2456400.5,"i":1.7688,"o":131.937,"p":57.82,"a":30.0185,"n":0.005996,"e":0.010067,"L":334.3220},
  182. {"jd":2456440.5,"i":1.7690,"o":131.940,"p":59.24,"a":30.0108,"n":0.005999,"e":0.009985,"L":334.5566},
  183. {"jd":2456480.5,"i":1.7691,"o":131.943,"p":60.44,"a":30.0044,"n":0.006000,"e":0.009894,"L":334.7895},
  184. {"jd":2456520.5,"i":1.7692,"o":131.946,"p":61.52,"a":29.9987,"n":0.006002,"e":0.009816,"L":335.0233},
  185. {"jd":2456560.5,"i":1.7693,"o":131.949,"p":62.57,"a":29.9932,"n":0.006004,"e":0.009748,"L":335.2581},
  186. {"jd":2456600.5,"i":1.7694,"o":131.951,"p":63.84,"a":29.9867,"n":0.006006,"e":0.009690,"L":335.4937},
  187. {"jd":2456640.5,"i":1.7695,"o":131.954,"p":65.29,"a":29.9793,"n":0.006008,"e":0.009609,"L":335.7265},
  188. {"jd":2456680.5,"i":1.7697,"o":131.957,"p":66.66,"a":29.9725,"n":0.006010,"e":0.009508,"L":335.9564}
  189. ]
  190. }];
  191. this.d2r = Math.PI/180;
  192. this.r2d = 180/Math.PI;
  193. this.AUinkm = 149597870.700;
  194. return this;
  195. }
  196. // Build an array containing all the planets
  197. // Inputs:
  198. // jd = the Julian Date to calculate from
  199. // days = the number of days to calculate ephemerides for
  200. Planets.prototype.build = function(jd,days){
  201. var arr = new Array(this.planets.length-1);
  202. var b = 0;
  203. if(!days) days = 365.25;
  204. for(var a = 0 ; a < this.planets.length ; a++){
  205. if(this.planets[a].colour) arr[b++] = this.buildPlanet(a,jd,days);
  206. }
  207. return arr;
  208. }
  209. // Build the data array for a particular planet
  210. // Inputs:
  211. // planet = the ID of the planet
  212. // jd = the Julian Date to calculate from
  213. // days = the number of days to calculate ephemerides for
  214. Planets.prototype.buildPlanet = function(planet,jd,days){
  215. var p,coord,interval,n,jdcurr;
  216. if(typeof planet==="number"){
  217. p = planet;
  218. }else{
  219. var match = -1;
  220. for(var a = 0 ; a < this.planets.length ; a++){
  221. if(this.planets[a].name==planet) match = a;
  222. }
  223. if(match < 0) return this;
  224. if(match == 2) return this; // Can't calculate Earth
  225. p = match;
  226. }
  227. interval = (typeof this.planets[p].interval==="number" ? this.planets[p].interval : 1);
  228. // Build an array of the form:
  229. // [Planet name,colour,[jd_1, ra_1, dec_1, mag_1, jd_2, ra_2, dec_2, mag_2....]]
  230. n = Math.floor(days/interval);
  231. var arr = new Array(3);
  232. arr[0] = this.planets[p]["name"];
  233. arr[1] = this.planets[p]["colour"];
  234. arr[2] = new Array(n*4);
  235. jdcurr = jd;
  236. for(var i = 0 ; i < n; i++){
  237. jdcurr += interval;
  238. coord = this.getEphem(p,jdcurr);
  239. arr[2][i*4+0] = jdcurr;
  240. arr[2][i*4+1] = coord[0];
  241. arr[2][i*4+2] = coord[1];
  242. arr[2][i*4+3] = coord[2];
  243. }
  244. return arr;
  245. }
  246. // Get the ephemeris for the specified planet number
  247. // Input:
  248. // planet = ID
  249. // day = Julian Date to calculate the ephemeris for
  250. // Method from http://www.stargazing.net/kepler/ellipse.html#twig06
  251. Planets.prototype.getEphem = function(planet,day){
  252. var i,v,e,x,y,z,ec,q,ra,dc,R,mag,FV,phase;
  253. if(typeof planet==="number"){
  254. i = planet;
  255. }else{
  256. var match = -1;
  257. for(var a = 0 ; a < this.planets.length ; a++){
  258. if(this.planets[a].name==planet) match = a;
  259. }
  260. if(match < 0) return this;
  261. if(match == 2) return this; // Can't calculate Earth
  262. i = match;
  263. }
  264. // Heliocentric coordinates of planet
  265. v = this.getHeliocentric(this.planets[i],day);
  266. // Heliocentric coordinates of Earth
  267. e = this.getHeliocentric(this.planets[2],day);
  268. // Geocentric ecliptic coordinates of the planet
  269. x = v.xyz[0] - e.xyz[0];
  270. y = v.xyz[1] - e.xyz[1];
  271. z = v.xyz[2] - e.xyz[2];
  272. // Geocentric equatorial coordinates of the planet
  273. ec = 23.439292*this.d2r; // obliquity of the ecliptic for the epoch the elements are referred to
  274. q = [x,y * Math.cos(ec) - z * Math.sin(ec),y * Math.sin(ec) + z * Math.cos(ec)];
  275. ra = Math.atan(q[1]/q[0])*this.r2d;
  276. if(q[0] < 0) ra += 180;
  277. if(q[0] >= 0 && q[1] < 0) ra += 360;
  278. dc = Math.atan(q[2] / Math.sqrt(q[0]*q[0] + q[1]*q[1]))*this.r2d;
  279. R = Math.sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2]);
  280. // Calculate the magnitude (http://stjarnhimlen.se/comp/tutorial.html)
  281. var angdiam = (this.planets[i].radius*2/(R*this.AUinkm));
  282. mag = 1;
  283. // planet's heliocentric distance, v.r, its geocentric distance, R, and the distance to the Sun, e.r.
  284. FV = Math.acos( ( v.r*v.r + R*R - e.r*e.r ) / (2*v.r*R) );
  285. phase = (1 + Math.cos(FV))/2;
  286. mag = this.planets[i].magnitude({a:v.r,r:v.r,R:R,FV:FV*this.r2d,x:x,y:y,z:z,jd:day,d2r:this.d2r});
  287. return [ra,dc,mag];
  288. }
  289. Planets.prototype.getHeliocentric = function(planet,jd,i){
  290. var min = 1e10;
  291. var mn,p,d,M,v,r;
  292. // Choose a set of orbital elements
  293. if(!i){
  294. // Loop over elements and pick the one closest in time
  295. for(var j = 0; j < planet.elements.length ;j++){
  296. mn = Math.abs(planet.elements[j].jd-jd);
  297. if(mn < min){
  298. i = j;
  299. min = mn;
  300. }
  301. }
  302. }
  303. p = planet.elements[i];
  304. // The day number is the number of days (decimal) since epoch of elements.
  305. d = (jd - p.jd);
  306. // Heliocentric coordinates of planet
  307. M = this.meanAnomaly(p.n,d,p.L,p.p)
  308. v = this.trueAnomaly(M*this.d2r,p.e,10);
  309. r = p.a * (1 - Math.pow(p.e,2)) / (1 + p.e * Math.cos(v*this.d2r));
  310. return {xyz: this.heliocentric(v*this.d2r,r,p.p*this.d2r,p.o*this.d2r,p.i*this.d2r), M:M, v:v, r:r, i:i, d:d, elements:p};
  311. }
  312. // Find the Mean Anomaly (M, degrees) of the planet where
  313. // n is daily motion
  314. // d is the number of days since the date of the elements
  315. // L is the mean longitude (deg)
  316. // p is the longitude of perihelion (deg)
  317. // M should be in range 0 to 360 degrees
  318. Planets.prototype.meanAnomaly = function(d,n,L,p){
  319. var M = n * d + L - p;
  320. while(M < 0) M += 360;
  321. while(M >= 360) M -= 360;
  322. return M;
  323. }
  324. // Heliocentric coordinates of the planet where:
  325. // o is longitude of ascending node (radians)
  326. // p is longitude of perihelion (radians)
  327. // i is inclination of plane of orbit (radians)
  328. // the quantity v + o - p is the angle of the planet measured in the plane of the orbit from the ascending node
  329. Planets.prototype.heliocentric = function(v,r,p,o,i){
  330. var vpo = v + p - o;
  331. var svpo = Math.sin(vpo);
  332. var cvpo = Math.cos(vpo);
  333. var co = Math.cos(o);
  334. var so = Math.sin(o);
  335. var ci = Math.cos(i);
  336. var si = Math.sin(i);
  337. return [r * (co * cvpo - so * svpo * ci),r * (so * cvpo + co * svpo * ci),r * (svpo * si)]
  338. }
  339. /*
  340. Find the True Anomaly given
  341. m - the 'mean anomaly' in orbit theory (in radians)
  342. ecc - the eccentricity of the orbit
  343. */
  344. Planets.prototype.trueAnomaly = function(m,ecc,eps){
  345. var e = m; // first guess
  346. if(typeof eps==="number"){
  347. var delta = 0.05; // set delta equal to a dummy value
  348. var eps = 10; // eps - the precision parameter - solution will be within 10^-eps of the true value. Don't set eps above 14, as convergence can't be guaranteed
  349. while(Math.abs(delta) >= Math.pow(10,-eps)){ // converged?
  350. delta = e - ecc * Math.sin(e) - m; // new error
  351. e -= delta / (1 - ecc * Math.cos(e)); // corrected guess
  352. }
  353. var v = 2 * Math.atan(Math.pow(((1 + ecc) / (1 - ecc)),0.5) * Math.tan(0.5 * e));
  354. if(v < 0) v+= Math.PI*2;
  355. }else{
  356. v = m + ( (2 * ecc - Math.pow(ecc,3)/4)*Math.sin(m) + 1.25*Math.pow(ecc,2)*Math.sin(2*m) + (13/12)*Math.pow(ecc,3)*Math.sin(3*m) );
  357. }
  358. return v*this.r2d; // return estimate
  359. }
  360. function formatRADec(ra,dec){
  361. var rah,ram,ras,dcd,dcm,dcs;
  362. ra /= 15;
  363. rah = Math.floor(ra);
  364. ram = Math.floor((ra-rah)*60);
  365. ras = (ra-rah-ram/60)*3600;
  366. dcd = Math.floor(dec);
  367. dcm = Math.floor((dec-dcd)*60);
  368. dcs = (dec-dcd-dcm/60)*3600;
  369. return (Math.abs(rah) < 10 ? "0":"")+rah+":"+(ram < 10 ? "0":"")+ram+":"+(ras < 10 ? "0":"")+ras.toFixed(2)+" "+(Math.abs(dcd) < 10 ? "0":"")+dcd+":"+(dcm < 10 ? "0":"")+dcm+":"+(dcs < 10 ? "0":"")+dcs.toFixed(2);
  370. }
  371. function getJD(today){
  372. if(!today) today = new Date();
  373. return ( today.getTime() / 86400000.0 ) + 2440587.5;
  374. }
  375. function rev(x) {
  376. return x - Math.floor(x/360.0)*360.0
  377. }
  378. function log10(x) {
  379. return Math.LOG10E * Math.log(x);
  380. }
  381. var match = false;
  382. for(var i = 0; i < $.virtualsky.plugins.length; i++){
  383. if($.virtualsky.plugins[i].name=="planets") match = true;
  384. }
  385. if(!match){
  386. $.virtualsky.plugins.push({
  387. init: init,
  388. name: 'planets',
  389. version: '1.0'
  390. });
  391. }
  392. })(jQuery);