1/** 2 * planets.js â Planet position computation for slateworks.ai 3 * 4 * Uses Astronomy Engine to compute positions of the 5 naked-eye planets, 5 * Jupiter's Galilean moons, and Saturn's ring tilt. Exposes positions as 6 * celestial XYZ (same coordinate system as star_catalog.js) via 7 * window._planetData for the WebGL renderer in stars_gl.js. 8 * 9 * Requires: astronomy.browser.min.js (Astronomy Engine by Don Cross, MIT) 10 */ 11(function () { 12 'use strict'; 13 14 if (typeof Astronomy === 'undefined') { 15 console.warn('[planets] Astronomy Engine not loaded'); 16 return; 17 } 18 19 var DEG = Math.PI / 180; 20 var RAD = 180 / Math.PI; 21 22 // Planet visual properties: body name + fixed color [r,g,b] in 0-1 23 var PLANET_DEFS = [ 24 { body: 'Mercury', color: [1.0, 0.92, 0.85] }, 25 { body: 'Venus', color: [1.0, 1.0, 0.95] }, 26 { body: 'Mars', color: [1.0, 0.6, 0.4 ] }, 27 { body: 'Jupiter', color: [1.0, 0.95, 0.85] }, 28 { body: 'Saturn', color: [1.0, 0.90, 0.70] } 29 ]; 30 31 var MOON_COLOR = [1.0, 0.95, 0.9]; 32 var MOON_NAMES = ['io', 'europa', 'ganymede', 'callisto']; 33 34 // Throttle: recompute every 200ms (5 fps ephemeris, plenty smooth even at 960x) 35 var COMPUTE_INTERVAL = 200; 36 var lastComputeTime = 0; 37 var cached = null; 38 39 // RA/Dec â celestial unit-sphere XYZ (same convention as star_catalog/stars_gl) 40 function raDecToXYZ(raHours, decDeg) { 41 var raRad = raHours * (Math.PI / 12); 42 var decRad = decDeg * DEG; 43 var cd = Math.cos(decRad); 44 return [cd * Math.cos(raRad), Math.sin(decRad), cd * Math.sin(raRad)]; 45 } 46 47 // Convert geocentric equatorial XYZ (AU) to RA (hours) and Dec (degrees) 48 function xyzToRADec(x, y, z) { 49 var dist = Math.sqrt(x * x + y * y + z * z); 50 var dec = Math.asin(z / dist) * RAD; 51 var ra = Math.atan2(y, x) * RAD / 15; // deg â hours 52 if (ra < 0) ra += 24; 53 return { ra: ra, dec: dec, dist: dist }; 54 } 55 56 function computePlanets(date) { 57 var loc = window._slateworksLocation || { lat: 34.0, lon: -118.25 }; 58 var observer = new Astronomy.Observer(loc.lat, loc.lon, 0); 59 60 var planets = []; 61 var jupiterMoons = []; 62 var saturnRingTilt = 0; 63 var jupiterGeo = null; 64 var jupiterMag = -2.5; // fallback 65 66 for (var i = 0; i < PLANET_DEFS.length; i++) { 67 var p = PLANET_DEFS[i]; 68
69 // Topocentric equatorial coordinates (RA/Dec), aberration-corrected 70 var eq = Astronomy.Equator(p.body, date, observer, true, true); 71 72 // Apparent magnitude + Saturn ring tilt 73 var illum = Astronomy.Illumination(p.body, date); 74 75 // Celestial unit-sphere XYZ 76 var xyz = raDecToXYZ(eq.ra, eq.dec); 77 78 planets.push({ 79 name: p.body, 80 xyz: xyz, 81 ra: eq.ra, 82 dec: eq.dec, 83 mag: illum.mag, 84 color: p.color 85 }); 86 87 if (p.body === 'Saturn') { 88 saturnRingTilt = illum.ring_tilt || 0; 89 } 90 91 if (p.body === 'Jupiter') { 92 jupiterGeo = Astronomy.GeoVector('Jupiter', date, true); 93 jupiterMag = illum.mag; 94 } 95 } 96 97 // Galilean moons: offset from Jupiter's geocentric position 98 if (jupiterGeo) { 99 var moons = Astronomy.JupiterMoons(date); 100 for (var m = 0; m < MOON_NAMES.length; m++) { 101 var moonName = MOON_NAMES[m]; 102 var moon = moons[moonName]; 103 104 // Moon geocentric = Jupiter geocentric + jovicentric offset (all EQJ, AU) 105 var rd = xyzToRADec( 106 jupiterGeo.x + moon.x, 107 jupiterGeo.y + moon.y, 108 jupiterGeo.z + moon.z 109 ); 110 111 jupiterMoons.push({ 112 name: moonName, 113 xyz: raDecToXYZ(rd.ra, rd.dec), 114 ra: rd.ra, 115 dec: rd.dec, 116 mag: jupiterMag / 2, 117 color: MOON_COLOR 118 }); 119 } 120 } 121 122 return { 123 planets: planets, 124 jupiterMoons: jupiterMoons, 125 saturnRingTilt: saturnRingTilt 126 }; 127 } 128 129 // Called each frame from the render loop â throttled internally 130 function update() { 131 var now = performance.now(); 132 if (cached && now - lastComputeTime < COMPUTE_INTERVAL) { 133 return cached; 134 } 135 136 // Build date from the time system (same logic as stars_gl.js) 137 var date = new Date(); 138 var oh = window._secretTimeOverride; 139 if (oh !== undefined && oh !== null) { 140 oh = (typeof oh === 'number') ? oh : parseFloat(oh); 141 // oh is in the active timezone â convert to browser-local for correct UTC 142 var activeTz = (typeof window._slateworksTzOffset === 'number') 143 ? window._slateworksTzOffset : -date.getTimezoneOffset() / 60; 144 var browserTz = -date.getTimezoneOffset() / 60; 145 var browserH = oh - activeTz + browserTz; 146 date = new Date(); 147 date.setHours(0, 0, 0, 0); 148 date.setTime(date.getTime() + browserH * 3600000); 149 } 150 151 cached = computePlanets(date); 152 window._planetData = cached; 153 lastComputeTime = now; 154 155 return cached; 156 } 157 158 window._updatePlanets = update; 159 160 // Initial computation 161 update(); 162 console.log('[planets] Init OK â 5 planets + 4 Galilean moons'); 163 164})();
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.