├── .gitignore ├── src ├── custom.constant.js ├── astronomy │ └── moshier │ │ ├── plan404 │ │ ├── index.js │ │ ├── neptune.js │ │ ├── venus.js │ │ └── mercury.js │ │ ├── vearth.js │ │ ├── deflection.js │ │ ├── epsilon.js │ │ ├── lonlat.js │ │ ├── aberration.js │ │ ├── refraction.js │ │ ├── sidereal.js │ │ ├── diurnal.js │ │ ├── light.js │ │ ├── constant.js │ │ ├── fk4fk5.js │ │ ├── altaz.js │ │ ├── julian.js │ │ ├── sun.js │ │ ├── precess.js │ │ ├── planet.js │ │ ├── body.js │ │ ├── star.js │ │ ├── processor.js │ │ ├── util.js │ │ ├── delta.js │ │ ├── moon.js │ │ ├── kepler.js │ │ ├── nutation.js │ │ ├── transit.js │ │ ├── constellation.js │ │ └── gplan.js └── common.js ├── .eslintrc.yml ├── test └── index.js ├── mise.toml ├── package.json ├── .eslintrc ├── index.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | play 2 | -------------------------------------------------------------------------------- /src/custom.constant.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | COSSUN: 6.123233995736766e-17 3 | } 4 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | browser: true 3 | commonjs: true 4 | es6: true 5 | node: true 6 | extends: 'eslint:recommended' 7 | globals: 8 | Atomics: readonly 9 | SharedArrayBuffer: readonly 10 | parserOptions: 11 | ecmaVersion: 3 12 | rules: 13 | no-unused-vars: [1, {vars: "local", args: "after-used"}] 14 | no-trailing-spaces: 2 15 | -------------------------------------------------------------------------------- /src/astronomy/moshier/plan404/index.js: -------------------------------------------------------------------------------- 1 | exports.earth = require('./earth') 2 | exports.jupiter = require('./jupiter') 3 | exports.mars = require('./mars') 4 | exports.mercury = require('./mercury') 5 | exports.moonlat = require('./moonlat') 6 | exports.moonlr = require('./moonlr') 7 | exports.neptune = require('./neptune') 8 | exports.pluto = require('./pluto') 9 | exports.saturn = require('./saturn') 10 | exports.uranus = require('./uranus') 11 | exports.venus = require('./venus') 12 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | // This file is a placeholder and needs more tests. 2 | 3 | var test = require('tape') 4 | 5 | var ephemeris = require('../') 6 | 7 | test('dummy test', function (t) { 8 | t.plan(4) 9 | var dateObj = new Date('2015-08-10T17:09:01.000+00:00') 10 | var result = ephemeris.getAllPlanets(dateObj, 10.0014, 53.5653, 0) 11 | 12 | t.equal(result.date.gregorianTerrestrial, '10.8.2015 17:9:1') 13 | t.equal(result.observer.longitudeGeodetic, 10.0014) 14 | t.equal(result.observed.sun.apparentLongitudeDms360, '137°45\'39"') 15 | t.equal(result.observed.venus.is_retrograde, false) 16 | }) 17 | -------------------------------------------------------------------------------- /mise.toml: -------------------------------------------------------------------------------- 1 | [tools] 2 | node = "20" 3 | 4 | [env] 5 | # Use the project name derived from the current directory 6 | PROJECT_NAME = "{{ config_root | basename }}" 7 | 8 | [tasks.yarninstall] 9 | description = "Install dependencies" 10 | alias = "yi" 11 | run = "yarn install" 12 | 13 | [tasks.test] 14 | description = "Run tests" 15 | alias = "t" 16 | run = "yarn run test" 17 | 18 | [tasks.lint] 19 | description = "Lint the code" 20 | run = "eslint . -f" 21 | 22 | [tasks.info] 23 | description = "Print project information" 24 | run = ''' 25 | echo "Project: $PROJECT_NAME" 26 | echo "Virtual Environment: $VIRTUAL_ENV" 27 | ''' 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ephemeris", 3 | "version": "2.2.0", 4 | "description": "JavaScript implementation of Moshier's ephemeris calculations for sun, planets, comets, asteroids and stars.", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/hemantgoswami/ephemeris" 8 | }, 9 | "main": "index.js", 10 | "scripts": { 11 | "test": "node test/index.js" 12 | }, 13 | "keywords": [ 14 | "ephemeris", 15 | "Moshier", 16 | "astronomy", 17 | "astrology", 18 | "planet", 19 | "planets" 20 | ], 21 | "author": "Hemantkumar Goswami", 22 | "license": "GPL-3.0", 23 | "devDependencies": { 24 | "eslint": "^9.32.0", 25 | "tape": "^4.13.3" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/astronomy/moshier/vearth.js: -------------------------------------------------------------------------------- 1 | var body = require('./body') 2 | var kepler = require('./kepler') 3 | 4 | var vearth = { 5 | jvearth: -1.0, 6 | vearth: {} 7 | } 8 | 9 | vearth.calc = function (date) { 10 | var e = {} 11 | 12 | if (date.julian == this.jvearth) { 13 | return 14 | } 15 | 16 | this.jvearth = date.julian 17 | 18 | /* calculate heliocentric position of the earth 19 | * as of a short time ago. 20 | */ 21 | var t = 0.005 22 | kepler.calc({julian: date.julian - t}, body.earth, e) 23 | 24 | this.vearth.longitude = (body.earth.position.rect.longitude - e.longitude) / t 25 | this.vearth.latitude = (body.earth.position.rect.latitude - e.latitude) / t 26 | this.vearth.distance = (body.earth.position.rect.distance - e.distance) / t 27 | } 28 | 29 | module.exports = vearth 30 | -------------------------------------------------------------------------------- /src/astronomy/moshier/deflection.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | var util = require('./util') 3 | 4 | var deflection = {} 5 | 6 | deflection.calc = function (p, q, e) { 7 | var C = 1.974e-8 / (constant.SE * (1 + constant.qe)) 8 | 9 | constant.dp.longitude = C * (constant.pq * e.longitude / constant.SE - constant.ep * q.longitude / constant.SO) 10 | constant.dp.latitude = C * (constant.pq * e.latitude / constant.SE - constant.ep * q.latitude / constant.SO) 11 | constant.dp.distance = C * (constant.pq * e.distance / constant.SE - constant.ep * q.distance / constant.SO) 12 | 13 | p.longitude += constant.dp.longitude 14 | p.latitude += constant.dp.latitude 15 | p.distance += constant.dp.distance 16 | 17 | return { 18 | sunElongation: Math.acos(-constant.ep) / constant.DTR, 19 | lightDeflection: util.showcor(p, constant.dp) 20 | } 21 | } 22 | 23 | module.exports = deflection 24 | -------------------------------------------------------------------------------- /src/astronomy/moshier/epsilon.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | 3 | var epsilon = { 4 | /* The results of the program are returned in these 5 | * global variables: 6 | */ 7 | /** Date for which obliquity was last computed */ 8 | jdeps: -1.0, 9 | /** The computed obliquity in radians */ 10 | eps: 0.0, 11 | /** Cosine of the obliquity */ 12 | coseps: 0.0, 13 | /** Sine of the obliquity */ 14 | sineps: 0.0 15 | } 16 | 17 | epsilon.calc = function (date) { 18 | if (date.julian == this.jdeps) { 19 | return 20 | } 21 | var T = (date.julian - 2451545) / 36525 22 | 23 | /* DE403 values. */ 24 | T /= 10 25 | this.eps = (((((((((2.45e-10 * T + 5.79e-9) * T + 2.787e-7) * T 26 | + 7.12e-7) * T - 3.905e-5) * T - 2.4967e-3) * T 27 | - 5.138e-3) * T + 1.9989) * T - 0.0175) * T - 468.33960) * T 28 | + 84381.406173 29 | this.eps *= constant.STR 30 | 31 | this.coseps = Math.cos(this.eps) 32 | this.sineps = Math.sin(this.eps) 33 | this.jdeps = date.julian 34 | } 35 | 36 | module.exports = epsilon 37 | -------------------------------------------------------------------------------- /src/astronomy/moshier/lonlat.js: -------------------------------------------------------------------------------- 1 | var epsilon = require('./epsilon') 2 | var precess = require('./precess') 3 | var util = require('./util') 4 | 5 | var lonlat = {} 6 | 7 | lonlat.calc = function (pp, date, ofdate) { 8 | /* Make local copy of position vector 9 | * and calculate radius. 10 | */ 11 | var s = { 12 | longitude: pp.longitude, 13 | latitude: pp.latitude, 14 | distance: pp.distance 15 | } 16 | 17 | var r = Math.sqrt(pp.longitude * pp.longitude 18 | + pp.latitude * pp.latitude + pp.distance * pp.distance 19 | ) 20 | 21 | /* Precess to equinox of date J */ 22 | if (ofdate) { 23 | precess.calc(s, date, -1) 24 | } 25 | 26 | /* Convert from equatorial to ecliptic coordinates */ 27 | epsilon.calc(date) 28 | var y = epsilon.coseps * s.latitude + epsilon.sineps * s.distance 29 | var z = -epsilon.sineps * s.latitude + epsilon.coseps * s.distance 30 | 31 | var yy = util.zatan2(s.longitude, y) 32 | var zz = Math.asin(z / r) 33 | 34 | return { 35 | // longitude and latitude in decimal 36 | longitude: yy, 37 | latitude: zz, 38 | distance: r, 39 | // longitude and latitude in h,m,s 40 | dLongitude: util.dms(yy), 41 | dLatitude: util.dms(zz) 42 | } 43 | } 44 | 45 | module.exports = lonlat 46 | -------------------------------------------------------------------------------- /src/common.js: -------------------------------------------------------------------------------- 1 | var common = {} 2 | 3 | common.copy = function (target /*, source ... */) { 4 | if (target) { 5 | for (var i = arguments.length - 1; i > 0; i--) { 6 | var source = arguments [i] 7 | if (source) { 8 | for (var key in source) { 9 | if (Object.prototype.hasOwnProperty.call(source, key)) { 10 | target [key] = source [key] 11 | } 12 | } 13 | } 14 | } 15 | } 16 | return target 17 | } 18 | 19 | common.is = function (object, type) { 20 | var typeName = Object.prototype.toString.call(object).slice(8, -1) 21 | return ( 22 | object !== undefined && 23 | object !== null && 24 | type.name === typeName 25 | ) 26 | } 27 | 28 | common.make = function (context, path) { 29 | if (common.is(context, String)) { 30 | path = context 31 | context = document 32 | } 33 | 34 | if (path) { 35 | var paths = path.split('.') 36 | var key = paths.shift() 37 | context [key] = context [key] || {} 38 | context = common.make(context [key], paths.join('.')) 39 | } 40 | return context 41 | } 42 | 43 | common.define = function (context, path, object) { 44 | common.copy(common.make(context, path), object) 45 | } 46 | 47 | common.assert = function (variable, value) { 48 | if (variable != value) { 49 | throw 'Assertion failed: ' + variable + ' != ' + value + '!' 50 | } 51 | } 52 | 53 | module.exports = common 54 | -------------------------------------------------------------------------------- /src/astronomy/moshier/aberration.js: -------------------------------------------------------------------------------- 1 | var body = require('./body') 2 | var constant = require('./constant') 3 | var util = require('./util') 4 | var vearth = require('./vearth') 5 | 6 | var aberration = {} 7 | 8 | aberration.calc = function (p) { 9 | /* Calculate the velocity of the earth (see vearth.js). */ 10 | vearth.calc(body.earth.position.date) 11 | 12 | var V = { 13 | longitude: vearth.vearth.longitude / constant.Clightaud, 14 | latitude: vearth.vearth.latitude / constant.Clightaud, 15 | distance: vearth.vearth.distance / constant.Clightaud 16 | } 17 | 18 | var betai = V.longitude * V.longitude 19 | + V.latitude * V.latitude 20 | + V.distance * V.distance 21 | 22 | var pV = p.longitude * V.longitude 23 | + p.latitude * V.latitude 24 | + p.distance * V.distance 25 | 26 | /* Make the adjustment for aberration. */ 27 | betai = Math.sqrt(1 - betai) 28 | var C = 1 + pV 29 | var A = betai / C 30 | var B = (1 + pV / (1 + betai)) / C 31 | 32 | var x = { 33 | longitude: A * p.longitude + B * V.longitude, 34 | latitude: A * p.latitude + B * V.latitude, 35 | distance: A * p.distance + B * V.distance 36 | } 37 | 38 | constant.dp = { 39 | longitude: x.longitude - p.longitude, 40 | latitude: x.latitude - p.latitude, 41 | distance: x.distance - p.distance 42 | } 43 | 44 | var result = util.showcor(p, constant.dp) 45 | 46 | p.longitude = x.longitude 47 | p.latitude = x.latitude 48 | p.distance = x.distance 49 | 50 | return result 51 | } 52 | 53 | module.exports = aberration 54 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 2017, 4 | "ecmaFeatures": { 5 | "sourceType": "module", 6 | "experimentalObjectRestSpread": true 7 | } 8 | }, 9 | "extends": "standard", 10 | "env": { 11 | "es6": true, 12 | "node": true, 13 | "mocha": true 14 | }, 15 | "rules": { 16 | "semi": ["error", "never"], 17 | "global-require": "error", 18 | "arrow-body-style": [2, "always"], 19 | "import/no-extraneous-dependencies": 0, 20 | "no-prototype-builtins": 0, 21 | "no-underscore-dangle": 0, 22 | "prefer-spread": 0, 23 | "new-cap": [ 24 | "error", 25 | { 26 | "newIsCapExceptions": ["tz", "duration"], 27 | "capIsNewExceptions": ["FLOAT", "Router"] 28 | } 29 | ], 30 | "comma-dangle": [ 31 | "error", 32 | { 33 | "arrays": "only-multiline", 34 | "objects": "only-multiline", 35 | "imports": "never", 36 | "exports": "never", 37 | "functions": "ignore" 38 | } 39 | ], 40 | "indent": [ 41 | "error", 42 | 2, 43 | { 44 | "VariableDeclarator": 2, 45 | "MemberExpression": 1, 46 | "FunctionDeclaration": { 47 | "parameters": "first", 48 | "body": 1 49 | }, 50 | "FunctionExpression": { 51 | "parameters": "first", 52 | "body": 1 53 | }, 54 | "CallExpression": { 55 | "arguments": 1 56 | }, 57 | "ArrayExpression": 1, 58 | "ObjectExpression": 1, 59 | "SwitchCase": 1 60 | } 61 | ] 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/astronomy/moshier/refraction.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | 3 | var refraction = {} 4 | 5 | /** 6 | * Atmospheric refraction. 7 | * Returns correction in degrees to be added to true altitude 8 | * to obtain apparent altitude. 9 | */ 10 | refraction.calc = function (alt) { 11 | if (alt < -2 || alt >= 90) { 12 | return 0 13 | } 14 | 15 | /* For high altitude angle, AA page B61 16 | * Accuracy "usually about 0.1' ". 17 | */ 18 | if (alt > 15) { 19 | return 0.00452 * constant.atpress / ((273 + constant.attemp) * Math.tan(constant.DTR * alt)) 20 | } 21 | 22 | /* Formula for low altitude is from the Almanac for Computers. 23 | * It gives the correction for observed altitude, so has 24 | * to be inverted numerically to get the observed from the true. 25 | * Accuracy about 0.2' for -20C < T < +40C and 970mb < P < 1050mb. 26 | */ 27 | 28 | /* Start iteration assuming correction = 0 */ 29 | var y = alt 30 | var D = 0.0 31 | /* Invert Almanac for Computers formula numerically */ 32 | var P = (constant.atpress - 80) / 930 33 | var Q = 4.8e-3 * (constant.attemp - 10) 34 | var y0 = y 35 | var D0 = D 36 | 37 | for (var i = 0; i < 4; i++) { 38 | var N = y + (7.31 / (y + 4.4)) 39 | N = 1 / Math.tan(constant.DTR * N) 40 | D = N * P / (60 + Q * (N + 39)) 41 | N = y - y0 42 | y0 = D - D0 - N 43 | /* denominator of derivative */ 44 | 45 | if (N != 0.0 && y0 != 0.0) { 46 | /* Newton iteration with numerically estimated derivative */ 47 | N = y - N * (alt + D - y) / y0 48 | } else { 49 | /* Can't do it on first pass */ 50 | N = alt + D 51 | } 52 | 53 | y0 = y 54 | D0 = D 55 | y = N 56 | } 57 | return D 58 | } 59 | 60 | module.exports = refraction 61 | -------------------------------------------------------------------------------- /src/astronomy/moshier/sidereal.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | var epsilon = require('./epsilon') 3 | var nutation = require('./nutation') 4 | 5 | var sidereal = {} 6 | 7 | sidereal.calc = function (date, tlong) { 8 | /** Julian day at given UT */ 9 | var jd = date.universal // UT 10 | /** Julian day at midnight Universal Time */ 11 | var jd0 = Math.floor(jd) 12 | /** Time of day, UT seconds since UT midnight */ 13 | var secs = date.julian - jd0 // UT 14 | if (secs < 0.5) { 15 | jd0 -= 0.5 16 | secs += 0.5 17 | } else { 18 | jd0 += 0.5 19 | secs -= 0.5 20 | } 21 | secs *= 86400 22 | 23 | /* Julian centuries from standard epoch J2000.0 */ 24 | /* T = (jd - J2000)/36525.0; */ 25 | /* Same but at 0h Universal Time of date */ 26 | var T0 = (jd0 - constant.j2000) / 36525 27 | 28 | /* The equation of the equinoxes is the nutation in longitude 29 | * times the cosine of the obliquity of the ecliptic. 30 | * We already have routines for these. 31 | */ 32 | nutation.calclo(date) 33 | epsilon.calc(date) 34 | /* nutl is in radians; convert to seconds of time 35 | * at 240 seconds per degree 36 | */ 37 | var eqeq = 240 * constant.RTD * nutation.nutl * epsilon.coseps 38 | /* Greenwich Mean Sidereal Time at 0h UT of date */ 39 | /* Corrections to Williams (1994) introduced in DE403. */ 40 | var gmst = (((-2.0e-6 * T0 - 3.e-7) * T0 + 9.27701e-2) * T0 + 8640184.7942063) * T0 41 | + 24110.54841 42 | var msday = (((-(4 * 2.0e-6) * T0 - (3 * 3.e-7)) * T0 + (2 * 9.27701e-2)) * T0 43 | + 8640184.7942063) / (86400 * 36525) + 1 44 | 45 | /* Local apparent sidereal time at given UT */ 46 | gmst = gmst + msday * secs + eqeq + 240 * tlong 47 | /* Sidereal seconds modulo 1 sidereal day */ 48 | gmst = gmst - 86400 * Math.floor(gmst / 86400) 49 | /* 50 | * var il = gmst/86400.0; 51 | * gmst = gmst - 86400.0 * il; 52 | * if( gmst < 0.0 ) 53 | * gmst += 86400.0; 54 | */ 55 | return gmst 56 | } 57 | 58 | module.exports = sidereal 59 | -------------------------------------------------------------------------------- /src/astronomy/moshier/diurnal.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | var util = require('./util') 3 | 4 | var diurnal = { 5 | /** Earth radii per au. */ 6 | DISFAC: 0.0 7 | } 8 | 9 | /** 10 | * Diurnal aberration 11 | * This formula is less rigorous than the method used for 12 | * annual aberration. However, the correction is small. 13 | */ 14 | diurnal.aberration = function (last, ra, dec) { 15 | var lha = last - ra 16 | var coslha = Math.cos(lha) 17 | var sinlha = Math.sin(lha) 18 | var cosdec = Math.cos(dec) 19 | var sindec = Math.sin(dec) 20 | var coslat = Math.cos(constant.DTR * constant.tlat) 21 | 22 | var N = cosdec != 0.0 ? 1.5472e-6 * constant.trho * coslat * coslha / cosdec : 0.0 23 | var D = 1.5472e-6 * constant.trho * coslat * sinlha * sindec 24 | 25 | return { 26 | ra: ra + N, 27 | dec: dec + D, 28 | dRA: constant.RTS * N / 15, 29 | dDec: constant.RTS * D 30 | } 31 | } 32 | 33 | /** Diurnal parallax, AA page D3 */ 34 | diurnal.parallax = function (last, ra, dec, dist) { 35 | /* Don't bother with this unless the equatorial horizontal parallax 36 | * is at least 0.005" 37 | */ 38 | if (dist > 1758.8) { 39 | return { 40 | ra: ra, 41 | dec: dec 42 | } 43 | } 44 | 45 | this.DISFAC = constant.au / (0.001 * constant.aearth) 46 | var cosdec = Math.cos(dec) 47 | var sindec = Math.sin(dec) 48 | 49 | /* Observer's astronomical latitude */ 50 | var x = constant.tlat * constant.DTR 51 | var coslat = Math.cos(x) 52 | var sinlat = Math.sin(x) 53 | 54 | /* Convert to equatorial rectangular coordinates 55 | * in which unit distance = earth radius 56 | */ 57 | var D = dist * this.DISFAC 58 | var p = { 59 | longitude: D * cosdec * Math.cos(ra), 60 | latitude: D * cosdec * Math.sin(ra), 61 | distance: D * sindec 62 | } 63 | var dp = { 64 | longitude: -constant.trho * coslat * Math.cos(last), 65 | latitude: -constant.trho * coslat * Math.sin(last), 66 | distance: -constant.trho * sinlat 67 | } 68 | 69 | x = p.longitude + dp.longitude 70 | var y = p.latitude + dp.latitude 71 | var z = p.distance + dp.distance 72 | /* topocentric distance */ 73 | D = Math.sqrt(x * x + y * y + z * z) 74 | 75 | var result = util.showcor(p, dp) 76 | return { 77 | ra: util.zatan2(x, y), 78 | dec: Math.asin(z / D), 79 | dRA: result.dRA, 80 | dDec: result.dDec 81 | } 82 | } 83 | 84 | module.exports = diurnal 85 | -------------------------------------------------------------------------------- /src/astronomy/moshier/light.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | var kepler = require('./kepler') 3 | var util = require('./util') 4 | var vearth = require('./vearth') 5 | 6 | var moshier = { 7 | body: require('./body') 8 | } 9 | 10 | var light = {} 11 | 12 | light.calc = function (body, q, e) { 13 | var p = {} 14 | var t // double 15 | 16 | /* save initial q-e vector for display */ 17 | var p0 = { 18 | longitude: q.longitude - e.longitude, 19 | latitude: q.latitude - e.latitude, 20 | distance: q.distance - e.distance 21 | } 22 | 23 | var E = Math.sqrt(e.longitude * e.longitude 24 | + e.latitude * e.latitude 25 | + e.distance * e.distance) 26 | 27 | for (var i = 0; i < 2; i++) { 28 | p.longitude = q.longitude - e.longitude 29 | p.latitude = q.latitude - e.latitude 30 | p.distance = q.distance - e.distance 31 | 32 | var Q = q.longitude * q.longitude 33 | + q.latitude * q.latitude 34 | + q.distance * q.distance 35 | 36 | var P = p.longitude * p.longitude 37 | + p.latitude * p.latitude 38 | + p.distance * p.distance 39 | 40 | P = Math.sqrt(P) 41 | Q = Math.sqrt(Q) 42 | /* Note the following blows up if object equals sun. */ 43 | t = (P + 1.97e-8 * Math.log((E + P + Q) / (E - P + Q))) / 173.1446327 44 | kepler.calc({julian: moshier.body.earth.position.date.julian - t}, body, q) 45 | } 46 | 47 | body.lightTime = 1440 * t 48 | 49 | /* Final object-earth vector and the amount by which it changed. */ 50 | p.longitude = q.longitude - e.longitude 51 | p.latitude = q.latitude - e.latitude 52 | p.distance = q.distance - e.distance 53 | constant.dp.longitude = p.longitude - p0.longitude 54 | constant.dp.latitude = p.latitude - p0.latitude 55 | constant.dp.distance = p.distance - p0.distance 56 | body.aberration = util.showcor(p0, constant.dp) 57 | 58 | /* Calculate dRA/dt and dDec/dt. 59 | * The desired correction of apparent coordinates is relative 60 | * to the equinox of date, but the coordinates here are 61 | * for J2000. This introduces a slight error. 62 | * 63 | * Estimate object-earth vector t days ago. We have 64 | * p(?) = q(J-t) - e(J), and must adjust to 65 | * p(J-t) = q(J-t) - e(J-t) = q(J-t) - (e(J) - Vearth * t) 66 | * = p(?) + Vearth * t. 67 | */ 68 | vearth.calc(moshier.body.earth.position.date) 69 | 70 | p.longitude += vearth.vearth.longitude * t 71 | p.latitude += vearth.vearth.latitude * t 72 | p.distance += vearth.vearth.distance * t 73 | 74 | var d = util.deltap(p, p0) 75 | /* see util.dms() */ 76 | constant.dradt = d.dr 77 | constant.ddecdt = d.dd 78 | constant.dradt /= t 79 | constant.ddecdt /= t 80 | } 81 | 82 | module.exports = light 83 | -------------------------------------------------------------------------------- /src/astronomy/moshier/constant.js: -------------------------------------------------------------------------------- 1 | var constant = { 2 | /* Standard epochs. Note Julian epochs (J) are measured in 3 | * years of 365.25 days. 4 | */ 5 | /** 2000 January 1.5 */ 6 | j2000: 2451545.0, 7 | /** 1950 January 0.923 Besselian epoch */ 8 | b1950: 2433282.423, 9 | /** 1900 January 0, 12h UT */ 10 | j1900: 2415020.0, 11 | /** Radians to hours, minutes, seconds */ 12 | RTOH: 12 / Math.PI, 13 | 14 | /** radians per degree */ 15 | DTR: 1.7453292519943295769e-2, 16 | /** degrees per radian */ 17 | RTD: 5.7295779513082320877e1, 18 | /** arc seconds per radian */ 19 | RTS: 2.0626480624709635516e5, 20 | /** radians per arc second */ 21 | STR: 4.8481368110953599359e-6, 22 | 23 | TPI: 2 * Math.PI, 24 | 25 | /** Input date */ 26 | date: {}, 27 | 28 | tlong: -71.13, /* Cambridge, Massachusetts */ // input for kinit 29 | /** geocentric */ 30 | tlat: 42.38, // input for kinit 31 | /** geodetic */ 32 | glat: 42.27, // input for kinit 33 | 34 | /* Parameters for calculation of azimuth and elevation */ 35 | /** atmospheric temperature, degrees Centigrade */ // input for kinit 36 | attemp: 12.0, 37 | /** atmospheric pressure, millibars */ // input for kinit 38 | atpress: 1010.0, 39 | 40 | /** 41 | * If this number is nonzero, then the program will return it for 42 | * delta T and not calculate anything. 43 | */ 44 | dtgiven: 0.0, // input for kinit 45 | 46 | /** Distance from observer to center of earth, in earth radii */ 47 | trho: 0.9985, 48 | flat: 298.257222, 49 | height: 0.0, 50 | 51 | /** Radius of the earth in au */ 52 | // Thanks to Min He for pointing out 53 | // this needs to be initialized early. 54 | Rearth: 0.0, // calculated in kinit 55 | 56 | /* Constants used elsewhere. These are DE403 values. */ 57 | /** Radius of the earth, in meters. */ 58 | aearth: 6378137, 59 | /** Astronomical unit, in kilometers. */ 60 | au: 1.49597870691e8, 61 | /** Earth/Moon mass ratio. */ 62 | emrat: 81.300585, 63 | /** Speed of light, km/sec */ 64 | Clight: 2.99792458e5, 65 | /** C in au/day */ 66 | Clightaud: 0.0, 67 | 68 | /** 69 | * approximate motion of right ascension and declination 70 | * of object, in radians per day 71 | */ 72 | dradt: 0.0, 73 | ddecdt: 0.0, 74 | 75 | /** earth-sun distance */ 76 | SE: 0.0, 77 | /** object-sun distance */ 78 | SO: 0.0, 79 | /** object-earth distance */ 80 | EO: 0.0, 81 | 82 | /** cosine of sun-object-earth angle */ 83 | pq: 0.0, 84 | /** -cosine of sun-earth-object angle */ 85 | ep: 0.0, 86 | /** cosine of earth-sun-object angle */ 87 | qe: 0.0, 88 | 89 | /** correction vector, saved for display */ 90 | dp: {}, 91 | 92 | /** Current kepler body */ 93 | body: {} 94 | } 95 | 96 | module.exports = constant 97 | -------------------------------------------------------------------------------- /src/astronomy/moshier/fk4fk5.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | var util = require('./util') 3 | 4 | var fk4fk5 = { 5 | /* Factors to eliminate E terms of aberration */ 6 | A: [-1.62557e-6, -3.1919e-7, -1.3843e-7], 7 | Ad: [1.244e-3, -1.579e-3, -6.60e-4], 8 | 9 | /** 10 | * Transformation matrix for unit direction vector, 11 | * and motion vector in arc seconds per century 12 | */ 13 | Mat: [ 14 | 0.9999256782, -0.0111820611, -4.8579477e-3, 15 | 2.42395018e-6, -2.710663e-8, -1.177656e-8, 16 | 0.0111820610, 0.9999374784, -2.71765e-5, 17 | 2.710663e-8, 2.42397878e-6, -6.587e-11, 18 | 4.8579479e-3, -2.71474e-5, 0.9999881997, 19 | 1.177656e-8, -6.582e-11, 2.42410173e-6, 20 | -5.51e-4, -0.238565, 0.435739, 21 | 0.99994704, -0.01118251, -4.85767e-3, 22 | 0.238514, -2.667e-3, -8.541e-3, 23 | 0.01118251, 0.99995883, -2.718e-5, 24 | -0.435623, 0.012254, 2.117e-3, 25 | 4.85767e-3, -2.714e-5, 1.00000956 26 | ] 27 | } 28 | 29 | /** 30 | * Convert FK4 B1950.0 catalogue coordinates 31 | * to FK5 J2000.0 coordinates. 32 | * AA page B58. 33 | */ 34 | fk4fk5.calc = function (p, m, el) { 35 | /* Note the direction vector and motion vector 36 | * are already supplied by rstar.c. 37 | */ 38 | m.longitude *= constant.RTS 39 | m.latitude *= constant.RTS 40 | m.distance *= constant.RTS 41 | 42 | /* motion must be in arc seconds per century */ 43 | var a = this.A[0] * p.longitude 44 | + this.A[1] * p.latitude 45 | + this.A[2] * p.distance 46 | 47 | var b = this.Ad[0] * p.longitude 48 | + this.Ad[1] * p.latitude 49 | + this.Ad[2] * p.distance 50 | 51 | /* Remove E terms of aberration from FK4 */ 52 | var R = [ 53 | p.longitude - this.A[0] + a * p.longitude, 54 | p.latitude - this.A[1] + a * p.latitude, 55 | p.distance - this.A[2] + a * p.distance, 56 | m.longitude - this.Ad[0] + b * p.longitude, 57 | m.latitude - this.Ad[1] + b * p.latitude, 58 | m.distance - this.Ad[2] + b * p.distance 59 | ] 60 | 61 | var u_i = 0 62 | var v_i = 0 63 | 64 | /* Perform matrix multiplication */ 65 | var v = this.Mat 66 | var M = [] 67 | for (var i = 0; i < 6; i++) { 68 | M[i] = 0.0 69 | for (var j = 0; j < 6; j++) { 70 | M[i] += R[u_i++] * v[v_i++] // *u++ * *v++; 71 | } 72 | } 73 | p.longitude = M[0] 74 | p.latitude = M[1] 75 | p.distance = M[2] 76 | m.longitude = M[3] 77 | m.latitude = M[4] 78 | m.distance = M[5] 79 | 80 | /* Transform the answers into J2000 catalogue entries 81 | * in radian measure. 82 | */ 83 | b = p.longitude * p.longitude + p.latitude * p.latitude 84 | var c = b + p.distance * p.distance 85 | a = Math.sqrt(c) 86 | 87 | el.ra = util.zatan2(p.longitude, p.latitude) 88 | el.dec = Math.asin(p.distance / a) 89 | 90 | /* Note motion converted back to radians per (Julian) century */ 91 | el.raMotion = (p.longitude * m.latitude - p.latitude * m.longitude) / (constant.RTS * b) 92 | el.decMotion = ( 93 | m.distance * b - p.distance * (p.longitude * m.longitude + p.latitude * m.latitude) 94 | ) / (constant.RTS * c * Math.sqrt(b)) 95 | 96 | if (el.parallax > 0) { 97 | c = p.longitude * m.longitude + p.latitude * m.latitude + p.distance * m.distance 98 | 99 | /* divide by RTS to deconvert m (and therefore c) 100 | * from arc seconds back to radians 101 | */ 102 | el.velocity = c / (21.094952663 * el.parallax * constant.RTS * a) 103 | } 104 | el.parallax = el.parallax / a 105 | /* a is dimensionless */ 106 | el.epoch = constant.j2000 107 | } 108 | 109 | module.exports = fk4fk5 110 | -------------------------------------------------------------------------------- /src/astronomy/moshier/altaz.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | var diurnal = require('./diurnal') 3 | var refraction = require('./refraction') 4 | var sidereal = require('./sidereal') 5 | var transit = require('./transit') 6 | var util = require('./util') 7 | 8 | var altaz = { 9 | azimuth: 0.0, 10 | elevation: 0.0, 11 | refracted_elevation: 0.0 12 | } 13 | 14 | altaz.calc = function (pol, date) { 15 | // var TPI = 2 * Math.PI 16 | 17 | /** local apparent sidereal time, seconds converted to radians */ 18 | var last = sidereal.calc(date, constant.tlong) * constant.DTR / 240 19 | /** local hour angle, radians */ 20 | var lha = last - pol.longitude 21 | 22 | var result = { 23 | dLocalApparentSiderealTime: last, 24 | localApparentSiderealTime: util.hms(last) 25 | } 26 | 27 | /* Display rate at which ra and dec are changing */ 28 | /* 29 | * if( prtflg ) 30 | * { 31 | * x = RTS/24.0; 32 | * N = x*dradt; 33 | * D = x*ddecdt; 34 | * if( N != 0.0 ) 35 | * printf( "dRA/dt %.2f\"/h, dDec/dt %.2f\"/h\n", N, D ); 36 | * } 37 | */ 38 | 39 | result.diurnalAberration = diurnal.aberration(last, pol.longitude, pol.latitude) 40 | var ra = result.diurnalAberration.ra 41 | var dec = result.diurnalAberration.dec 42 | 43 | /* Do rise, set, and transit times 44 | transit.js takes diurnal parallax into account, 45 | but not diurnal aberration. */ 46 | lha = last - ra 47 | result.transit = transit.calc(date, lha, dec) 48 | 49 | /* Diurnal parallax */ 50 | result.diurnalParallax = diurnal.parallax(last, ra, dec, pol.distance) 51 | ra = result.diurnalParallax.ra 52 | dec = result.diurnalParallax.dec 53 | 54 | /* Diurnal aberration */ 55 | /* diurab( last, &ra, &dec ); */ 56 | 57 | /* Convert ra and dec to altitude and azimuth */ 58 | var cosdec = Math.cos(dec) 59 | var sindec = Math.sin(dec) 60 | lha = last - ra 61 | var coslha = Math.cos(lha) 62 | var sinlha = Math.sin(lha) 63 | 64 | /* Use the geodetic latitude for altitude and azimuth */ 65 | x = constant.DTR * constant.glat 66 | var coslat = Math.cos(x) 67 | var sinlat = Math.sin(x) 68 | 69 | var N = -cosdec * sinlha 70 | var D = sindec * coslat - cosdec * coslha * sinlat 71 | var az = constant.RTD * util.zatan2(D, N) 72 | var alt = sindec * sinlat + cosdec * coslha * coslat 73 | alt = constant.RTD * Math.asin(alt) 74 | 75 | /* Store results */ 76 | this.azimuth = az 77 | this.elevation = alt 78 | /* Save unrefracted value. */ 79 | 80 | /* Correction for atmospheric refraction 81 | * unit = degrees 82 | */ 83 | D = refraction.calc(alt) 84 | alt += D 85 | this.refracted_elevation = alt 86 | 87 | /* Convert back to R.A. and Dec. */ 88 | var x = Math.cos(constant.DTR * alt) 89 | var y = Math.sin(constant.DTR * alt) 90 | var z = Math.cos(constant.DTR * az) 91 | sinlha = -x * Math.sin(constant.DTR * az) 92 | coslha = y * coslat - x * z * sinlat 93 | sindec = y * sinlat + x * z * coslat 94 | lha = util.zatan2(coslha, sinlha) 95 | 96 | y = ra 97 | /* save previous values, before refrac() */ 98 | z = dec 99 | dec = Math.asin(sindec) 100 | ra = last - lha 101 | y = ra - y 102 | /* change in ra */ 103 | while (y < -Math.PI) { 104 | y += constant.TPI 105 | } 106 | while (y > Math.PI) { 107 | y -= constant.TPI 108 | } 109 | y = constant.RTS * y / 15 110 | z = constant.RTS * (dec - z) 111 | 112 | result.atmosphericRefraction = { 113 | deg: D, 114 | dRA: y, 115 | dDec: z 116 | } 117 | 118 | result.topocentric = { 119 | altitude: alt, 120 | azimuth: az, 121 | ra: ra, 122 | dec: dec, 123 | dRA: util.hms(ra), 124 | dDec: util.dms(dec) 125 | } 126 | 127 | return result 128 | } 129 | 130 | module.exports = altaz 131 | -------------------------------------------------------------------------------- /src/astronomy/moshier/julian.js: -------------------------------------------------------------------------------- 1 | var common = require('../../common') 2 | var constant = require('./constant') 3 | var util = require('./util') 4 | 5 | var julian = {} 6 | 7 | julian.calc = function (date) { 8 | var b = 0 9 | 10 | /* The origin should be chosen to be a century year 11 | * that is also a leap year. We pick 4801 B.C. 12 | */ 13 | var year = date.year + 4800 14 | if (date.year < 0) { 15 | year += 1 16 | } 17 | 18 | /* The following magic arithmetic calculates a sequence 19 | * whose successive terms differ by the correct number of 20 | * days per calendar month. It starts at 122 = March; January 21 | * and February come after December. 22 | */ 23 | var month = date.month 24 | if (month <= 2) { 25 | month += 12 26 | year -= 1 27 | } 28 | var e = Math.floor((306 * (month + 1)) / 10) 29 | 30 | // number of centuries 31 | var centuries = Math.floor(year / 100) 32 | 33 | if (date.year <= 1582) { 34 | if (date.year == 1582) { 35 | if (date.month < 10) { 36 | b = -38 37 | } 38 | if (date.month > 10 || date.day >= 15) { 39 | // number of century years that are not leap years 40 | b = Math.floor((centuries / 4) - centuries) 41 | } 42 | } 43 | } else { 44 | b = Math.floor((centuries / 4) - centuries) 45 | } 46 | 47 | // Julian calendar years and leap years 48 | var c = Math.floor((36525 * year) / 100) 49 | 50 | /* Add up these terms, plus offset from J 0 to 1 Jan 4801 B.C. 51 | * Also fudge for the 122 days from the month algorithm. 52 | */ 53 | date.julianDate = b + c + e + date.day - 32167.5 54 | 55 | // Add time 56 | date.julianTime = (3600 * date.hours + 60 * date.minutes + date.seconds) / 86400 57 | 58 | date.julian = date.julianDate + date.julianTime 59 | 60 | date.j2000 = 2000 + (date.julian - constant.j2000) / 365.25 61 | date.b1950 = 1950 + (date.julian - constant.b1950) / 365.25 62 | date.j1900 = 1900 + (date.julian - constant.j1900) / 365.25 63 | 64 | return date.julian 65 | } 66 | 67 | julian.toGregorian = function (date) { 68 | var J = date.julian 69 | 70 | /* January 1.0, 1 A.D. */ 71 | var BC = J < 1721423.5 ? 1 : 0 72 | 73 | var jd = Math.floor(J + 0.5) 74 | /* round Julian date up to integer */ 75 | 76 | /* Find the number of Gregorian centuries 77 | * since March 1, 4801 B.C. 78 | */ 79 | var a = Math.floor((100 * jd + 3204500) / 3652425) 80 | 81 | /* Transform to Julian calendar by adding in Gregorian century years 82 | * that are not leap years. 83 | * Subtract 97 days to shift origin of JD to March 1. 84 | * Add 122 days for magic arithmetic algorithm. 85 | * Add four years to ensure the first leap year is detected. 86 | */ 87 | var c = jd + 1486 88 | if (jd >= 2299160.5) { 89 | c += a - Math.floor(a / 4) 90 | } else { 91 | c += 38 92 | } 93 | /* Offset 122 days, which is where the magic arithmetic 94 | * month formula sequence starts (March 1 = 4 * 30.6 = 122.4). 95 | */ 96 | var d = Math.floor((100 * c - 12210) / 36525) 97 | /* Days in that many whole Julian years */ 98 | var x = Math.floor((36525 * d) / 100) 99 | 100 | /* Find month and day. */ 101 | var y = Math.floor(((c - x) * 100) / 3061) 102 | var day = Math.floor(c - x - Math.floor((306 * y) / 10)) 103 | var month = Math.floor(y - 1) 104 | if (y > 13) { 105 | month -= 12 106 | } 107 | 108 | /* Get the year right. */ 109 | var year = d - 4715 110 | if (month > 2) { 111 | year -= 1 112 | } 113 | 114 | /* Fractional part of day. */ 115 | var dd = day + J - jd + 0.5 116 | 117 | if (BC) { 118 | year = year - 1 119 | } 120 | 121 | date.year = year 122 | date.month = month 123 | 124 | date.day = Math.floor(dd) 125 | 126 | /* Display fraction of calendar day 127 | * as clock time. 128 | */ 129 | dd = dd - Math.floor(dd) 130 | x = 2 * Math.PI * dd 131 | 132 | common.copy(date, util.hms(x)) 133 | 134 | return date 135 | } 136 | 137 | module.exports = julian 138 | -------------------------------------------------------------------------------- /src/astronomy/moshier/sun.js: -------------------------------------------------------------------------------- 1 | var common = require('../../common') 2 | var altaz = require('./altaz') 3 | var body = require('./body') 4 | var constant = require('./constant') 5 | var constellation = require('./constellation') 6 | var epsilon = require('./epsilon') 7 | var kepler = require('./kepler') 8 | var lonlat = require('./lonlat') 9 | var nutation = require('./nutation') 10 | var precess = require('./precess') 11 | var util = require('./util') 12 | 13 | var sun = {} 14 | 15 | sun.calc = function () { 16 | var t // double 17 | 18 | body.sun.position = body.sun.position || {} 19 | 20 | /* Display ecliptic longitude and latitude. */ 21 | var ecr = { 22 | longitude: -body.earth.position.rect.longitude, 23 | latitude: -body.earth.position.rect.latitude, 24 | distance: -body.earth.position.rect.distance 25 | } 26 | 27 | var pol = body.sun.position.equinoxEclipticLonLat = lonlat.calc(ecr, body.earth.position.date, true) // TDT 28 | 29 | /* Philosophical note: the light time correction really affects 30 | * only the Sun's barycentric position; aberration is due to 31 | * the speed of the Earth. In Newtonian terms the aberration 32 | * is the same if the Earth is standing still and the Sun moving 33 | * or vice versa. Thus the following is actually wrong, but it 34 | * differs from relativity only in about the 8th decimal. 35 | * It should be done the same way as the corresponding planetary 36 | * correction, however. 37 | */ 38 | pol.distance = body.earth.position.polar.distance // eapolar[2]; 39 | for (var i = 0; i < 2; i++) { 40 | t = pol.distance / 173.1446327 41 | /* Find the earth at time TDT - t */ 42 | kepler.calc({julian: body.earth.position.date.julian - t}, body.earth, ecr, pol) 43 | } 44 | 45 | /* position t days ago */ 46 | ecr = { 47 | longitude: -ecr.longitude, 48 | latitude: -ecr.latitude, 49 | distance: -ecr.distance 50 | } 51 | 52 | /* position now */ 53 | var rec = { 54 | longitude: -body.earth.position.rect.longitude, // -rearth[0]; 55 | latitude: -body.earth.position.rect.latitude, // -rearth[1]; 56 | distance: -body.earth.position.rect.distance // -rearth[2]; 57 | } 58 | 59 | /* change in position */ 60 | pol = { 61 | longitude: rec.longitude - ecr.longitude, 62 | latitude: rec.latitude - ecr.latitude, 63 | distance: rec.distance - ecr.distance 64 | } 65 | 66 | common.copy(body.sun.position, { 67 | date: body.earth.position.date, 68 | lightTime: 1440 * t, 69 | aberration: util.showcor(ecr, pol) 70 | }) 71 | 72 | /* Estimate rate of change of RA and Dec 73 | * for use by altaz(). 74 | */ 75 | var d = util.deltap(ecr, rec) 76 | /* see util.dms() */ 77 | constant.dradt = d.dr 78 | constant.ddecdt = d.dd 79 | constant.dradt /= t 80 | constant.ddecdt /= t 81 | 82 | /* There is no light deflection effect. 83 | * AA page B39. 84 | */ 85 | 86 | /* precess to equinox of date */ 87 | precess.calc(ecr, body.earth.position.date, -1) 88 | 89 | rec = { 90 | longitude: ecr.longitude, 91 | latitude: ecr.latitude, 92 | distance: ecr.distance 93 | } 94 | 95 | /* Nutation */ 96 | epsilon.calc(body.earth.position.date) 97 | nutation.calc(body.earth.position.date, ecr) 98 | 99 | /* Display the final apparent R.A. and Dec. 100 | * for equinox of date. 101 | */ 102 | body.sun.position.constellation = constellation.calc(ecr, body.earth.position.date) 103 | 104 | body.sun.position.apparent = util.showrd(ecr, pol) 105 | 106 | /* Show it in ecliptic coordinates */ 107 | var y = epsilon.coseps * rec.latitude + epsilon.sineps * rec.distance 108 | y = util.zatan2(rec.longitude, y) + nutation.nutl 109 | body.sun.position.apparentLongitude = constant.RTD * y 110 | var dmsLongitude = util.dms(y) 111 | body.sun.position.apparentLongitudeString = 112 | dmsLongitude.degree + '\u00B0' + 113 | dmsLongitude.minutes + '\'' + 114 | Math.floor(dmsLongitude.seconds) + '"' 115 | 116 | body.sun.position.apparentLongitude30String = 117 | util.mod30(dmsLongitude.degree) + '\u00B0' + 118 | dmsLongitude.minutes + '\'' + 119 | Math.floor(dmsLongitude.seconds) + '"' 120 | 121 | body.sun.position.geocentricDistance = -1 122 | 123 | /* Report altitude and azimuth */ 124 | body.sun.position.altaz = altaz.calc(pol, body.earth.position.date) 125 | } 126 | 127 | module.exports = sun 128 | -------------------------------------------------------------------------------- /src/astronomy/moshier/precess.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | var epsilon = require('./epsilon') 3 | 4 | var precess = { 5 | /* In WILLIAMS and SIMON, Laskar's terms of order higher than t^4 6 | have been retained, because Simon et al mention that the solution 7 | is the same except for the lower order terms. */ 8 | pAcof: [ 9 | /* Corrections to Williams (1994) introduced in DE403. */ 10 | -8.66e-10, -4.759e-8, 2.424e-7, 1.3095e-5, 1.7451e-4, -1.8055e-3, 11 | -0.235316, 0.076, 110.5414, 50287.91959 12 | ], 13 | /** Pi from Williams' 1994 paper, in radians. No change in DE403. */ 14 | nodecof: [ 15 | 6.6402e-16, -2.69151e-15, -1.547021e-12, 7.521313e-12, 1.9e-10, 16 | -3.54e-9, -1.8103e-7, 1.26e-7, 7.436169e-5, 17 | -0.04207794833, 3.052115282424 18 | ], 19 | /** Pi from Williams' 1994 paper, in radians. No change in DE403. */ 20 | inclcof: [ 21 | 1.2147e-16, 7.3759e-17, -8.26287e-14, 2.503410e-13, 2.4650839e-11, 22 | -5.4000441e-11, 1.32115526e-9, -6.012e-7, -1.62442e-5, 23 | 0.00227850649, 0.0 24 | ] 25 | } 26 | 27 | /** 28 | * Precession of the equinox and ecliptic 29 | * from epoch Julian date J to or from J2000.0 30 | * 31 | * Subroutine arguments: 32 | * 33 | * R = rectangular equatorial coordinate vector to be precessed. 34 | * The result is written back into the input vector. 35 | * J = Julian date 36 | * direction = 37 | * Precess from J to J2000: direction = 1 38 | * Precess from J2000 to J: direction = -1 39 | * Note that if you want to precess from J1 to J2, you would 40 | * first go from J1 to J2000, then call the program again 41 | * to go from J2000 to J2. 42 | */ 43 | precess.calc = function (R, date, direction) { 44 | var p_i = 0 45 | var i // int 46 | 47 | if (date.julian == constant.j2000) { 48 | return 49 | } 50 | /* Each precession angle is specified by a polynomial in 51 | * T = Julian centuries from J2000.0. See AA page B18. 52 | */ 53 | var T = (date.julian - constant.j2000) / 36525 54 | 55 | /* Implementation by elementary rotations using Laskar's expansions. 56 | * First rotate about the x axis from the initial equator 57 | * to the ecliptic. (The input is equatorial.) 58 | */ 59 | if (direction == 1) { 60 | /* To J2000 */ 61 | epsilon.calc(date) 62 | } else { 63 | /* From J2000 */ 64 | epsilon.calc({julian: constant.j2000}) 65 | } 66 | var z = epsilon.coseps * R.latitude + epsilon.sineps * R.distance 67 | var x = { 68 | longitude: R.longitude, 69 | latitude: z, 70 | distance: -epsilon.sineps * R.latitude + epsilon.coseps * R.distance 71 | } 72 | 73 | /* Precession in longitude */ 74 | T /= 10 75 | /* thousands of years */ 76 | var p = this.pAcof 77 | var pA = p[p_i++] // *p++; 78 | for (i = 0; i < 9; i++) { 79 | pA = pA * T + p[p_i++] // *p++; 80 | } 81 | pA *= constant.STR * T 82 | 83 | /* Node of the moving ecliptic on the J2000 ecliptic. */ 84 | p = this.nodecof 85 | p_i = 0 86 | var W = p[p_i++] // *p++; 87 | for (i = 0; i < 10; i++) { 88 | W = W * T + p[p_i++] // *p++; 89 | } 90 | 91 | /* Rotate about z axis to the node. */ 92 | z = direction == 1 ? W + pA : W 93 | var B = Math.cos(z) 94 | var A = Math.sin(z) 95 | z = B * x.longitude + A * x.latitude 96 | x.latitude = -A * x.longitude + B * x.latitude 97 | x.longitude = z 98 | 99 | /* Rotate about new x axis by the inclination of the moving 100 | * ecliptic on the J2000 ecliptic. 101 | */ 102 | p = this.inclcof 103 | p_i = 0 104 | z = p[p_i++] // *p++; 105 | for (i = 0; i < 10; i++) { 106 | z = z * T + p[p_i++] // *p++; 107 | } 108 | if (direction == 1) { 109 | z = -z 110 | } 111 | B = Math.cos(z) 112 | A = Math.sin(z) 113 | z = B * x.latitude + A * x.distance 114 | x.distance = -A * x.latitude + B * x.distance 115 | x.latitude = z 116 | 117 | /* Rotate about new z axis back from the node. */ 118 | z = direction == 1 ? -W : -W - pA 119 | B = Math.cos(z) 120 | A = Math.sin(z) 121 | z = B * x.longitude + A * x.latitude 122 | x.latitude = -A * x.longitude + B * x.latitude 123 | x.longitude = z 124 | 125 | /* Rotate about x axis to final equator. */ 126 | if (direction == 1) { 127 | epsilon.calc({julian: constant.j2000}) 128 | } else { 129 | epsilon.calc(date) 130 | } 131 | z = epsilon.coseps * x.latitude - epsilon.sineps * x.distance 132 | x.distance = epsilon.sineps * x.latitude + epsilon.coseps * x.distance 133 | x.latitude = z 134 | 135 | R.longitude = x.longitude 136 | R.latitude = x.latitude 137 | R.distance = x.distance 138 | } 139 | 140 | module.exports = precess 141 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var constant = require('./src/astronomy/moshier/constant') 4 | var processor = require('./src/astronomy/moshier/processor') 5 | var body = require('./src/astronomy/moshier/body') 6 | 7 | function setUp (date, geodeticalLongitude, geodeticalLatitude, height) { 8 | var d = !date ? new Date() : date 9 | constant.tlong = geodeticalLongitude 10 | constant.glat = geodeticalLatitude 11 | constant.height = height 12 | constant.date = { 13 | day: d.getUTCDate(), 14 | month: d.getUTCMonth()+1, 15 | year: d.getUTCFullYear(), 16 | hours: d.getUTCHours(), 17 | minutes: d.getUTCMinutes(), 18 | seconds: d.getUTCSeconds() 19 | } 20 | processor.init() 21 | } 22 | 23 | // Example call: getAllPlanets(new Date(), 10.0014, 53.5653, 0); 24 | function getAllPlanets (date, geodeticalLongitude, geodeticalLatitude, height) { 25 | 26 | setUp(date, geodeticalLongitude, geodeticalLatitude, height) 27 | 28 | var ret = { 29 | date: undefined, 30 | observer: undefined, 31 | observed: {} 32 | } 33 | date = constant.date 34 | var observables = Object.keys(body) 35 | 36 | for (var i = 0; i < observables.length; i++) { 37 | 38 | var observeMe = observables[i] 39 | if (['earth', 'init'].indexOf(observeMe) >= 0) { 40 | continue 41 | } 42 | 43 | constant.body = body[observeMe] 44 | 45 | processor.calc(date, constant.body) 46 | 47 | if (ret.date === undefined) { 48 | ret.date = { 49 | gregorianTerrestrial: [date.day, date.month, date.year].join('.') 50 | + ' ' + [date.hours, date.minutes, date.seconds].join(':'), 51 | gregorianTerrestrialRaw: date, 52 | gregorianUniversal: constant.date.universalDateString, 53 | gregorianDelta: '00:00:' + constant.date.delta, 54 | julianTerrestrial: constant.date.julian, 55 | julianUniversal: constant.date.universal, 56 | julianDelta: constant.date.delta / 86400 57 | } 58 | } 59 | 60 | if (ret.observer === undefined) { 61 | ret.observer = { 62 | name: 'earth', 63 | longitudeGeodetic: constant.tlong, 64 | longitudeGeocentric: constant.tlong, 65 | latitudeGeodetic: constant.glat, 66 | latitudeGeocentric: constant.tlat, 67 | heightGeodetic: constant.height, 68 | heightGeocentric: constant.trho * constant.aearth / 1000 69 | } 70 | } 71 | 72 | ret.observed[constant.body.key] = { 73 | name: constant.body.key, 74 | raw: constant.body, 75 | apparentLongitudeDms30: constant.body.position.apparentLongitude30String, 76 | apparentLongitudeDms360: constant.body.position.apparentLongitudeString, 77 | apparentLongitudeDd: constant.body.position.apparentLongitude, 78 | geocentricDistanceKm: constant.body.position.geocentricDistance, 79 | is_retrograde: constant.body.position.is_retrograde 80 | } 81 | 82 | } 83 | 84 | return ret 85 | } 86 | 87 | // Example call: getPlanet('moon', new Date(), 10.0014, 53.5653, 0); 88 | function getPlanet (planetName, date, geodeticalLongitude, geodeticalLatitude, height) { 89 | 90 | setUp(date, geodeticalLongitude, geodeticalLatitude, height) 91 | 92 | var ret = { 93 | date: undefined, 94 | observer: undefined, 95 | observed: {} 96 | } 97 | date = constant.date 98 | 99 | constant.body = body[planetName] 100 | 101 | processor.calc(date, constant.body) 102 | 103 | if (ret.date === undefined) { 104 | ret.date = { 105 | gregorianTerrestrial: [date.day, date.month, date.year].join('.') 106 | + ' ' + [date.hours, date.minutes, date.seconds].join(':'), 107 | gregorianTerrestrialRaw: date, 108 | gregorianUniversal: constant.date.universalDateString, 109 | gregorianDelta: '00:00:' + constant.date.delta, 110 | julianTerrestrial: constant.date.julian, 111 | julianUniversal: constant.date.universal, 112 | julianDelta: constant.date.delta / 86400 113 | } 114 | } 115 | 116 | if (ret.observer === undefined) { 117 | ret.observer = { 118 | name: 'earth', 119 | longitudeGeodetic: constant.tlong, 120 | longitudeGeocentric: constant.tlong, 121 | latitudeGeodetic: constant.glat, 122 | latitudeGeocentric: constant.tlat, 123 | heightGeodetic: constant.height, 124 | heightGeocentric: constant.trho * constant.aearth / 1000 125 | } 126 | } 127 | 128 | ret.observed[constant.body.key] = { 129 | name: constant.body.key, 130 | raw: constant.body, 131 | apparentLongitudeDms30: constant.body.position.apparentLongitude30String, 132 | apparentLongitudeDms360: constant.body.position.apparentLongitudeString, 133 | apparentLongitudeDd: constant.body.position.apparentLongitude, 134 | geocentricDistanceKm: constant.body.position.geocentricDistance, 135 | is_retrograde: constant.body.position.is_retrograde 136 | } 137 | 138 | return ret 139 | } 140 | 141 | module.exports = { 142 | getAllPlanets: getAllPlanets, 143 | getPlanet: getPlanet 144 | } 145 | -------------------------------------------------------------------------------- /src/astronomy/moshier/planet.js: -------------------------------------------------------------------------------- 1 | var aberration = require('./aberration') 2 | var altaz = require('./altaz') 3 | var constant = require('./constant') 4 | var constellation = require('./constellation') 5 | var deflection = require('./deflection') 6 | var epsilon = require('./epsilon') 7 | var kepler = require('./kepler') 8 | var light = require('./light') 9 | var lonlat = require('./lonlat') 10 | var nutation = require('./nutation') 11 | var precess = require('./precess') 12 | var util = require('./util') 13 | 14 | var moshier = { 15 | body: require('./body') 16 | } 17 | 18 | var planet = {} 19 | 20 | planet.calc = function (body) { 21 | this.prepare(body) 22 | 23 | /* calculate heliocentric position of the object */ 24 | kepler.calc(moshier.body.earth.position.date, body) 25 | /* apply correction factors and print apparent place */ 26 | this.reduce(body, body.position.rect, moshier.body.earth.position.rect) 27 | } 28 | 29 | /** 30 | * The following program reduces the heliocentric equatorial 31 | * rectangular coordinates of the earth and object that 32 | * were computed by kepler() and produces apparent geocentric 33 | * right ascension and declination. 34 | */ 35 | planet.reduce = function (body, q, e) { 36 | /* Save the geometric coordinates at TDT */ 37 | var temp = { 38 | longitude: q.longitude, 39 | latitude: q.latitude, 40 | distance: q.distance 41 | } 42 | 43 | /* Display ecliptic longitude and latitude, precessed to equinox 44 | of date. */ 45 | var polar = body.equinoxEclipticLonLat = lonlat.calc(q, moshier.body.earth.position.date, true) 46 | 47 | /* Adjust for light time (planetary aberration) */ 48 | light.calc(body, q, e) 49 | 50 | /* Find Euclidean vectors between earth, object, and the sun */ 51 | var p = { 52 | longitude: q.longitude - e.longitude, 53 | latitude: q.latitude - e.latitude, 54 | distance: q.distance - e.distance 55 | } 56 | 57 | util.angles(p, q, e) 58 | 59 | var b = temp.longitude - e.longitude 60 | var a = b * b 61 | b = temp.latitude - e.latitude 62 | a += b * b 63 | b = temp.distance - e.distance 64 | a += b * b 65 | body.position.trueGeocentricDistance = Math.sqrt(a) 66 | 67 | /* was EO */ 68 | body.position.equatorialDiameter = 2 * body.semiDiameter / constant.EO 69 | 70 | /* Calculate visual magnitude. 71 | * "Visual" refers to the spectrum of visible light. 72 | * Phase = 0.5(1+pq) = geometric fraction of disc illuminated. 73 | * where pq = cos( sun-object-earth angle ) 74 | * The magnitude is 75 | * V(1,0) + 2.5 log10( SE^2 SO^2 / Phase) 76 | * where V(1,0) = elemnt->mag is the magnitude at 1au from 77 | * both earth and sun and 100% illumination. 78 | */ 79 | var phase = 0.5 * (1 + constant.pq) 80 | /* Fudge the phase for light leakage in magnitude estimation. 81 | * Note this phase term estimate does not reflect reality well. 82 | * Calculated magnitudes of Mercury and Venus are inaccurate. 83 | */ 84 | var x = 0.5 * (1.01 + 0.99 * constant.pq) 85 | var magnitude = body.magnitude + 2.1715 * Math.log(constant.EO * constant.SO) - 1.085 * Math.log(x) 86 | body.position.approxVisual = { 87 | magnitude: magnitude, 88 | phase: phase 89 | } 90 | 91 | /* Find unit vector from earth in direction of object */ 92 | p.longitude /= constant.EO 93 | p.latitude /= constant.EO 94 | p.distance /= constant.EO 95 | 96 | temp = { 97 | longitude: p.longitude, 98 | latitude: p.latitude, 99 | distance: p.distance 100 | } 101 | 102 | /* Report astrometric position */ 103 | body.position.astrometricJ2000 = util.showrd(p, polar) 104 | 105 | /* Also in 1950 coordinates */ 106 | precess.calc(temp, {julian: constant.b1950}, -1) 107 | body.position.astrometricB1950 = util.showrd(temp, polar) 108 | 109 | /* Correct position for light deflection */ 110 | body.position.deflection = deflection.calc(p, q, e) // relativity 111 | 112 | /* Correct for annual aberration */ 113 | body.position.aberration = aberration.calc(p) 114 | 115 | /* Precession of the equinox and ecliptic 116 | * from J2000.0 to ephemeris date 117 | */ 118 | precess.calc(p, moshier.body.earth.position.date, -1) 119 | 120 | /* Adjust for nutation at current ecliptic. */ 121 | epsilon.calc(moshier.body.earth.position.date) 122 | body.position.nutation = nutation.calc(moshier.body.earth.position.date, p) 123 | 124 | /* Display the final apparent R.A. and Dec. 125 | * for equinox of date. 126 | */ 127 | body.position.constellation = constellation.calc(p, moshier.body.earth.position.date) 128 | body.position.apparent = util.showrd(p, polar) 129 | 130 | /* Geocentric ecliptic longitude and latitude. */ 131 | p.longitude *= constant.EO 132 | p.latitude *= constant.EO 133 | p.distance *= constant.EO 134 | 135 | body.position.apparentGeocentric = lonlat.calc(p, moshier.body.earth.position.date, false) 136 | body.position.apparentGeocentric_prev_date = lonlat.calc(p, constant.retro_date, false) 137 | body.position.apparentLongitude = body.position.apparentGeocentric.longitude * constant.RTD 138 | body.position.apparentLongitudeString = 139 | body.position.apparentGeocentric.dLongitude.degree + '\u00B0' + 140 | body.position.apparentGeocentric.dLongitude.minutes + '\'' + 141 | Math.floor(body.position.apparentGeocentric.dLongitude.seconds) + '"' 142 | var p1 = body.position.apparentGeocentric_prev_date.dLongitude 143 | var p2 = body.position.apparentGeocentric.dLongitude 144 | body.position.is_retrograde = (util.degreesToDecimal(p1['degree'], p1['minutes'], p1['seconds']) - util.degreesToDecimal(p2['degree'], p2['minutes'], p2['seconds'])) < 0 145 | 146 | body.position.apparentLongitude30String = 147 | util.mod30(body.position.apparentGeocentric.dLongitude.degree) + '\u00B0' + 148 | body.position.apparentGeocentric.dLongitude.minutes + '\'' + 149 | Math.floor(body.position.apparentGeocentric.dLongitude.seconds) + '"' 150 | 151 | body.position.geocentricDistance = -1 152 | 153 | /* Go do topocentric reductions. */ 154 | polar.distance = constant.EO 155 | body.position.altaz = altaz.calc(polar, moshier.body.earth.position.date) 156 | } 157 | 158 | planet.prepare = function (body) { 159 | if (!body.semiAxis) { 160 | body.semiAxis = body.perihelionDistance / (1 - body.eccentricity) 161 | } 162 | } 163 | 164 | module.exports = planet 165 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This source is modified version of [xerik](https://www.npmjs.com/package/ephemeris-moshier). Thank you for such a brilliant piece of work. 2 | 3 | This is basically JavaScript implementation of [Moshier's ephemeris](http://www.moshier.net) calculations for sun, planets, comets, asteroids and stars. 4 | 5 | Which, initially written by [mivion](https://github.com/mivion/ephemeris), xerik converted it into a node module. This is a slight customized version with following changes: 6 | 7 | 1. Changes the transit method to get standard sun/moon rise/set times as well as a custom horizon based 8 | 1. Takes in JavaScript date object as opposed to a date time string 9 | 1. Implements a method to just fetch in single planet as opposed to all of it 10 | 1. Removes html, css bit to keep it focused to one task 11 | 1. Reformats the code 12 | 13 | ### Installation 14 | 15 | `npm install ephemeris` 16 | 17 | ### Changelog 18 | 19 | #### 2.2.0 Feature added 20 | * Adds retrograde flag for planets 21 | 22 | #### 2.0.0 Breaking Changes - Please read carefully 23 | * Released 5th July 2020 24 | * Removes dependency on Moment.js and uses JavaScript's default date object 25 | * Fixes names of a few variables as there were typos (Thanks [Erik](https://github.com/stenflo) for these changes) 26 | 27 | #### 1.0.0 28 | * Released 30th June 2020 29 | * updates test and fixes test 30 | 31 | 32 | ### Usage 33 | 34 | *app.js* 35 | ```javascript 36 | const ephemeris = require('ephemeris'); 37 | const dateObj = new Date('2015-08-10T17:09:01.000+08:00'); 38 | 39 | // parameters: ephemeris.getAllPlanets(dateObj, longitude, latitude, height); 40 | var result = ephemeris.getAllPlanets(dateObj, 10.0014, 53.5653, 0); 41 | 42 | /* Check out the namespaces: date, observer and observed: 43 | 44 | { date: 45 | { gregorianTerrestrial: '10.8.2015 17:9:1', 46 | gregorianTerrestrialRaw: 47 | { day: 10, 48 | month: 8, 49 | year: 2015, 50 | hours: 17, 51 | minutes: 9, 52 | seconds: 1, 53 | julianDate: 2457244.5, 54 | julianTime: 0.7145949074074074, 55 | julian: 2457245.2145949076, 56 | j2000: 2015.6063370154895, 57 | b1950: 2015.6065478300004, 58 | j1900: 2015.6063370154895, 59 | delta: 68.01714323102905, 60 | terrestrial: 2457245.2145949076, 61 | universal: 2457245.2138076723, 62 | universalDate: [Object], 63 | universalDateString: '10.8.2015 17:7:52.983' }, 64 | gregorianUniversal: '10.8.2015 17:7:52.983', 65 | gregorianDelta: '00:00:68.01714323102905', 66 | julianTerrestrial: 2457245.2145949076, 67 | julianUniversal: 2457245.2138076723, 68 | julianDelta: 0.0007872354540628362 }, 69 | observer: 70 | { name: 'earth', 71 | longitudeGeodetic: 10.0014, 72 | longitudeGeocentric: 10.0014, 73 | latitudeGeodetic: 53.5653, 74 | latitudeGeocentric: 53.38123133267187, 75 | heightGeodetic: 0, 76 | heightGeocentric: 6364.336264644461 }, 77 | observed: 78 | { sun: 79 | { name: 'sun', 80 | raw: [Object], 81 | apparentLongitudeDms30: '17°45\'39"', 82 | apparentLongitudeDms360: '137°45\'39"', 83 | apparentLongitudeDd: 137.76105855382917, 84 | geocentricDistanceKm: -1 }, 85 | mercury: 86 | { name: 'mercury', 87 | raw: [Object], 88 | apparentLongitudeDms30: '5°2\'10"', 89 | apparentLongitudeDms360: '155°2\'10"', 90 | apparentLongitudeDd: 155.03637003916958, 91 | geocentricDistanceKm: -1 }, 92 | venus: 93 | { name: 'venus', 94 | raw: [Object], 95 | apparentLongitudeDms30: '25°43\'16"', 96 | apparentLongitudeDms360: '145°43\'16"', 97 | apparentLongitudeDd: 145.7212923824036, 98 | geocentricDistanceKm: -1 }, 99 | moon: 100 | { name: 'moon', 101 | raw: [Object], 102 | apparentLongitudeDms30: '2°41\'17"', 103 | apparentLongitudeDms360: '92°41\'17"', 104 | apparentLongitudeDd: 92.68823373136327, 105 | geocentricDistanceKm: 61.007764233212335 }, 106 | mars: 107 | { name: 'mars', 108 | raw: [Object], 109 | apparentLongitudeDms30: '1°7\'20"', 110 | apparentLongitudeDms360: '121°7\'20"', 111 | apparentLongitudeDd: 121.12222806696656, 112 | geocentricDistanceKm: -1 }, 113 | jupiter: 114 | { name: 'jupiter', 115 | raw: [Object], 116 | apparentLongitudeDms30: '29°50\'16"', 117 | apparentLongitudeDms360: '149°50\'16"', 118 | apparentLongitudeDd: 149.83799891400335, 119 | geocentricDistanceKm: -1 }, 120 | saturn: 121 | { name: 'saturn', 122 | raw: [Object], 123 | apparentLongitudeDms30: '28°20\'25"', 124 | apparentLongitudeDms360: '238°20\'25"', 125 | apparentLongitudeDd: 238.34045318452542, 126 | geocentricDistanceKm: -1 }, 127 | uranus: 128 | { name: 'uranus', 129 | raw: [Object], 130 | apparentLongitudeDms30: '20°24\'33"', 131 | apparentLongitudeDms360: '20°24\'33"', 132 | apparentLongitudeDd: 20.40921989582207, 133 | geocentricDistanceKm: -1 }, 134 | neptune: 135 | { name: 'neptune', 136 | raw: [Object], 137 | apparentLongitudeDms30: '8°58\'37"', 138 | apparentLongitudeDms360: '338°58\'37"', 139 | apparentLongitudeDd: 338.9771304673532, 140 | geocentricDistanceKm: -1 }, 141 | pluto: 142 | { name: 'pluto', 143 | raw: [Object], 144 | apparentLongitudeDms30: '13°27\'13"', 145 | apparentLongitudeDms360: '283°27\'13"', 146 | apparentLongitudeDd: 283.4537823191463, 147 | geocentricDistanceKm: -1 }, 148 | chiron: 149 | { name: 'chiron', 150 | raw: [Object], 151 | apparentLongitudeDms30: '20°41\'58"', 152 | apparentLongitudeDms360: '350°41\'58"', 153 | apparentLongitudeDd: 350.6995558283406, 154 | geocentricDistanceKm: -1 }, 155 | sirius: 156 | { name: 'sirius', 157 | raw: [Object], 158 | apparentLongitudeDms30: '11°27\'17"', 159 | apparentLongitudeDms360: '101°27\'17"', 160 | apparentLongitudeDd: 1.7707222368344282, 161 | geocentricDistanceKm: 7777 } } } 162 | */ 163 | ``` 164 | 165 | ### Contributors 166 | 167 | This implementation based on code by [Steve Moshier](http://www.moshier.net). 168 | 169 | The initial JavaScript code has been written by [xerik](https://github.com/xErik/ephemeris-moshier). 170 | 171 | 172 | ### License 173 | 174 | [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) 175 | -------------------------------------------------------------------------------- /src/astronomy/moshier/body.js: -------------------------------------------------------------------------------- 1 | var plan404 = require('./plan404') 2 | 3 | /** 4 | * body definition 5 | * 6 | * // body 7 | * epoch: epoch = epoch of orbital elements 8 | * inclination: i = inclination 9 | * node: W = longitude of the ascending node 10 | * perihelion: w = argument of the perihelion 11 | * semiAxis: a = mean distance (semimajor axis), if 0.0 then = perihelionDistance / (1 - eccentricity) 12 | * dailyMotion: dm = daily motion, if 0.0 will be calculated 13 | * eccentricity: ecc = eccentricity 14 | * anomaly: M = mean anomaly 15 | * equinox: equinox = epoch of equinox and ecliptic 16 | * magnitude: mag = visual magnitude at 1AU from earth and sun 17 | * semiDiameter: sdiam = equatorial semidiameter at 1au, arc seconds 18 | * perihelionDistance: perihelion distance 19 | * // computed values 20 | * longitude: L = computed mean longitude 21 | * distance: r = computed radius vector 22 | * perturbation plat = perturbation in ecliptic latitude 23 | * 24 | * // star 25 | * ra: ra = right ascension, radians 26 | * dec: dec = declination, radians 27 | * parallax: px = parallax, radians 28 | * raMotion: mura = proper motion in R.A., rad/century 29 | * decMotion: mudec = proper motion in Dec., rad/century 30 | * velocity: v = radial velocity, km/s 31 | * equinox: equinox = epoch of equinox and ecliptic 32 | * magnitude: mag = visual magnitude 33 | * 34 | * // constellation 35 | * index: index of constellation (1-88) 36 | * raLow: lower right ascension, in units of hours times 3600 37 | * raHight: upper right ascension, in units of hours times 3600 38 | * dec0: lower declination, in units of degrees times 3600 39 | */ 40 | var body = { 41 | /** 42 | * Sun 43 | */ 44 | sun: { 45 | weight: 100 46 | }, 47 | 48 | /* 49 | * Planets 50 | */ 51 | mercury: { 52 | epoch: 2446800.5, // 05.01.1987 53 | inclination: 7.0048, 54 | node: 48.177, 55 | perihelion: 29.074, 56 | semiAxis: 0.387098, 57 | dailyMotion: 4.09236, 58 | eccentricity: 0.205628, 59 | anomaly: 198.7199, 60 | equinox: {julian: 2446800.5}, 61 | magnitude: -0.42, 62 | semiDiameter: 3.36 63 | }, 64 | venus: { 65 | epoch: 2446800.5, // 05.01.1987 66 | inclination: 3.3946, 67 | node: 76.561, 68 | perihelion: 54.889, 69 | semiAxis: 0.723329, 70 | dailyMotion: 1.60214, 71 | eccentricity: 0.006757, 72 | anomaly: 9.0369, 73 | equinox: {julian: 2446800.5}, 74 | /* Note the calculated apparent visual magnitude for Venus 75 | * is not very accurate. 76 | */ 77 | magnitude: -4.40, 78 | semiDiameter: 8.34 79 | }, 80 | earth: { 81 | epoch: 2446800.5, // 05.01.1987 82 | inclination: 0.0, 83 | node: 0.0, 84 | perihelion: 102.884, 85 | semiAxis: 0.999999, 86 | dailyMotion: 0.985611, 87 | eccentricity: 0.016713, 88 | anomaly: 1.1791, 89 | equinox: {julian: 2446800.5}, 90 | magnitude: -3.86, 91 | semiDiameter: 0.0, 92 | longitude: 0.0, // computed 93 | distance: 0.0, // computed 94 | perturbation: 0.0 // computed 95 | }, 96 | moon: {}, 97 | mars: { 98 | epoch: 2446800.5, // 05.01.1987 99 | inclination: 1.8498, 100 | node: 49.457, 101 | perihelion: 286.343, 102 | semiAxis: 1.523710, 103 | dailyMotion: 0.524023, 104 | eccentricity: 0.093472, 105 | anomaly: 53.1893, 106 | equinox: {julian: 2446800.5}, 107 | magnitude: -1.52, 108 | semiDiameter: 4.68 109 | }, 110 | jupiter: { 111 | epoch: 2446800.5, // 05.01.1987 112 | inclination: 1.3051, 113 | node: 100.358, 114 | perihelion: 275.129, 115 | semiAxis: 5.20265, 116 | dailyMotion: 0.0830948, 117 | eccentricity: 0.048100, 118 | anomaly: 344.5086, 119 | equinox: {julian: 2446800.5}, 120 | magnitude: -9.40, 121 | semiDiameter: 98.44 122 | }, 123 | saturn: { 124 | epoch: 2446800.5, // 05.01.1987 125 | inclination: 2.4858, 126 | node: 113.555, 127 | perihelion: 337.969, 128 | semiAxis: 9.54050, 129 | dailyMotion: 0.0334510, 130 | eccentricity: 0.052786, 131 | anomaly: 159.6327, 132 | equinox: {julian: 2446800.5}, 133 | magnitude: -8.88, 134 | semiDiameter: 82.73 135 | }, 136 | uranus: { 137 | epoch: 2446800.5, // 05.01.1987 138 | inclination: 0.7738, 139 | node: 73.994, 140 | perihelion: 98.746, 141 | semiAxis: 19.2233, 142 | dailyMotion: 0.0116943, 143 | eccentricity: 0.045682, 144 | anomaly: 84.8516, 145 | equinox: {julian: 2446800.5}, 146 | magnitude: -7.19, 147 | semiDiameter: 35.02 148 | }, 149 | neptune: { 150 | epoch: 2446800.5, // 05.01.1987 151 | inclination: 1.7697, 152 | node: 131.677, 153 | perihelion: 250.623, 154 | semiAxis: 30.1631, 155 | dailyMotion: 0.00594978, 156 | eccentricity: 0.009019, 157 | anomaly: 254.2568, 158 | equinox: {julian: 2446800.5}, 159 | magnitude: -6.87, 160 | semiDiameter: 33.50 161 | }, 162 | pluto: { 163 | epoch: 2446640.5, 164 | inclination: 17.1346, 165 | node: 110.204, 166 | perihelion: 114.21, 167 | semiAxis: 39.4633, 168 | dailyMotion: 0.00397570, 169 | eccentricity: 0.248662, 170 | anomaly: 355.0554, 171 | equinox: {julian: 2446640.5}, 172 | magnitude: -1.0, 173 | semiDiameter: 2.07 174 | }, 175 | 176 | /* 177 | * Comets and asteroids 178 | */ 179 | chiron: { 180 | epoch: 2456000.5, 181 | inclination: 6.926651533484328, 182 | node: 209.3851130617651, 183 | perihelion: 339.4595737215378, 184 | semiAxis: 0.0, // will be calulated if 0.0 185 | dailyMotion: 0.0, // will be calculated 186 | eccentricity: 0.3792037887546262, 187 | anomaly: 114.8798253094007, 188 | equinox: {julian: 2450109.234581196786}, 189 | magnitude: 6.5, 190 | semiDiameter: 0.0, 191 | perihelionDistance: 8.486494269138399 192 | }, 193 | 194 | /* 195 | * Stars (implemented, not tested) 196 | */ 197 | sirius: { 198 | epoch: 2000, 199 | hmsRa: {hours: 6, minutes: 45, seconds: 8.871}, 200 | hmsDec: {hours: -16, minutes: 42, seconds: 57.99}, 201 | raMotion: -3.847, 202 | decMotion: -120.53, 203 | velocity: -7.6, 204 | parallax: 0.3751, 205 | magnitude: -1.46, 206 | ra: 0.0, 207 | dec: 0.0, 208 | equinox: {julian: 0.0} 209 | } 210 | } 211 | 212 | body.init = function () { 213 | for (var key in this) { 214 | if (Object.prototype.hasOwnProperty.call(this, key) && key != 'init') { 215 | // fill the 'key' 216 | this [key].key = key 217 | // fill the ptable for the body 218 | if (Object.prototype.hasOwnProperty.call(plan404, key)) { 219 | this [key].ptable = plan404 [key] 220 | } 221 | } 222 | } 223 | } 224 | 225 | module.exports = body 226 | -------------------------------------------------------------------------------- /src/astronomy/moshier/star.js: -------------------------------------------------------------------------------- 1 | var aberration = require('./aberration') 2 | var altaz = require('./altaz') 3 | var constant = require('./constant') 4 | var deflection = require('./deflection') 5 | var epsilon = require('./epsilon') 6 | var fk4fk5 = require('./fk4fk5') 7 | var nutation = require('./nutation') 8 | var precess = require('./precess') 9 | var util = require('./util') 10 | 11 | var moshier = { 12 | body: require('./body') 13 | } 14 | 15 | var star = {} 16 | 17 | star.calc = function (body) { 18 | if (!body.isPrepared) { 19 | this.prepare(body) 20 | body.isPrepared = true 21 | } 22 | this.reduce(body) 23 | } 24 | 25 | star.reduce = function (body) { 26 | var q = {}, polar = {} 27 | var epoch // double 28 | 29 | /* Convert from RA and Dec to equatorial rectangular direction */ 30 | do { 31 | var cosdec = Math.cos(body.dec) 32 | var sindec = Math.sin(body.dec) 33 | var cosra = Math.cos(body.ra) 34 | var sinra = Math.sin(body.ra) 35 | q.longitude = cosra * cosdec 36 | q.latitude = sinra * cosdec 37 | q.distance = sindec 38 | 39 | /* space motion */ 40 | var vpi = 21.094952663 * body.velocity * body.parallax 41 | var m = { 42 | longitude: -body.raMotion * cosdec * sinra 43 | - body.decMotion * sindec * cosra 44 | + vpi * q.longitude, 45 | latitude: body.raMotion * cosdec * cosra 46 | - body.decMotion * sindec * sinra 47 | + vpi * q.latitude, 48 | distance: body.decMotion * cosdec 49 | + vpi * q.distance 50 | } 51 | 52 | epoch = body.epoch 53 | 54 | /* Convert FK4 to FK5 catalogue */ 55 | if (epoch == constant.b1950) { 56 | fk4fk5.calc(q, m, body) 57 | // continue; 58 | } 59 | } while (epoch == constant.b1950) 60 | 61 | var e = { 62 | longitude: moshier.body.earth.position.rect.longitude, 63 | latitude: moshier.body.earth.position.rect.latitude, 64 | distance: moshier.body.earth.position.rect.distance 65 | } 66 | 67 | /* precess the earth to the star epoch */ 68 | precess.calc(e, {julian: epoch}, -1) 69 | 70 | /* Correct for proper motion and parallax */ 71 | var T = (moshier.body.earth.position.date.julian - epoch) / 36525 72 | var p = { 73 | longitude: q.longitude + T * m.longitude - body.parallax * e.longitude, 74 | latitude: q.latitude + T * m.latitude - body.parallax * e.latitude, 75 | distance: q.distance + T * m.distance - body.parallax * e.distance 76 | } 77 | 78 | /* precess the star to J2000 */ 79 | precess.calc(p, {julian: epoch}, 1) 80 | /* reset the earth to J2000 */ 81 | e = { 82 | longitude: moshier.body.earth.position.rect.longitude, 83 | latitude: moshier.body.earth.position.rect.latitude, 84 | distance: moshier.body.earth.position.rect.distance 85 | } 86 | 87 | /* Find Euclidean vectors between earth, object, and the sun 88 | * angles( p, q, e ); 89 | */ 90 | util.angles(p, p, e) 91 | 92 | /* Find unit vector from earth in direction of object */ 93 | p.longitude /= constant.EO 94 | p.latitude /= constant.EO 95 | p.distance /= constant.EO 96 | 97 | var temp = { 98 | longitude: p.longitude, 99 | latitude: p.latitude, 100 | distance: p.distance 101 | } 102 | 103 | body.position = {} 104 | body.position.approxVisualMagnitude = body.magnitude 105 | 106 | /* Report astrometric position */ 107 | body.position.astrometricJ2000 = util.showrd(p, polar) 108 | 109 | /* Also in 1950 coordinates */ 110 | precess.calc(temp, {julian: constant.b1950}, -1) 111 | 112 | body.position.astrometricB1950 = util.showrd(temp, polar) 113 | 114 | /* For equinox of date: */ 115 | temp = { 116 | longitude: p.longitude, 117 | latitude: p.latitude, 118 | distance: p.distance 119 | } 120 | 121 | precess.calc(temp, moshier.body.earth.position.date, -1) 122 | body.position.astrometricDate = util.showrd(temp, polar) 123 | 124 | /* Correct position for light deflection 125 | * relativity( p, q, e ); 126 | */ 127 | body.position.deflection = deflection.calc(p, p, e) // relativity 128 | 129 | /* Correct for annual aberration */ 130 | body.position.aberration = aberration.calc(p) 131 | 132 | /* Precession of the equinox and ecliptic 133 | * from J2000.0 to ephemeris date 134 | */ 135 | precess.calc(p, moshier.body.earth.position.date, -1) 136 | 137 | /* Adjust for nutation at current ecliptic. */ 138 | epsilon.calc(moshier.body.earth.position.date) 139 | nutation.calc(moshier.body.earth.position.date, p) 140 | 141 | /* Display the final apparent R.A. and Dec. 142 | * for equinox of date. 143 | */ 144 | body.position.apparent = util.showrd(p, polar) 145 | 146 | // prepare for display 147 | body.position.apparentLongitude = body.position.apparent.dRA 148 | var dmsLongitude = util.dms(body.position.apparentLongitude) 149 | body.position.apparentLongitudeString = 150 | dmsLongitude.degree + '\u00B0' + 151 | dmsLongitude.minutes + '\'' + 152 | Math.floor(dmsLongitude.seconds) + '"' 153 | 154 | body.position.apparentLongitude30String = 155 | util.mod30(dmsLongitude.degree) + '\u00B0' + 156 | dmsLongitude.minutes + '\'' + 157 | Math.floor(dmsLongitude.seconds) + '"' 158 | 159 | body.position.geocentricDistance = 7777 160 | 161 | /* Go do topocentric reductions. */ 162 | constant.dradt = 0.0 163 | constant.ddecdt = 0.0 164 | polar.distance = 1.0e38 165 | /* make it ignore diurnal parallax */ 166 | 167 | body.position.altaz = altaz.calc(polar, moshier.body.earth.position.date) 168 | } 169 | 170 | star.prepare = function (body) { 171 | /* Read in the ASCII string data and name of the object */ 172 | // sscanf( s, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %s", 173 | // &body->epoch, &rh, &rm, &rs, &dd, &dm, &ds, 174 | // &body->mura, &body->mudec, &body->v, &body->px, &body->mag, &body->obname[0] ); 175 | 176 | switch (body.epoch) { 177 | case 2000: 178 | body.epoch = constant.j2000 179 | break 180 | case 1950: 181 | body.epoch = constant.b1950 182 | break 183 | case 1900: 184 | body.epoch = constant.j1900 185 | break 186 | default: 187 | body.epoch = constant.j2000 + 365.25 * (body.epoch - 2000) 188 | break 189 | } 190 | 191 | /* read the right ascension */ 192 | if (!body.ra) { 193 | body.ra = 2 * Math.PI * (3600 * body.hmsRa.hours + 60 * body.hmsRa.minutes + body.hmsRa.seconds) / 86400 194 | } 195 | 196 | /* read the declination */ 197 | if (!body.dec) { 198 | /* the '-' sign may appaer at any part of hmsDec */ 199 | var sign = body.hmsDec.hours < 0 || body.hmsDec.minutes < 0 || body.hmsDec.seconds < 0 ? -1 : 1 200 | var z = (3600 * Math.abs(body.hmsDec.hours) + 60 * Math.abs(body.hmsDec.minutes) + Math.abs(body.hmsDec.seconds)) / constant.RTS 201 | body.dec = sign < 0 ? -z : z 202 | } 203 | 204 | body.raMotion *= 15 / constant.RTS 205 | /* s/century -> "/century -> rad/century */ 206 | body.decMotion /= constant.RTS 207 | if (body.parallax < 1) { 208 | /* assume px in arc seconds */ 209 | body.parallax = body.parallax <= 0 ? 0 : constant.STR * body.parallax 210 | } else { 211 | body.parallax = 1 / (constant.RTS * body.parallax) 212 | /* parsecs -> radians */ 213 | } 214 | } 215 | 216 | module.exports = star 217 | -------------------------------------------------------------------------------- /src/astronomy/moshier/processor.js: -------------------------------------------------------------------------------- 1 | var common = require('../../common') 2 | var constant = require('./constant') 3 | var delta = require('./delta') 4 | var julian = require('./julian') 5 | var kepler = require('./kepler') 6 | var moon = require('./moon') 7 | var planet = require('./planet') 8 | var star = require('./star') 9 | var sun = require('./sun') 10 | 11 | var moshier = { 12 | body: require('./body') 13 | } 14 | 15 | var processor = {} 16 | 17 | processor.calc = function (date, body) { 18 | constant.body = body 19 | 20 | julian.calc(date) 21 | delta.calc(date) 22 | 23 | date.universalDate = julian.toGregorian({ 24 | julian: date.universal 25 | }) 26 | 27 | date.universalDateString = 28 | date.universalDate.day + '.' + 29 | date.universalDate.month + '.' + 30 | date.universalDate.year + ' ' + 31 | date.universalDate.hours + ':' + 32 | date.universalDate.minutes + ':' + 33 | (date.universalDate.seconds + date.universalDate.milliseconds / 1000) 34 | 35 | // Adding another date to check if a planet is in retrograde position 36 | var retro_date = new Date(date.year, date.month-1, date.day, date.hours, date.minutes, date.seconds) 37 | retro_date.setUTCHours(retro_date.getUTCHours() - 1) 38 | constant.retro_date = { 39 | day: retro_date.getUTCDate(), 40 | month: retro_date.getUTCMonth()+1, 41 | year: retro_date.getUTCFullYear(), 42 | hours: retro_date.getUTCHours(), 43 | minutes: retro_date.getUTCMinutes(), 44 | seconds: retro_date.getUTCSeconds() 45 | } 46 | julian.calc(constant.retro_date) 47 | delta.calc(constant.retro_date) 48 | constant.retro_date.universalDate = julian.toGregorian({ 49 | julian: date.universal 50 | }) 51 | 52 | constant.retro_date.universalDateString = 53 | constant.retro_date.universalDate.day + '.' + 54 | constant.retro_date.universalDate.month + '.' + 55 | constant.retro_date.universalDate.year + ' ' + 56 | constant.retro_date.universalDate.hours + ':' + 57 | constant.retro_date.universalDate.minutes + ':' + 58 | (constant.retro_date.universalDate.seconds + constant.retro_date.universalDate.milliseconds / 1000) 59 | 60 | // First calculate the earth 61 | kepler.calc(date, moshier.body.earth) 62 | 63 | switch (body.key) { 64 | case 'sun': 65 | sun.calc() 66 | break 67 | case 'moon': 68 | moon.calc() 69 | break 70 | default: 71 | if (body.raMotion) { // star 72 | star.calc(body) 73 | } else { // planet 74 | planet.calc(body) 75 | } 76 | break 77 | } 78 | } 79 | 80 | processor.ecliptic = function (date, observer, body) { 81 | this.calc(date, observer) 82 | this.calc(date, body) 83 | // this.reduce(observer, body) 84 | } 85 | 86 | processor.init = function () { 87 | moshier.body.init() 88 | kepler.init() 89 | } 90 | 91 | processor.test = function () { 92 | // tested position 93 | common.copy(constant, { 94 | tlong: -71.13, 95 | glat: 42.27, 96 | attemp: 12.0, 97 | atpress: 1010.0, 98 | height: 0.0 99 | }) 100 | 101 | // initialize processor 102 | this.init() 103 | 104 | // test the moon 105 | var date = {year: 1986, month: 1, day: 1, hours: 1, minutes: 52, seconds: 0} 106 | var body = moshier.body.moon 107 | this.calc(date, body) 108 | 109 | common.assert(date.julian, 2446431.577777778) 110 | common.assert(date.delta, 54.87009963821919) 111 | 112 | common.assert(body.position.nutation.dRA, -0.48342256851185134) 113 | common.assert(body.position.nutation.dDec, 5.886353197581648) 114 | 115 | common.assert(body.position.geometric.longitude, 156.0921880198016) 116 | common.assert(body.position.geometric.latitude, 4.422063993387057) 117 | common.assert(body.position.geometric.distance, 0.14716616073282882) 118 | 119 | common.assert(body.position.apparentGeocentric.longitude, 2.7242742960376667) 120 | common.assert(body.position.apparentGeocentric.latitude, 0.07717957641849299) 121 | common.assert(body.position.apparentGeocentric.distance, 60.24442952894567) 122 | 123 | common.assert(body.position.dHorizontalParallax, 0.016599807399569004) 124 | 125 | common.assert(body.position.sunElongation, 124.15076164595345) 126 | common.assert(body.position.illuminatedFraction, 0.7815787330095528) 127 | 128 | common.assert(body.position.apparent.dRA, 2.7844808512258266) 129 | common.assert(body.position.apparent.dDec, 0.23362556081599462) 130 | 131 | common.assert(body.position.altaz.diurnalAberration.ra, 2.7844805966970942) 132 | common.assert(body.position.altaz.diurnalAberration.dec, 0.23362530162522877) 133 | 134 | common.assert(body.position.altaz.diurnalParallax.ra, 2.7967931740378766) 135 | common.assert(body.position.altaz.diurnalParallax.dec, 0.2221893682125501) 136 | 137 | common.assert(body.position.altaz.atmosphericRefraction.deg, 0.6356568799861307) 138 | common.assert(body.position.altaz.atmosphericRefraction.dRA, -112.9014532718829) 139 | common.assert(body.position.altaz.atmosphericRefraction.dDec, 1585.1382135790564) 140 | 141 | common.assert(body.position.altaz.topocentric.altitude, -0.2989379770846806) 142 | common.assert(body.position.altaz.topocentric.ra, -3.4946025585162133) 143 | common.assert(body.position.altaz.topocentric.dec, 0.22987433513647665) 144 | common.assert(body.position.altaz.topocentric.azimuth, 71.78002666681668) 145 | 146 | // test the sun 147 | date = {year: 1986, month: 1, day: 1, hours: 16, minutes: 47, seconds: 0} 148 | body = moshier.body.sun 149 | this.calc(date, body) 150 | 151 | common.assert(date.julian, 2446432.199305556) 152 | common.assert(date.delta, 54.87089572485891) 153 | 154 | common.assert(body.position.equinoxEclipticLonLat.longitude, 4.90413951369789) 155 | common.assert(body.position.equinoxEclipticLonLat.latitude, 0.000002184617423267333) 156 | common.assert(body.position.equinoxEclipticLonLat.distance, 0.9832794756330766) 157 | 158 | common.assert(body.position.lightTime, 8.177686171897745) 159 | 160 | common.assert(body.position.aberration.dRA, 1.50327643199855) 161 | common.assert(body.position.aberration.dDec, 1.7448150469138453) 162 | 163 | common.assert(body.position.constellation, 77) 164 | 165 | common.assert(body.position.apparent.dRA, 4.920756988829355) 166 | common.assert(body.position.apparent.dDec, -0.40123417213339135) 167 | 168 | common.assert(body.position.apparentLongitude, 280.9781321178379) 169 | 170 | common.assert(body.position.altaz.diurnalParallax.ra, 4.920758543965699) 171 | common.assert(body.position.altaz.diurnalParallax.dec, -0.4012734282906353) 172 | 173 | common.assert(body.position.altaz.atmosphericRefraction.deg, 0.0347669495824713) 174 | common.assert(body.position.altaz.atmosphericRefraction.dRA, -0.0654871080210392) 175 | common.assert(body.position.altaz.atmosphericRefraction.dDec, 125.15775095794257) 176 | 177 | common.assert(body.position.altaz.topocentric.altitude, 24.771802544653966) 178 | common.assert(body.position.altaz.topocentric.ra, -1.3624315255707726) 179 | common.assert(body.position.altaz.topocentric.dec, -0.4006666463910222) 180 | common.assert(body.position.altaz.topocentric.azimuth, 179.48488458374226) 181 | 182 | // test sirius 183 | date = {year: 1986, month: 1, day: 1, hours: 0, minutes: 0, seconds: 0} 184 | body = moshier.body.sirius 185 | this.calc(date, body) 186 | 187 | common.assert(date.julian, 2446431.5) 188 | common.assert(date.delta, 54.87) 189 | 190 | common.assert(body.position.apparent.dRA, 1.7651675096112047) 191 | common.assert(body.position.apparent.dDec, -0.29137543179606207) 192 | 193 | common.assert(body.position.astrometricDate.dRA, 1.7651002655957506) 194 | common.assert(body.position.astrometricDate.dDec, -0.29140596467162816) 195 | 196 | common.assert(body.position.altaz.topocentric.altitude, 1.7060953673767152) 197 | common.assert(body.position.altaz.topocentric.ra, -4.522192086886859) 198 | common.assert(body.position.altaz.topocentric.dec, -0.2873401996237649) 199 | common.assert(body.position.altaz.topocentric.azimuth, 114.21923743994829) 200 | } 201 | 202 | module.exports = processor 203 | -------------------------------------------------------------------------------- /src/astronomy/moshier/util.js: -------------------------------------------------------------------------------- 1 | var common = require('../../common') 2 | var constant = require('./constant') 3 | 4 | var util = {} 5 | 6 | util.mods3600 = function (value) { 7 | return value - 1.296e6 * Math.floor(value / 1.296e6) 8 | } 9 | 10 | /** Reduce x modulo 2 pi */ 11 | util.modtp = function (x) { 12 | var y = x - Math.floor(x / constant.TPI) * constant.TPI 13 | while (y < 0) { 14 | y += constant.TPI 15 | } 16 | while (y >= constant.TPI) { 17 | y -= constant.TPI 18 | } 19 | return y 20 | } 21 | 22 | /** Reduce x modulo 360 degrees */ 23 | util.mod360 = function (x) { 24 | var y = x - Math.floor(x / 360) * 360 25 | while (y < 0) { 26 | y += 360 27 | } 28 | while (y > 360) { 29 | y -= 360 30 | } 31 | return y 32 | } 33 | 34 | /** Reduce x modulo 30 degrees */ 35 | util.mod30 = function (x) { 36 | var y = x - Math.floor(x / 30) * 30 37 | while (y < 0) { 38 | y += 30 39 | } 40 | while (y > 30) { 41 | y -= 30 42 | } 43 | return y 44 | } 45 | 46 | util.zatan2 = function (x, y) { 47 | var w = 0, code = 0 48 | 49 | if (x < 0) { 50 | code = 2 51 | } 52 | if (y < 0) { 53 | code |= 1 54 | } 55 | 56 | if (x == 0) { 57 | return code & 1 ? 1.5 * Math.PI 58 | : y == 0 ? 0 : 0.5 * Math.PI 59 | } 60 | 61 | if (y == 0) { 62 | return code & 2 ? Math.PI : 0 63 | } 64 | 65 | switch (code) { 66 | default: 67 | case 0: 68 | w = 0 69 | break 70 | case 1: 71 | w = 2 * Math.PI 72 | break 73 | case 2: 74 | case 3: 75 | w = Math.PI 76 | break 77 | } 78 | 79 | return w + Math.atan(y / x) 80 | } 81 | 82 | util.sinh = function (x) { 83 | return (Math.exp(x) - Math.exp(-x)) / 2 84 | } 85 | 86 | util.cosh = function (x) { 87 | return (Math.exp(x) + Math.exp(-x)) / 2 88 | } 89 | 90 | util.tanh = function (x) { 91 | return (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x)) 92 | } 93 | 94 | util.hms = function (x) { 95 | var s = x * constant.RTOH 96 | if (s < 0) { 97 | s += 24 98 | } 99 | var h = Math.floor(s) 100 | s -= h 101 | s *= 60 102 | var m = Math.floor(s) 103 | s -= m 104 | s *= 60 105 | /* Handle shillings and pence roundoff. */ 106 | var sfrac = Math.floor(1000 * s + 0.5) 107 | if (sfrac >= 60000) { 108 | sfrac -= 60000 109 | m += 1 110 | if (m >= 60) { 111 | m -= 60 112 | h += 1 113 | } 114 | } 115 | var sint = Math.floor(sfrac / 1000) 116 | sfrac -= Math.floor(sint * 1000) 117 | 118 | return { 119 | hours: h, 120 | minutes: m, 121 | seconds: sint, 122 | milliseconds: sfrac 123 | } 124 | } 125 | 126 | util.degreesToDecimal = function (deg, minutes, seconds) { 127 | return deg + (minutes / 60) + (seconds / 3600) 128 | } 129 | 130 | util.dms = function (x) { 131 | var s = x * constant.RTD 132 | if (s < 0) { 133 | s = -s 134 | } 135 | var d = Math.floor(s) 136 | s -= d 137 | s *= 60 138 | var m = Math.floor(s) 139 | s -= m 140 | s *= 60 141 | 142 | return { 143 | degree: d, 144 | minutes: m, 145 | seconds: s 146 | } 147 | } 148 | 149 | /** 150 | * Display magnitude of correction vector 151 | * in arc seconds 152 | */ 153 | util.showcor = function (p, dp) { 154 | var p1 = { 155 | longitude: p.longitude + dp.longitude, 156 | latitude: p.latitude + dp.latitude, 157 | distance: p.distance + dp.distance 158 | } 159 | var d = util.deltap(p, p1) 160 | return { 161 | dRA: constant.RTS * d.dr / 15, 162 | dDec: constant.RTS * d.dd 163 | } 164 | } 165 | 166 | /** 167 | * Display Right Ascension and Declination 168 | * from input equatorial rectangular unit vector. 169 | * Output vector pol contains R.A., Dec., and radius. 170 | */ 171 | util.showrd = function (p, pol) { 172 | var r = Math.sqrt(p.longitude * p.longitude 173 | + p.latitude * p.latitude + p.distance * p.distance 174 | ) 175 | 176 | pol.longitude = util.zatan2(p.longitude, p.latitude) 177 | pol.latitude = Math.asin(p.distance / r) 178 | pol.distance = r 179 | 180 | var result = {} 181 | common.copy(result, { 182 | dRA: pol.longitude, 183 | dDec: pol.latitude, 184 | ra: util.hms(pol.longitude), 185 | dec: util.dms(pol.latitude) 186 | }) 187 | return result 188 | } 189 | 190 | /** 191 | * Convert change in rectangular coordinates to change 192 | * in right ascension and declination. 193 | * For changes greater than about 0.1 degree, the 194 | * coordinates are converted directly to R.A. and Dec. 195 | * and the results subtracted. For small changes, 196 | * the change is calculated to first order by differentiating 197 | * tan(R.A.) = y/x 198 | * to obtain 199 | * dR.A./cos**2(R.A.) = dy/x - y dx/x**2 200 | * where 201 | * cos**2(R.A.) = 1/(1 + (y/x)**2) 202 | * 203 | * The change in declination arcsin(z/R) is 204 | * d asin(u) = du/sqrt(1-u**2) 205 | * where u = z/R. 206 | * 207 | * p0 is the initial object - earth vector and 208 | * p1 is the vector after motion or aberration. 209 | */ 210 | util.deltap = function (p0, p1) { 211 | var dr 212 | 213 | var P = p0.longitude * p0.longitude 214 | + p0.latitude * p0.latitude 215 | + p0.distance * p0.distance 216 | 217 | var Q = p1.longitude * p1.longitude 218 | + p1.latitude * p1.latitude 219 | + p1.distance * p1.distance 220 | 221 | var dp = { 222 | longitude: p1.longitude - p0.longitude, 223 | latitude: p1.latitude - p0.latitude, 224 | distance: p1.distance - p0.distance 225 | } 226 | 227 | var z = dp.longitude * dp.longitude 228 | + dp.latitude * dp.latitude 229 | + dp.distance * dp.distance 230 | 231 | var A = Math.sqrt(P) 232 | var B = Math.sqrt(Q) 233 | 234 | if (A < 1.e-7 || B < 1.e-7 || z / (P + Q) > 5.e-7) { 235 | P = util.zatan2(p0.longitude, p0.latitude) 236 | Q = util.zatan2(p1.longitude, p1.latitude) 237 | Q = Q - P 238 | while (Q < -Math.PI) { 239 | Q += 2 * Math.PI 240 | } 241 | while (Q > Math.PI) { 242 | Q -= 2 * Math.PI 243 | } 244 | dr = Q 245 | P = Math.asin(p0.distance / A) 246 | Q = Math.asin(p1.distance / B) 247 | return { 248 | dd: Q - P, 249 | dr: dr 250 | } 251 | } 252 | 253 | var x = p0.longitude 254 | var y = p0.latitude 255 | if (x == 0.0) { 256 | dr = 1.0e38 257 | } else { 258 | var a = y / x 259 | dr = (dp.latitude - dp.longitude * y / x) / (x * (1 + a * a)) 260 | } 261 | x = p0.distance / A 262 | return { 263 | dd: (p1.distance / B - x) / Math.sqrt(1 - x * x), 264 | dr: dr 265 | } 266 | } 267 | 268 | /** 269 | * Sun - object - earth angles and distances. 270 | * q (object), e (earth), and p (q minus e) are input vectors. 271 | * The answers are posted in the following global locations: 272 | */ 273 | util.angles = function (p, q, e) { 274 | var a = { 275 | longitude: p.longitude, 276 | latitude: p.latitude, 277 | distance: p.distance 278 | } 279 | /* Distance between Earth and object */ 280 | constant.EO = Math.sqrt(a.longitude * a.longitude 281 | + a.latitude * a.latitude + a.distance * a.distance 282 | ) 283 | /* Sun - object */ 284 | constant.SO = Math.sqrt(q.longitude * q.longitude 285 | + q.latitude * q.latitude + q.distance * q.distance 286 | ) 287 | /* Sun - earth */ 288 | constant.SE = Math.sqrt(e.longitude * e.longitude 289 | + e.latitude * e.latitude + e.distance * e.distance 290 | ) 291 | 292 | constant.pq = a.longitude * q.longitude 293 | + a.latitude * q.latitude + a.distance * q.distance 294 | 295 | constant.ep = e.longitude * a.longitude 296 | + e.latitude * a.latitude + e.distance * a.distance 297 | 298 | constant.qe = q.longitude * e.longitude 299 | + q.latitude * e.latitude + q.distance * e.distance 300 | 301 | /* Avoid fatality: if object equals sun, SO is zero. */ 302 | if (constant.SO > 1.0e-12) { 303 | /* cosine of sun-object-earth */ 304 | constant.pq /= constant.EO * constant.SO 305 | /* cosine of earth-sun-object */ 306 | constant.qe /= constant.SO * constant.SE 307 | } 308 | /* -cosine of sun-earth-object */ 309 | constant.ep /= constant.SE * constant.EO 310 | } 311 | 312 | module.exports = util 313 | -------------------------------------------------------------------------------- /src/astronomy/moshier/plan404/neptune.js: -------------------------------------------------------------------------------- 1 | var neptune = { 2 | maxargs: 9, 3 | max_harmonic: [0, 0, 0, 0, 3, 8, 7, 9, 0], 4 | max_power_of_t: 3, 5 | distance: 3.0110386869399999e+01, 6 | timescale: 3652500.0, 7 | trunclvl: 1.0, 8 | lon_tbl: [ 9 | -1376.86480, 730.38970, 78655362.50948, 1095691.38676, 10 | -196.19023, 2086.77782, 11 | -122.04650, -276.81592, 12 | 184.56164, -148.08924, 13 | 3.39142, -14.75027, 14 | -9.22741, 0.87688, 15 | -0.13903, -0.44707, 16 | -0.17668, -0.36299, 17 | -0.12682, -0.26636, 18 | -0.51426, -0.24667, 19 | -0.04965, -0.03177, 20 | 0.05050, -0.00249, 21 | -0.80362, -0.07363, -0.15436, -0.07180, 22 | 2.45034, -3.50145, 0.86698, 0.09777, 23 | 7.72386, 7.16565, 2.10273, 8.86682, 24 | 2.44705, 77.90155, 25 | 0.28323, -11.87157, -13.64083, 252.70556, 26 | -4.94214, -6.17988, -305.60504, 51.23962, 27 | -2759.81719, 2476.20912, 28 | 12.65762, 13.31543, 29 | 0.36996, -0.19077, 0.67363, 0.36737, 30 | 0.02312, 0.02216, 31 | 0.09953, 0.04777, 32 | -0.00572, -0.02772, 33 | -0.02478, -0.21920, 34 | -0.15289, -1.50784, 35 | -0.17822, 0.34638, -0.70473, -8.61559, 36 | -2.65756, 1.25632, 37 | -0.31453, -1.40348, -4.02571, -1.50467, 38 | -69.62308, 3.21315, 39 | 0.69973, 0.08832, 40 | -0.00551, -0.04964, 41 | -0.02264, -0.34881, 42 | 0.00762, -1.85072, 43 | 0.01407, -0.30457, 44 | -0.09851, -0.02372, 45 | -0.07729, -0.11602, -0.75995, -0.71884, 46 | -0.08585, -0.30406, 0.45818, 0.14921, 47 | -0.01033, -0.11776, 48 | 0.00640, -0.57717, 49 | -0.01014, -0.01357, -0.00544, -0.02168, 50 | 0.40468, 0.28195, 0.00668, 0.14448, 51 | 0.01245, -0.08956, 52 | -0.26283, 0.01864, -0.00641, 18.55347, 53 | 0.01460, 0.08284, 54 | -0.04785, 0.11360, 55 | -0.33861, 0.01327, -0.06392, -0.18758, 56 | 0.05449, -0.05583, 57 | -0.00435, -0.09869, 58 | -0.00286, -0.04613, 59 | -0.00395, -0.14564, 60 | -0.01385, -0.01762, 61 | 0.21160, -0.61631, -0.52100, -0.04583, 62 | 0.32812, 0.32138, 63 | 0.04749, -0.05724, 64 | 0.11239, 0.13216, 65 | -0.01203, 0.40084, -0.05207, 34.07903, 66 | -0.21457, -0.34938, -0.04594, 0.11198, 67 | -0.30662, -0.20776, -0.01076, -0.10959, 68 | 0.10891, -0.10304, 69 | -0.28141, 0.25061, -0.20293, 0.79930 70 | ], 71 | lat_tbl: [ 72 | -391.05987, -243.95958, -23.83558, 58.13857, 73 | 5.04859, -3.93183, 74 | -14.21914, 7.14247, 75 | -12.09415, -9.70132, 76 | 1.04307, 0.47323, 77 | -0.07504, 0.70575, 78 | -0.05239, 0.00482, 79 | -0.02916, 0.00877, 80 | -0.00528, -0.00286, 81 | 0.00028, -0.00228, 82 | -0.00056, -0.00149, 83 | 0.00049, 0.00047, 84 | -0.18765, -0.59571, 0.03742, -0.14653, 85 | 2.30535, 0.65092, 0.42216, 0.24521, 86 | -2.86932, 2.37808, -0.58456, 0.27446, 87 | -1.12264, -2.04413, 88 | -11.71318, -1.41554, -23.30671, -24.70499, 89 | 8.82738, 85.64657, -90.02223, 22.42604, 90 | -4749.41359, -4244.46820, 91 | 25.20811, -18.51469, 92 | -1.19892, -0.61067, 0.67734, -1.08912, 93 | -0.01607, 0.00626, 94 | -0.00008, 0.00126, 95 | -0.00330, -0.00078, 96 | -0.01503, 0.00758, 97 | -0.13208, -0.00218, 98 | -0.04522, 0.20297, -0.94708, -0.77897, 99 | -2.74075, -3.01122, 100 | -1.03394, 0.00886, 1.55485, -4.68416, 101 | -0.13244, -57.26983, 102 | 0.05589, -0.55396, 103 | -0.00130, 0.00526, 104 | -0.01028, 0.02086, 105 | 0.01334, 0.00699, 106 | 0.08565, 0.02020, 107 | 0.01001, -0.08402, 108 | 0.08558, -0.04488, 0.57268, -0.59574, 109 | 0.00807, 0.00492, 0.21993, -0.18949, 110 | -0.00396, 0.00735, 111 | 0.00487, 0.00230, 112 | 0.00699, -0.00473, 0.01406, -0.00139, 113 | 0.00738, 0.00099, 0.00161, 0.00019, 114 | -0.00067, -0.00047, 115 | 0.00572, -0.00486, -0.00842, 0.00322, 116 | 0.00018, -0.00109, 117 | -0.00272, 0.00112, 118 | -0.00041, 0.00763, 0.00211, 0.00118, 119 | -0.46842, -0.17877, 120 | 0.00209, -0.00179, 121 | 0.00090, -0.00075, 122 | 0.00618, 0.00610, 123 | 0.00015, 0.00032, 124 | -0.00123, 0.00026, 0.00332, 0.00135, 125 | 0.39130, -0.34727, 126 | 0.00015, -0.00027, 127 | -0.00026, -0.00052, 128 | 0.00162, 0.00913, -0.00697, 0.00308, 129 | -0.00333, -0.00258, -0.00117, 0.00035, 130 | 0.00766, 0.00194, 0.00135, 0.00067, 131 | -0.41171, 0.24241, 132 | 0.00106, 0.00025, 0.00013, -0.00019 133 | ], 134 | rad_tbl: [ 135 | -767.68936, -460.59576, -52.41861, -273.85897, 136 | 59.52489, 1.85006, 137 | -39.64750, 23.63348, 138 | -34.60399, -23.41681, 139 | 2.74937, 1.55389, 140 | 0.20343, 2.15502, 141 | -0.12846, 0.07199, 142 | -0.07555, 0.05582, 143 | -0.04354, 0.01546, 144 | -0.03931, 0.07623, 145 | -0.00491, 0.00661, 146 | 0.00322, 0.01540, 147 | -0.06741, -0.35343, 0.00469, -0.08073, 148 | 1.94975, 0.66376, 0.06137, 0.31426, 149 | -2.93841, 4.27732, -4.00342, 1.11157, 150 | -36.87785, 1.24960, 151 | 4.69573, 2.15164, -114.24899, -6.69320, 152 | 12.99919, -9.47795, -21.82350, -156.88624, 153 | -1237.19769, -1379.88864, 154 | 6.54369, -6.20873, 155 | -0.14163, -0.32700, 0.17937, -0.34864, 156 | 0.01393, -0.01286, 157 | 0.02876, -0.05767, 158 | 0.02210, -0.00128, 159 | 0.16495, -0.01242, 160 | 1.15915, -0.10365, 161 | -0.33224, -0.10045, 6.83719, -0.27499, 162 | -0.31284, -0.94332, 163 | 1.63704, -0.33318, 1.48134, -1.32257, 164 | 0.96498, -8.31047, 165 | -0.00402, -0.09441, 166 | 0.04292, -0.00444, 167 | 0.30325, -0.02012, 168 | 1.67999, 0.00353, 169 | 0.00467, 0.03556, 170 | 0.01393, -0.01229, 171 | 0.01188, -0.01390, 0.04615, -0.03509, 172 | 0.32423, -0.12491, 0.13682, 0.15131, 173 | 0.11221, -0.01201, 174 | 0.57239, 0.00093, 175 | 0.02068, -0.01162, 0.00647, -0.00325, 176 | 0.27010, -0.42993, 0.14314, -0.01353, 177 | -0.08757, -0.00699, 178 | 0.00199, 0.31873, 18.80329, 0.01681, 179 | 0.08009, -0.00998, 180 | -0.14421, -0.15912, 181 | 0.37208, 0.49744, 0.35144, 0.06582, 182 | -0.11501, -0.14037, 183 | 0.10352, -0.00768, 184 | 0.04826, -0.00423, 185 | 0.19850, 0.00310, 186 | -0.01780, 0.01350, 187 | -0.61106, -0.20525, -0.04388, 0.52143, 188 | 0.19300, -0.21446, 189 | -0.05749, -0.04776, 190 | 0.12877, -0.10908, 191 | 0.39821, 0.00627, 34.03956, 0.04392, 192 | -0.34455, 0.22015, 0.11743, 0.04638, 193 | 0.20723, -0.30447, 0.10976, -0.01008, 194 | -0.20778, -0.21822, 195 | 0.24939, 0.27976, 0.79790, 0.20200 196 | ], 197 | arg_tbl: [ 198 | 0, 3, 199 | 2, 1, 7, -2, 8, 0, 200 | 3, 3, 5, -8, 6, 3, 8, 0, 201 | 2, 2, 7, -4, 8, 0, 202 | 3, 1, 5, -3, 6, 3, 8, 0, 203 | 2, 3, 7, -6, 8, 0, 204 | 2, 4, 7, -8, 8, 0, 205 | 3, 1, 6, -6, 7, 6, 8, 0, 206 | 3, 1, 6, -5, 7, 4, 8, 0, 207 | 3, 1, 6, -4, 7, 2, 8, 0, 208 | 2, 1, 6, -3, 7, 0, 209 | 3, 1, 6, -2, 7, -1, 8, 0, 210 | 2, 5, 7, -9, 8, 1, 211 | 2, 4, 7, -7, 8, 1, 212 | 2, 3, 7, -5, 8, 1, 213 | 2, 2, 7, -3, 8, 0, 214 | 2, 1, 7, -1, 8, 1, 215 | 1, 1, 8, 2, 216 | 2, 1, 7, -3, 8, 0, 217 | 2, 2, 7, -5, 8, 1, 218 | 3, 1, 6, -6, 7, 5, 8, 0, 219 | 3, 1, 6, -5, 7, 3, 8, 0, 220 | 2, 5, 7, -8, 8, 0, 221 | 2, 4, 7, -6, 8, 0, 222 | 2, 3, 7, -4, 8, 0, 223 | 2, 2, 7, -2, 8, 1, 224 | 1, 1, 7, 0, 225 | 1, 2, 8, 2, 226 | 2, 1, 7, -4, 8, 0, 227 | 2, 5, 7, -7, 8, 0, 228 | 2, 4, 7, -5, 8, 0, 229 | 2, 3, 7, -3, 8, 0, 230 | 2, 2, 7, -1, 8, 0, 231 | 2, 1, 7, 1, 8, 0, 232 | 1, 3, 8, 1, 233 | 2, 1, 6, -2, 8, 1, 234 | 2, 5, 7, -6, 8, 0, 235 | 2, 4, 7, -4, 8, 0, 236 | 1, 4, 8, 1, 237 | 3, 2, 5, -4, 6, -1, 8, 1, 238 | 3, 1, 6, 1, 7, -3, 8, 0, 239 | 2, 1, 6, -1, 8, 1, 240 | 3, 1, 6, -1, 7, 1, 8, 0, 241 | 3, 2, 5, -6, 6, 1, 8, 0, 242 | 2, 5, 7, -5, 8, 1, 243 | 1, 1, 6, 0, 244 | 2, 6, 7, -6, 8, 0, 245 | 2, 7, 7, -7, 8, 0, 246 | 2, 2, 6, -2, 8, 0, 247 | 3, 2, 5, -3, 6, -1, 8, 0, 248 | 2, 2, 6, -1, 8, 1, 249 | 2, 1, 5, -2, 8, 0, 250 | 3, 3, 5, -5, 6, -1, 8, 0, 251 | 2, 4, 7, 5, 8, 0, 252 | 2, 1, 5, -1, 8, 1, 253 | 3, 1, 5, -1, 7, 1, 8, 1, 254 | 3, 1, 5, -5, 6, 1, 8, 1, 255 | 1, 1, 5, 0, 256 | 2, 2, 5, -1, 8, 1, 257 | -1 258 | ] 259 | } 260 | 261 | module.exports = neptune 262 | -------------------------------------------------------------------------------- /src/astronomy/moshier/delta.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | 3 | var delta = {} 4 | 5 | /** 6 | * Morrison and Stephenson (2004) 7 | * This table covers -1000 through 1700 in 100-year steps. 8 | * Values are in whole seconds. 9 | * Estimated standard error at -1000 is 640 seconds; at 1600, 20 seconds. 10 | * The first value in the table has been adjusted 28 sec for 11 | * continuity with their long-term quadratic extrapolation formula. 12 | * The last value in this table agrees with the AA table at 1700, 13 | * so there is no discontinuity at either endpoint. 14 | */ 15 | delta.m_s = [ 16 | /* -1000 to -100 */ 17 | 25428, 23700, 22000, 21000, 19040, 17190, 15530, 14080, 12790, 11640, 18 | /* 0 to 900 */ 19 | 10580, 9600, 8640, 7680, 6700, 5710, 4740, 3810, 2960, 2200, 20 | /* 1000 to 1700 */ 21 | 1570, 1090, 740, 490, 320, 200, 120, 9 22 | ] 23 | 24 | /** 25 | * Entries prior to 1955 in the following table are from 26 | * the 1984 Astronomical Almanac and assume ndot = -26.0. 27 | * For dates prior to 1700, the above table is used instead of this one. 28 | */ 29 | delta.dt = [ 30 | /* 1620.0 thru 1659.0 */ 31 | 12400, 11900, 11500, 11000, 10600, 10200, 9800, 9500, 9100, 8800, 32 | 8500, 8200, 7900, 7700, 7400, 7200, 7000, 6700, 6500, 6300, 33 | 6200, 6000, 5800, 5700, 5500, 5400, 5300, 5100, 5000, 4900, 34 | 4800, 4700, 4600, 4500, 4400, 4300, 4200, 4100, 4000, 3800, 35 | /* 1660.0 thru 1699.0 */ 36 | 3700, 3600, 3500, 3400, 3300, 3200, 3100, 3000, 2800, 2700, 37 | 2600, 2500, 2400, 2300, 2200, 2100, 2000, 1900, 1800, 1700, 38 | 1600, 1500, 1400, 1400, 1300, 1200, 1200, 1100, 1100, 1000, 39 | 1000, 1000, 900, 900, 900, 900, 900, 900, 900, 900, 40 | /* 1700.0 thru 1739.0 */ 41 | 900, 900, 900, 900, 900, 900, 900, 900, 1000, 1000, 42 | 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1100, 1100, 1100, 43 | 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 44 | 1100, 1100, 1100, 1100, 1200, 1200, 1200, 1200, 1200, 1200, 45 | /* 1740.0 thru 1779.0 */ 46 | 1200, 1200, 1200, 1200, 1300, 1300, 1300, 1300, 1300, 1300, 47 | 1300, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1500, 1500, 48 | 1500, 1500, 1500, 1500, 1500, 1600, 1600, 1600, 1600, 1600, 49 | 1600, 1600, 1600, 1600, 1600, 1700, 1700, 1700, 1700, 1700, 50 | /* 1780.0 thru 1799.0 */ 51 | 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 52 | 1700, 1700, 1600, 1600, 1600, 1600, 1500, 1500, 1400, 1400, 53 | /* 1800.0 thru 1819.0 */ 54 | 1370, 1340, 1310, 1290, 1270, 1260, 1250, 1250, 1250, 1250, 55 | 1250, 1250, 1250, 1250, 1250, 1250, 1250, 1240, 1230, 1220, 56 | /* 1820.0 thru 1859.0 */ 57 | 1200, 1170, 1140, 1110, 1060, 1020, 960, 910, 860, 800, 58 | 750, 700, 660, 630, 600, 580, 570, 560, 560, 560, 59 | 570, 580, 590, 610, 620, 630, 650, 660, 680, 690, 60 | 710, 720, 730, 740, 750, 760, 770, 770, 780, 780, 61 | /* 1860.0 thru 1899.0 */ 62 | 788, 782, 754, 697, 640, 602, 541, 410, 292, 182, 63 | 161, 10, -102, -128, -269, -324, -364, -454, -471, -511, 64 | -540, -542, -520, -546, -546, -579, -563, -564, -580, -566, 65 | -587, -601, -619, -664, -644, -647, -609, -576, -466, -374, 66 | /* 1900.0 thru 1939.0 */ 67 | -272, -154, -2, 124, 264, 386, 537, 614, 775, 913, 68 | 1046, 1153, 1336, 1465, 1601, 1720, 1824, 1906, 2025, 2095, 69 | 2116, 2225, 2241, 2303, 2349, 2362, 2386, 2449, 2434, 2408, 70 | 2402, 2400, 2387, 2395, 2386, 2393, 2373, 2392, 2396, 2402, 71 | /* 1940.0 thru 1979.0 */ 72 | 2433, 2483, 2530, 2570, 2624, 2677, 2728, 2778, 2825, 2871, 73 | 2915, 2957, 2997, 3036, 3072, 3107, 3135, 3168, 3218, 3268, 74 | 3315, 3359, 3400, 3447, 3503, 3573, 3654, 3743, 3829, 3920, 75 | 4018, 4117, 4223, 4337, 4449, 4548, 4646, 4752, 4853, 4959, 76 | /* 1980.0 thru 2011.0 */ 77 | 5054, 5138, 5217, 5296, 5379, 5434, 5487, 5532, 5582, 5630, 78 | 5686, 5757, 5831, 5912, 5998, 6078, 6163, 6230, 6297, 6347, 79 | 6383, 6409, 6430, 6447, 6457, 6469, 6485, 6515, 6546, 6578, 80 | 6607, 6632 81 | ] 82 | 83 | delta.demo = 0 84 | delta.TABSTART = 1620 85 | delta.TABEND = 2011 86 | delta.TABSIZ = delta.TABEND - delta.TABSTART + 1 87 | 88 | delta.calc = function (date) { 89 | var p, B // double 90 | var diff = [0, 0, 0, 0, 0, 0] // int 91 | var i, iy // int 92 | 93 | if (constant.dtgiven) { 94 | date.delta = constant.dtgiven 95 | } else if (date.j2000 > this.TABEND) { 96 | /* Extrapolate future values beyond the lookup table. */ 97 | if (date.j2000 > this.TABEND + 100) { 98 | /* Morrison & Stephenson (2004) long-term curve fit. */ 99 | B = (date.j2000 - 1820) / 100 100 | date.delta = 32 * B * B - 20 101 | } else { 102 | /* Cubic interpolation between last tabulated value 103 | and long-term curve evaluated at 100 years later. */ 104 | 105 | /* Last tabulated delta T value. */ 106 | var a = this.dt[this.TABSIZ - 1] / 100 107 | /* Approximate slope in past 10 years. */ 108 | var b = (this.dt[this.TABSIZ - 1] - this.dt[this.TABSIZ - 11]) / 1000 109 | 110 | /* Long-term curve 100 years hence. */ 111 | B = (this.TABEND + 100 - 1820) / 100 112 | var m0 = 32 * B * B - 20 113 | /* Its slope. */ 114 | var m1 = 0.64 * B 115 | 116 | /* Solve for remaining coefficients of an interpolation polynomial 117 | that agrees in value and slope at both ends of the 100-year 118 | interval. */ 119 | var d = 2.0e-6 * (50 * (m1 + b) - m0 + a) 120 | var c = 1.0e-4 * (m0 - a - 100 * b - 1.0e6 * d) 121 | 122 | /* Note, the polynomial coefficients do not depend on Y. 123 | A given tabulation and long-term formula 124 | determine the polynomial. 125 | Thus, for the IERS table ending at 2011.0, the coefficients are 126 | a = 66.32 127 | b = 0.223 128 | c = 0.03231376 129 | d = -0.0001607784 130 | */ 131 | 132 | /* Compute polynomial value at desired time. */ 133 | p = date.j2000 - this.TABEND 134 | date.delta = a + p * (b + p * (c + p * d)) 135 | } 136 | } else { 137 | /* Use Morrison and Stephenson (2004) prior to the year 1700. */ 138 | if (date.j2000 < 1700) { 139 | if (date.j2000 <= -1000) { 140 | /* Morrison and Stephenson long-term fit. */ 141 | B = (date.j2000 - 1820) / 100 142 | date.delta = 32 * B * B - 20 143 | } else { 144 | /* Morrison and Stephenson recommend linear interpolation 145 | between tabulations. */ 146 | iy = Math.floor(date.j2000) 147 | iy = Math.floor((iy + 1000) / 100) 148 | /* Integer index into the table. */ 149 | B = -1000 + 100 * iy 150 | /* Starting year of tabulated interval. */ 151 | date.delta = this.m_s[iy] + (date.j2000 - B) * (this.m_s[iy + 1] - this.m_s[iy]) / 100 152 | } 153 | } else { 154 | /* Besselian interpolation between tabulated values 155 | * in the telescopic era. 156 | * See AA page K11. 157 | */ 158 | 159 | /* Index into the table. */ 160 | p = Math.floor(date.j2000) 161 | iy = Math.floor(p - this.TABSTART) 162 | /* Zeroth order estimate is value at start of year */ 163 | date.delta = this.dt[iy] 164 | var k = iy + 1 165 | if (k < this.TABSIZ) { 166 | /* The fraction of tabulation interval */ 167 | p = date.j2000 - p 168 | 169 | /* First order interpolated value */ 170 | date.delta += p * (this.dt[k] - this.dt[iy]) 171 | if (iy - 1 >= 0 && iy + 2 < this.TABSIZ) { 172 | // make table of first differences 173 | k = iy - 2 174 | for (i = 0; i < 5; i++) { 175 | if (k < 0 || k + 1 >= this.TABSIZ) { 176 | diff[i] = 0 177 | } else { 178 | diff[i] = this.dt[k + 1] - this.dt[k] 179 | } 180 | k += 1 181 | } 182 | 183 | // compute second differences 184 | for (i = 0; i < 4; i++) { 185 | diff[i] = diff[i + 1] - diff[i] 186 | } 187 | B = 0.25 * p * (p - 1) 188 | date.delta += B * (diff[1] + diff[2]) 189 | 190 | if (iy + 2 < this.TABSIZ) { 191 | // Compute third differences 192 | for (i = 0; i < 3; i++) { 193 | diff[i] = diff[i + 1] - diff[i] 194 | } 195 | B = 2 * B / 3 196 | date.delta += (p - 0.5) * B * diff[1] 197 | if (iy - 2 >= 0 && iy + 3 <= this.TABSIZ) { 198 | // Compute fourth differences 199 | for (i = 0; i < 2; i++) { 200 | diff[i] = diff[i + 1] - diff[i] 201 | } 202 | B = 0.125 * B * (p + 1) * (p - 2) 203 | date.delta += B * (diff[0] + diff[1]) 204 | } 205 | } 206 | } 207 | } 208 | } 209 | date.delta /= 100 210 | } 211 | 212 | date.terrestrial = date.julian 213 | date.universal = date.terrestrial - date.delta / 86400 214 | 215 | return date.delta 216 | } 217 | 218 | module.exports = delta 219 | -------------------------------------------------------------------------------- /src/astronomy/moshier/moon.js: -------------------------------------------------------------------------------- 1 | var aberration = require('./aberration') 2 | var altaz = require('./altaz') 3 | var constant = require('./constant') 4 | var epsilon = require('./epsilon') 5 | var gplan = require('./gplan') 6 | var lonlat = require('./lonlat') 7 | var nutation = require('./nutation') 8 | var precess = require('./precess') 9 | var util = require('./util') 10 | 11 | var moshier = { 12 | body: require('./body') 13 | } 14 | 15 | var moon = { 16 | /** Right Ascension */ 17 | ra: 0.0, 18 | /** Declination */ 19 | dec: 0.0 20 | } 21 | 22 | /** 23 | * Calculate geometric position of the Moon and apply 24 | * approximate corrections to find apparent position, 25 | * phase of the Moon, etc. for AA.ARC. 26 | */ 27 | moon.calc = function () { 28 | var moonpp = {}, moonpol = {} 29 | 30 | moshier.body.moon.position = { 31 | polar: {}, 32 | rect: {} 33 | } 34 | 35 | /** Geometric equatorial coordinates of the earth. */ 36 | var re = { 37 | longitude: moshier.body.earth.position.rect.longitude, 38 | latitude: moshier.body.earth.position.rect.latitude, 39 | distance: moshier.body.earth.position.rect.distance 40 | } 41 | 42 | /* Run the orbit calculation twice, at two different times, 43 | * in order to find the rate of change of R.A. and Dec. 44 | */ 45 | 46 | /* Calculate for 0.001 day ago */ 47 | this.calcll({julian: moshier.body.earth.position.date.julian - 0.001}, moonpp, moonpol) // TDT - 0.001 48 | var ra0 = this.ra 49 | var dec0 = this.dec 50 | var lon0 = moonpol.longitude 51 | 52 | /* Calculate for present instant. */ 53 | moshier.body.moon.position.nutation = this.calcll(moshier.body.earth.position.date, moonpp, moonpol).nutation 54 | 55 | moshier.body.moon.position.geometric = { 56 | longitude: constant.RTD * moshier.body.moon.position.polar.longitude, 57 | latitude: constant.RTD * moshier.body.moon.position.polar.latitude, 58 | distance: constant.RTD * moshier.body.moon.position.polar.distance 59 | } 60 | 61 | /* 62 | * The rates of change. These are used by altaz () to 63 | * correct the time of rising, transit, and setting. 64 | */ 65 | constant.dradt = this.ra - ra0 66 | if (constant.dradt >= Math.PI) { 67 | constant.dradt = constant.dradt - 2 * Math.PI 68 | } 69 | if (constant.dradt <= -Math.PI) { 70 | constant.dradt = constant.dradt + 2 * Math.PI 71 | } 72 | constant.dradt = 1000 * constant.dradt 73 | constant.ddecdt = 1000 * (this.dec - dec0) 74 | 75 | /* Rate of change in longitude, degrees per day 76 | * used for phase of the moon 77 | */ 78 | lon0 = 1000 * constant.RTD * (moonpol.longitude - lon0) 79 | 80 | /* Get apparent coordinates for the earth. */ 81 | var z = Math.sqrt(re.longitude * re.longitude 82 | + re.latitude * re.latitude + re.distance * re.distance 83 | ) 84 | 85 | re.longitude /= z 86 | re.latitude /= z 87 | re.distance /= z 88 | 89 | /* aberration of light. */ 90 | moshier.body.moon.position.annualAberration = aberration.calc(re) 91 | 92 | /* pe.longitude -= STR * (20.496/(RTS*pe.distance)); */ 93 | precess.calc(re, moshier.body.earth.position.date, -1) 94 | nutation.calc(moshier.body.earth.position.date, re) 95 | 96 | re.longitude *= z 97 | re.latitude *= z 98 | re.distance *= z 99 | 100 | var pe = lonlat.calc(re, moshier.body.earth.position.date, false) 101 | 102 | /* Find sun-moon-earth angles */ 103 | var qq = { 104 | longitude: re.longitude + moonpp.longitude, 105 | latitude: re.latitude + moonpp.latitude, 106 | distance: re.distance + moonpp.distance 107 | } 108 | 109 | util.angles(moonpp, qq, re) 110 | 111 | /* Display answers */ 112 | moshier.body.moon.position.apparentGeocentric = { 113 | longitude: moonpol.longitude, 114 | dLongitude: constant.RTD * moonpol.longitude, 115 | latitude: moonpol.latitude, 116 | dLatitude: constant.RTD * moonpol.latitude, 117 | distance: moonpol.distance / constant.Rearth 118 | } 119 | moshier.body.moon.position.apparentLongitude = moshier.body.moon.position.apparentGeocentric.dLongitude 120 | var dmsLongitude = util.dms(moshier.body.moon.position.apparentGeocentric.longitude) 121 | moshier.body.moon.position.apparentLongitudeString = 122 | dmsLongitude.degree + '\u00B0' + 123 | dmsLongitude.minutes + '\'' + 124 | Math.floor(dmsLongitude.seconds) + '"' 125 | 126 | moshier.body.moon.position.apparentLongitude30String = 127 | util.mod30(dmsLongitude.degree) + '\u00B0' + 128 | dmsLongitude.minutes + '\'' + 129 | Math.floor(dmsLongitude.seconds) + '"' 130 | 131 | moshier.body.moon.position.geocentricDistance = moonpol.distance / constant.Rearth 132 | 133 | var x = constant.Rearth / moonpol.distance 134 | moshier.body.moon.position.dHorizontalParallax = Math.asin(x) 135 | moshier.body.moon.position.horizontalParallax = util.dms(Math.asin(x)) 136 | 137 | x = 0.272453 * x + 0.0799 / constant.RTS 138 | /* AA page L6 */ 139 | moshier.body.moon.position.dSemidiameter = x 140 | moshier.body.moon.position.Semidiameter = util.dms(x) 141 | 142 | x = constant.RTD * Math.acos(-constant.ep) 143 | /* x = 180.0 - RTD * arcdot (re, pp); */ 144 | moshier.body.moon.position.sunElongation = x 145 | x = 0.5 * (1 + constant.pq) 146 | moshier.body.moon.position.illuminatedFraction = x 147 | 148 | /* Find phase of the Moon by comparing Moon's longitude 149 | * with Earth's longitude. 150 | * 151 | * The number of days before or past indicated phase is 152 | * estimated by assuming the true longitudes change linearly 153 | * with time. These rates are estimated for the date, but 154 | * do not stay constant. The error can exceed 0.15 day in 4 days. 155 | */ 156 | x = moonpol.longitude - pe.longitude 157 | x = util.modtp(x) * constant.RTD 158 | /* difference in longitude */ 159 | var y = Math.floor(x / 90) 160 | /* number of quarters */ 161 | x = x - y * 90 162 | /* phase angle mod 90 degrees */ 163 | 164 | /* days per degree of phase angle */ 165 | z = moonpol.distance / (12.3685 * 0.00257357) 166 | 167 | if (x > 45) { 168 | moshier.body.moon.position.phaseDaysBefore = -(x - 90) * z 169 | y = (y + 1) & 3 170 | } else { 171 | moshier.body.moon.position.phaseDaysPast = x * z 172 | } 173 | 174 | moshier.body.moon.position.phaseQuarter = y 175 | 176 | moshier.body.moon.position.apparent = { 177 | dRA: this.ra, 178 | dDec: this.dec, 179 | ra: util.hms(this.ra), 180 | dec: util.dms(this.dec) 181 | } 182 | 183 | /* Compute and display topocentric position (altaz.js) */ 184 | var pp = { 185 | longitude: this.ra, 186 | latitude: this.dec, 187 | distance: moonpol.distance 188 | } 189 | moshier.body.moon.position.altaz = altaz.calc(pp, moshier.body.earth.position.date) 190 | } 191 | 192 | /** 193 | * Calculate apparent latitude, longitude, and horizontal parallax 194 | * of the Moon at Julian date J. 195 | */ 196 | moon.calcll = function (date, rect, pol) { 197 | /* Compute obliquity of the ecliptic, coseps, and sineps. */ 198 | epsilon.calc(date) 199 | /* Get geometric coordinates of the Moon. */ 200 | gplan.moon(date, rect, pol) 201 | /* Post the geometric ecliptic longitude and latitude, in radians, 202 | * and the radius in au. 203 | */ 204 | constant.body.position.polar.longitude = pol.longitude 205 | constant.body.position.polar.latitude = pol.latitude 206 | constant.body.position.polar.distance = pol.distance 207 | 208 | /* Light time correction to longitude, 209 | * about 0.7". 210 | */ 211 | pol.longitude -= 0.0118 * constant.DTR * constant.Rearth / pol.distance 212 | 213 | /* convert to equatorial system of date */ 214 | var cosB = Math.cos(pol.latitude) 215 | var sinB = Math.sin(pol.latitude) 216 | var cosL = Math.cos(pol.longitude) 217 | var sinL = Math.sin(pol.longitude) 218 | rect.longitude = cosB * cosL 219 | rect.latitude = epsilon.coseps * cosB * sinL - epsilon.sineps * sinB 220 | rect.distance = epsilon.sineps * cosB * sinL + epsilon.coseps * sinB 221 | 222 | /* Rotate to J2000. */ 223 | precess.calc(rect, {julian: moshier.body.earth.position.date.julian}, 1) // TDT 224 | 225 | /* Find Euclidean vectors and angles between earth, object, and the sun */ 226 | var pp = { 227 | longitude: rect.longitude * pol.distance, 228 | latitude: rect.latitude * pol.distance, 229 | distance: rect.distance * pol.distance 230 | } 231 | 232 | var qq = { 233 | longitude: moshier.body.earth.position.rect.longitude + pp.longitude, 234 | latitude: moshier.body.earth.position.rect.latitude + pp.latitude, 235 | distance: moshier.body.earth.position.rect.distance + pp.distance 236 | } 237 | 238 | util.angles(pp, qq, moshier.body.earth.position.rect) 239 | 240 | /* Make rect a unit vector. */ 241 | /* rect.longitude /= EO; */ 242 | /* rect.latitude /= EO; */ 243 | /* rect.distance /= EO; */ 244 | 245 | /* Correct position for light deflection. (Ignore.) */ 246 | /* relativity(rect, qq, rearth); */ 247 | 248 | /* Aberration of light. 249 | The Astronomical Almanac (Section D, Daily Polynomial Coefficients) 250 | seems to omit this, even though the reference ephemeris is inertial. */ 251 | /* annuab (rect); */ 252 | 253 | /* Precess to date. */ 254 | precess.calc(rect, {julian: moshier.body.earth.position.date.julian}, -1) // TDT 255 | 256 | /* Correct for nutation at date TDT. */ 257 | var result = { 258 | nutation: nutation.calc({julian: moshier.body.earth.position.date.julian}, rect) // TDT 259 | } 260 | 261 | /* Apparent geocentric right ascension and declination. */ 262 | this.ra = util.zatan2(rect.longitude, rect.latitude) 263 | this.dec = Math.asin(rect.distance) 264 | 265 | /* For apparent ecliptic coordinates, rotate from the true 266 | equator into the ecliptic of date. */ 267 | cosL = Math.cos(epsilon.eps + nutation.nuto) 268 | sinL = Math.sin(epsilon.eps + nutation.nuto) 269 | var y = cosL * rect.latitude + sinL * rect.distance 270 | var z = -sinL * rect.latitude + cosL * rect.distance 271 | pol.longitude = util.zatan2(rect.longitude, y) 272 | pol.latitude = Math.asin(z) 273 | 274 | /* Restore earth-moon distance. */ 275 | rect.longitude *= constant.EO 276 | rect.latitude *= constant.EO 277 | rect.distance *= constant.EO 278 | 279 | return result 280 | } 281 | 282 | module.exports = moon 283 | -------------------------------------------------------------------------------- /src/astronomy/moshier/kepler.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | var epsilon = require('./epsilon') 3 | var gplan = require('./gplan') 4 | var precess = require('./precess') 5 | var util = require('./util') 6 | 7 | var kepler = {} 8 | 9 | kepler.calc = function (date, body, rect, polar) { 10 | var alat, E, M, W, temp, r // double 11 | 12 | polar = polar || {} 13 | 14 | /* Call program to compute position, if one is supplied. */ 15 | if (body.ptable) { 16 | polar = body.key == 'earth' 17 | ? gplan.calc3(date, body.ptable, 3) 18 | : gplan.calc(date, body.ptable) 19 | /* longitude */ 20 | body.longitude = E = polar.longitude 21 | /* latitude */ 22 | W = polar.latitude 23 | /* radius */ 24 | r = polar.distance 25 | body.distance = r 26 | body.epoch = date.julian 27 | body.equinox = {julian: constant.j2000} 28 | // goto kepdon; 29 | } else { 30 | /* Decant the parameters from the data structure */ 31 | var epoch = body.epoch 32 | var inclination = body.inclination 33 | var ascnode = body.node * constant.DTR 34 | var argperih = body.perihelion 35 | /* semimajor axis */ 36 | var meandistance = body.semiAxis 37 | var dailymotion = body.dailyMotion 38 | var eccent = body.eccentricity 39 | var meananomaly = body.anomaly 40 | /* Check for parabolic orbit. */ 41 | if (eccent == 1.0) { 42 | /* meandistance = perihelion distance, q 43 | * epoch = perihelion passage date 44 | */ 45 | temp = meandistance * Math.sqrt(meandistance) 46 | W = (date.julian - epoch) * 0.0364911624 / temp 47 | /* The constant above is 3 k / sqrt(2), 48 | * k = Gaussian gravitational constant = 0.01720209895 */ 49 | E = 0.0 50 | M = 1.0 51 | while (Math.abs(M) > 1.0e-11) { 52 | temp = E * E 53 | temp = (2 * E * temp + W) / (3 * (1 + temp)) 54 | M = temp - E 55 | if (temp != 0.0) { 56 | M /= temp 57 | } 58 | E = temp 59 | } 60 | r = meandistance * (1 + E * E) 61 | M = Math.atan(E) 62 | M = 2 * M 63 | alat = M + constant.DTR * argperih 64 | // goto parabcon; 65 | } else { 66 | if (eccent > 1) { 67 | /* The equation of the hyperbola in polar coordinates r, theta 68 | * is r = a(e^2 - 1)/(1 + e cos(theta)) 69 | * so the perihelion distance q = a(e-1), 70 | * the "mean distance" a = q/(e-1). 71 | */ 72 | meandistance = meandistance / (eccent - 1) 73 | temp = meandistance * Math.sqrt(meandistance) 74 | W = (date.julian - epoch) * 0.01720209895 / temp 75 | /* solve M = -E + e sinh E */ 76 | E = W / (eccent - 1) 77 | M = 1.0 78 | while (Math.abs(M) > 1.0e-11) { 79 | M = -E + eccent * util.sinh(E) - W 80 | E += M / (1 - eccent * util.cosh(E)) 81 | } 82 | r = meandistance * (-1 + eccent * util.cosh(E)) 83 | temp = (eccent + 1) / (eccent - 1) 84 | M = Math.sqrt(temp) * util.tanh(0.5 * E) 85 | M = 2 * Math.atan(M) 86 | alat = M + constant.DTR * argperih 87 | // goto parabcon; 88 | } else { 89 | /* Calculate the daily motion, if it is not given. */ 90 | if (dailymotion == 0.0) { 91 | /* The constant is 180 k / pi, k = Gaussian gravitational constant. 92 | * Assumes object in heliocentric orbit is massless. 93 | */ 94 | dailymotion = 0.9856076686 / (body.semiAxis * Math.sqrt(body.semiAxis)) 95 | } 96 | dailymotion *= date.julian - epoch 97 | /* M is proportional to the area swept out by the radius 98 | * vector of a circular orbit during the time between 99 | * perihelion passage and Julian date J. 100 | * It is the mean anomaly at time J. 101 | */ 102 | M = constant.DTR * (meananomaly + dailymotion) 103 | M = util.modtp(M) 104 | /* If mean longitude was calculated, adjust it also 105 | * for motion since epoch of elements. 106 | */ 107 | if (body.longitude) { 108 | body.longitude += dailymotion 109 | body.longitude = util.mod360(body.longitude) 110 | } 111 | 112 | /* By Kepler's second law, M must be equal to 113 | * the area swept out in the same time by an 114 | * elliptical orbit of same total area. 115 | * Integrate the ellipse expressed in polar coordinates 116 | * r = a(1-e^2)/(1 + e cosW) 117 | * with respect to the angle W to get an expression for the 118 | * area swept out by the radius vector. The area is given 119 | * by the mean anomaly; the angle is solved numerically. 120 | * 121 | * The answer is obtained in two steps. We first solve 122 | * Kepler's equation 123 | * M = E - eccent*sin(E) 124 | * for the eccentric anomaly E. Then there is a 125 | * closed form solution for W in terms of E. 126 | */ 127 | 128 | E = M 129 | /* Initial guess is same as circular orbit. */ 130 | temp = 1.0 131 | do { 132 | /* The approximate area swept out in the ellipse */ 133 | temp = E - eccent * Math.sin(E) 134 | /* ...minus the area swept out in the circle */ 135 | - M 136 | /* ...should be zero. Use the derivative of the error 137 | * to converge to solution by Newton's method. 138 | */ 139 | E -= temp / (1 - eccent * Math.cos(E)) 140 | } while (Math.abs(temp) > 1.0e-11) 141 | 142 | /* The exact formula for the area in the ellipse is 143 | * 2.0*atan(c2*tan(0.5*W)) - c1*eccent*sin(W)/(1+e*cos(W)) 144 | * where 145 | * c1 = sqrt( 1.0 - eccent*eccent ) 146 | * c2 = sqrt( (1.0-eccent)/(1.0+eccent) ). 147 | * Substituting the following value of W 148 | * yields the exact solution. 149 | */ 150 | temp = Math.sqrt((1 + eccent) / (1 - eccent)) 151 | W = 2 * Math.atan(temp * Math.tan(0.5 * E)) 152 | 153 | /* The true anomaly. */ 154 | W = util.modtp(W) 155 | 156 | meananomaly *= constant.DTR 157 | /* Orbital longitude measured from node 158 | * (argument of latitude) 159 | */ 160 | if (body.longitude) { 161 | alat = body.longitude * constant.DTR + W - meananomaly - ascnode 162 | } else { 163 | alat = W + constant.DTR * argperih 164 | /* mean longitude not given */ 165 | } 166 | 167 | /* From the equation of the ellipse, get the 168 | * radius from central focus to the object. 169 | */ 170 | r = meandistance * (1 - eccent * eccent) / (1 + eccent * Math.cos(W)) 171 | } 172 | } 173 | // parabcon: 174 | /* The heliocentric ecliptic longitude of the object 175 | * is given by 176 | * tan(longitude - ascnode) = cos(inclination) * tan(alat) 177 | */ 178 | var coso = Math.cos(alat) 179 | var sino = Math.sin(alat) 180 | inclination *= constant.DTR 181 | W = sino * Math.cos(inclination) 182 | E = util.zatan2(coso, W) + ascnode 183 | 184 | /* The ecliptic latitude of the object */ 185 | W = sino * Math.sin(inclination) 186 | W = Math.asin(W) 187 | } 188 | // kepdon: 189 | 190 | /* Convert to rectangular coordinates, 191 | * using the perturbed latitude. 192 | */ 193 | rect = rect || {} 194 | rect.distance = r * Math.sin(W) 195 | var cosa = Math.cos(W) 196 | rect.latitude = r * cosa * Math.sin(E) 197 | rect.longitude = r * cosa * Math.cos(E) 198 | 199 | /* Convert from heliocentric ecliptic rectangular 200 | * to heliocentric equatorial rectangular coordinates 201 | * by rotating eps radians about the x axis. 202 | */ 203 | epsilon.calc(body.equinox) 204 | W = epsilon.coseps * rect.latitude - epsilon.sineps * rect.distance 205 | M = epsilon.sineps * rect.latitude + epsilon.coseps * rect.distance 206 | rect.latitude = W 207 | rect.distance = M 208 | 209 | /* Precess the position 210 | * to ecliptic and equinox of J2000.0 211 | * if not already there. 212 | */ 213 | precess.calc(rect, body.equinox, 1) 214 | 215 | /* If earth, adjust from earth-moon barycenter to earth 216 | * by AA page E2. 217 | */ 218 | if (body.key == 'earth') { 219 | r = this.embofs(date, rect) 220 | /* see below */ 221 | } 222 | 223 | /* Rotate back into the ecliptic. */ 224 | epsilon.calc({julian: constant.j2000}) 225 | W = epsilon.coseps * rect.latitude + epsilon.sineps * rect.distance 226 | M = -epsilon.sineps * rect.latitude + epsilon.coseps * rect.distance 227 | 228 | /* Convert to polar coordinates */ 229 | E = util.zatan2(rect.longitude, W) 230 | W = Math.asin(M / r) 231 | 232 | /* Output the polar coordinates */ 233 | /* longitude */ 234 | polar.longitude = E 235 | /* latitude */ 236 | polar.latitude = W 237 | /* radius */ 238 | polar.distance = r 239 | 240 | // fill the body.position only if rect and polar are 241 | // not defined 242 | if (arguments.length < 3) { 243 | body.position = { 244 | date: date, 245 | rect: rect, 246 | polar: polar 247 | } 248 | } 249 | } 250 | 251 | /** 252 | * Adjust position from Earth-Moon barycenter to Earth 253 | * 254 | * J = Julian day number 255 | * emb = Equatorial rectangular coordinates of EMB. 256 | * return = Earth's distance to the Sun (au) 257 | */ 258 | kepler.embofs = function (date, ea) { 259 | var pm = {} 260 | 261 | /* Compute the vector Moon - Earth. */ 262 | gplan.moon(date, pm) 263 | 264 | /* Precess the lunar position 265 | * to ecliptic and equinox of J2000.0 266 | */ 267 | precess.calc(pm, date, 1) 268 | 269 | /* Adjust the coordinates of the Earth */ 270 | var a = 1 / (constant.emrat + 1) 271 | 272 | ea.longitude = ea.longitude - a * pm.longitude 273 | ea.latitude = ea.latitude - a * pm.latitude 274 | ea.distance = ea.distance - a * pm.distance 275 | 276 | /* Sun-Earth distance. */ 277 | return Math.sqrt(ea.longitude * ea.longitude 278 | + ea.latitude * ea.latitude + ea.distance * ea.distance 279 | ) 280 | } 281 | 282 | kepler.init = function () { 283 | var u = constant.glat * constant.DTR 284 | 285 | /* Reduction from geodetic latitude to geocentric latitude 286 | * AA page K5 287 | */ 288 | var co = Math.cos(u) 289 | var si = Math.sin(u) 290 | var fl = 1 - 1 / constant.flat 291 | fl = fl * fl 292 | si = si * si 293 | u = 1 / Math.sqrt(co * co + fl * si) 294 | var a = constant.aearth * u + constant.height 295 | var b = constant.aearth * fl * u + constant.height 296 | constant.trho = Math.sqrt(a * a * co * co + b * b * si) 297 | constant.tlat = constant.RTD * Math.acos(a * co / constant.trho) 298 | if (constant.glat < 0) { 299 | constant.tlat = -constant.tlat 300 | } 301 | constant.trho /= constant.aearth 302 | 303 | /* Reduction from geodetic latitude to geocentric latitude 304 | * AA page K5 305 | */ 306 | /* 307 | tlat = glat 308 | - 0.19242861 * sin(2.0*u) 309 | + 0.00032314 * sin(4.0*u) 310 | - 0.00000072 * sin(6.0*u); 311 | 312 | trho = 0.998327073 313 | + 0.001676438 * cos(2.0*u) 314 | - 0.000003519 * cos(4.0*u) 315 | + 0.000000008 * cos(6.0*u); 316 | trho += height/6378160; 317 | */ 318 | 319 | constant.Clightaud = 86400 * constant.Clight / constant.au 320 | /* Radius of the earth in au 321 | Thanks to Min He for pointing out 322 | this needs to be initialized early. */ 323 | constant.Rearth = 0.001 * constant.aearth / constant.au 324 | } 325 | 326 | module.exports = kepler 327 | -------------------------------------------------------------------------------- /src/astronomy/moshier/nutation.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | var epsilon = require('./epsilon') 3 | var util = require('./util') 4 | 5 | var nutation = { 6 | /* The answers are posted here by nutlo(): */ 7 | /** time to which the nutation applies */ 8 | jdnut: {}, 9 | /** nutation in longitude (radians) */ 10 | nutl: 0.0, 11 | /** nutation in obliquity (radians) */ 12 | nuto: 0.0, 13 | 14 | /** 15 | * Each term in the expansion has a trigonometric 16 | * argument given by 17 | * W = i*MM + j*MS + k*FF + l*DD + m*OM 18 | * where the variables are defined below. 19 | * The nutation in longitude is a sum of terms of the 20 | * form (a + bT) * sin(W). The terms for nutation in obliquity 21 | * are of the form (c + dT) * cos(W). The coefficients 22 | * are arranged in the tabulation as follows: 23 | * 24 | * Coefficient: 25 | * i j k l m a b c d 26 | * 0, 0, 0, 0, 1, -171996, -1742, 92025, 89, 27 | * The first line of the table, above, is done separately 28 | * since two of the values do not fit into 16 bit integers. 29 | * The values a and c are arc seconds times 10000. b and d 30 | * are arc seconds per Julian century times 100000. i through m 31 | * are integers. See the program for interpretation of MM, MS, 32 | * etc., which are mean orbital elements of the Sun and Moon. 33 | * 34 | * If terms with coefficient less than X are omitted, the peak 35 | * errors will be: 36 | * 37 | * omit error, omit error, 38 | * a < longitude c < obliquity 39 | * .0005" .0100" .0008" .0094" 40 | * .0046 .0492 .0095 .0481 41 | * .0123 .0880 .0224 .0905 42 | * .0386 .1808 .0895 .1129 43 | */ 44 | nt: [ 45 | 0, 0, 0, 0, 2, 2062, 2, -895, 5, 46 | -2, 0, 2, 0, 1, 46, 0, -24, 0, 47 | 2, 0, -2, 0, 0, 11, 0, 0, 0, 48 | -2, 0, 2, 0, 2, -3, 0, 1, 0, 49 | 1, -1, 0, -1, 0, -3, 0, 0, 0, 50 | 0, -2, 2, -2, 1, -2, 0, 1, 0, 51 | 2, 0, -2, 0, 1, 1, 0, 0, 0, 52 | 0, 0, 2, -2, 2, -13187, -16, 5736, -31, 53 | 0, 1, 0, 0, 0, 1426, -34, 54, -1, 54 | 0, 1, 2, -2, 2, -517, 12, 224, -6, 55 | 0, -1, 2, -2, 2, 217, -5, -95, 3, 56 | 0, 0, 2, -2, 1, 129, 1, -70, 0, 57 | 2, 0, 0, -2, 0, 48, 0, 1, 0, 58 | 0, 0, 2, -2, 0, -22, 0, 0, 0, 59 | 0, 2, 0, 0, 0, 17, -1, 0, 0, 60 | 0, 1, 0, 0, 1, -15, 0, 9, 0, 61 | 0, 2, 2, -2, 2, -16, 1, 7, 0, 62 | 0, -1, 0, 0, 1, -12, 0, 6, 0, 63 | -2, 0, 0, 2, 1, -6, 0, 3, 0, 64 | 0, -1, 2, -2, 1, -5, 0, 3, 0, 65 | 2, 0, 0, -2, 1, 4, 0, -2, 0, 66 | 0, 1, 2, -2, 1, 4, 0, -2, 0, 67 | 1, 0, 0, -1, 0, -4, 0, 0, 0, 68 | 2, 1, 0, -2, 0, 1, 0, 0, 0, 69 | 0, 0, -2, 2, 1, 1, 0, 0, 0, 70 | 0, 1, -2, 2, 0, -1, 0, 0, 0, 71 | 0, 1, 0, 0, 2, 1, 0, 0, 0, 72 | -1, 0, 0, 1, 1, 1, 0, 0, 0, 73 | 0, 1, 2, -2, 0, -1, 0, 0, 0, 74 | 0, 0, 2, 0, 2, -2274, -2, 977, -5, 75 | 1, 0, 0, 0, 0, 712, 1, -7, 0, 76 | 0, 0, 2, 0, 1, -386, -4, 200, 0, 77 | 1, 0, 2, 0, 2, -301, 0, 129, -1, 78 | 1, 0, 0, -2, 0, -158, 0, -1, 0, 79 | -1, 0, 2, 0, 2, 123, 0, -53, 0, 80 | 0, 0, 0, 2, 0, 63, 0, -2, 0, 81 | 1, 0, 0, 0, 1, 63, 1, -33, 0, 82 | -1, 0, 0, 0, 1, -58, -1, 32, 0, 83 | -1, 0, 2, 2, 2, -59, 0, 26, 0, 84 | 1, 0, 2, 0, 1, -51, 0, 27, 0, 85 | 0, 0, 2, 2, 2, -38, 0, 16, 0, 86 | 2, 0, 0, 0, 0, 29, 0, -1, 0, 87 | 1, 0, 2, -2, 2, 29, 0, -12, 0, 88 | 2, 0, 2, 0, 2, -31, 0, 13, 0, 89 | 0, 0, 2, 0, 0, 26, 0, -1, 0, 90 | -1, 0, 2, 0, 1, 21, 0, -10, 0, 91 | -1, 0, 0, 2, 1, 16, 0, -8, 0, 92 | 1, 0, 0, -2, 1, -13, 0, 7, 0, 93 | -1, 0, 2, 2, 1, -10, 0, 5, 0, 94 | 1, 1, 0, -2, 0, -7, 0, 0, 0, 95 | 0, 1, 2, 0, 2, 7, 0, -3, 0, 96 | 0, -1, 2, 0, 2, -7, 0, 3, 0, 97 | 1, 0, 2, 2, 2, -8, 0, 3, 0, 98 | 1, 0, 0, 2, 0, 6, 0, 0, 0, 99 | 2, 0, 2, -2, 2, 6, 0, -3, 0, 100 | 0, 0, 0, 2, 1, -6, 0, 3, 0, 101 | 0, 0, 2, 2, 1, -7, 0, 3, 0, 102 | 1, 0, 2, -2, 1, 6, 0, -3, 0, 103 | 0, 0, 0, -2, 1, -5, 0, 3, 0, 104 | 1, -1, 0, 0, 0, 5, 0, 0, 0, 105 | 2, 0, 2, 0, 1, -5, 0, 3, 0, 106 | 0, 1, 0, -2, 0, -4, 0, 0, 0, 107 | 1, 0, -2, 0, 0, 4, 0, 0, 0, 108 | 0, 0, 0, 1, 0, -4, 0, 0, 0, 109 | 1, 1, 0, 0, 0, -3, 0, 0, 0, 110 | 1, 0, 2, 0, 0, 3, 0, 0, 0, 111 | 1, -1, 2, 0, 2, -3, 0, 1, 0, 112 | -1, -1, 2, 2, 2, -3, 0, 1, 0, 113 | -2, 0, 0, 0, 1, -2, 0, 1, 0, 114 | 3, 0, 2, 0, 2, -3, 0, 1, 0, 115 | 0, -1, 2, 2, 2, -3, 0, 1, 0, 116 | 1, 1, 2, 0, 2, 2, 0, -1, 0, 117 | -1, 0, 2, -2, 1, -2, 0, 1, 0, 118 | 2, 0, 0, 0, 1, 2, 0, -1, 0, 119 | 1, 0, 0, 0, 2, -2, 0, 1, 0, 120 | 3, 0, 0, 0, 0, 2, 0, 0, 0, 121 | 0, 0, 2, 1, 2, 2, 0, -1, 0, 122 | -1, 0, 0, 0, 2, 1, 0, -1, 0, 123 | 1, 0, 0, -4, 0, -1, 0, 0, 0, 124 | -2, 0, 2, 2, 2, 1, 0, -1, 0, 125 | -1, 0, 2, 4, 2, -2, 0, 1, 0, 126 | 2, 0, 0, -4, 0, -1, 0, 0, 0, 127 | 1, 1, 2, -2, 2, 1, 0, -1, 0, 128 | 1, 0, 2, 2, 1, -1, 0, 1, 0, 129 | -2, 0, 2, 4, 2, -1, 0, 1, 0, 130 | -1, 0, 4, 0, 2, 1, 0, 0, 0, 131 | 1, -1, 0, -2, 0, 1, 0, 0, 0, 132 | 2, 0, 2, -2, 1, 1, 0, -1, 0, 133 | 2, 0, 2, 2, 2, -1, 0, 0, 0, 134 | 1, 0, 0, 2, 1, -1, 0, 0, 0, 135 | 0, 0, 4, -2, 2, 1, 0, 0, 0, 136 | 3, 0, 2, -2, 2, 1, 0, 0, 0, 137 | 1, 0, 2, -2, 0, -1, 0, 0, 0, 138 | 0, 1, 2, 0, 1, 1, 0, 0, 0, 139 | -1, -1, 0, 2, 1, 1, 0, 0, 0, 140 | 0, 0, -2, 0, 1, -1, 0, 0, 0, 141 | 0, 0, 2, -1, 2, -1, 0, 0, 0, 142 | 0, 1, 0, 2, 0, -1, 0, 0, 0, 143 | 1, 0, -2, -2, 0, -1, 0, 0, 0, 144 | 0, -1, 2, 0, 1, -1, 0, 0, 0, 145 | 1, 1, 0, -2, 1, -1, 0, 0, 0, 146 | 1, 0, -2, 2, 0, -1, 0, 0, 0, 147 | 2, 0, 0, 2, 0, 1, 0, 0, 0, 148 | 0, 0, 2, 4, 2, -1, 0, 0, 0, 149 | 0, 1, 0, 1, 0, 1, 0, 0, 0 150 | ], 151 | 152 | ss: [], 153 | cc: [] 154 | } 155 | 156 | /** 157 | * Nutation -- AA page B20 158 | * using nutation in longitude and obliquity from nutlo() 159 | * and obliquity of the ecliptic from epsiln() 160 | * both calculated for Julian date J. 161 | * 162 | * p = equatorial rectangular position vector of object for 163 | * mean ecliptic and equinox of date. 164 | */ 165 | nutation.calc = function (date, p) { 166 | this.calclo(date) 167 | /* be sure we calculated nutl and nuto */ 168 | epsilon.calc(date) 169 | /* and also the obliquity of date */ 170 | 171 | var f = epsilon.eps + this.nuto 172 | var ce = Math.cos(f) 173 | var se = Math.sin(f) 174 | var sino = Math.sin(this.nuto) 175 | var cl = Math.cos(this.nutl) 176 | var sl = Math.sin(this.nutl) 177 | 178 | /* Apply adjustment 179 | * to equatorial rectangular coordinates of object. 180 | * 181 | * This is a composite of three rotations: rotate about x axis 182 | * to ecliptic of date; rotate about new z axis by the nutation 183 | * in longitude; rotate about new x axis back to equator of date 184 | * plus nutation in obliquity. 185 | */ 186 | var p1 = { 187 | longitude: cl * p.longitude 188 | - sl * epsilon.coseps * p.latitude 189 | - sl * epsilon.sineps * p.distance, 190 | latitude: sl * ce * p.longitude 191 | + (cl * epsilon.coseps * ce + epsilon.sineps * se) * p.latitude 192 | - (sino + (1 - cl) * epsilon.sineps * ce) * p.distance, 193 | distance: sl * se * p.longitude 194 | + (sino + (cl - 1) * se * epsilon.coseps) * p.latitude 195 | + (cl * epsilon.sineps * se + epsilon.coseps * ce) * p.distance 196 | } 197 | 198 | var dp = { 199 | longitude: p1.longitude - p.longitude, 200 | latitude: p1.latitude - p.latitude, 201 | distance: p1.distance - p.distance 202 | } 203 | 204 | var result = util.showcor(p, dp) 205 | 206 | p.longitude = p1.longitude 207 | p.latitude = p1.latitude 208 | p.distance = p1.distance 209 | 210 | return result 211 | } 212 | 213 | /** 214 | * Nutation in longitude and obliquity 215 | * computed at Julian date J. 216 | */ 217 | nutation.calclo = function (date) { 218 | if (this.jdnut.julian == date.julian) { 219 | return 0 220 | } 221 | 222 | this.jdnut = date 223 | 224 | /* Julian centuries from 2000 January 1.5, 225 | * barycentric dynamical time 226 | */ 227 | var T = (date.julian - 2451545) / 36525 228 | var T2 = T * T 229 | var T10 = T / 10 230 | 231 | /* Fundamental arguments in the FK5 reference system. */ 232 | 233 | /** 234 | * longitude of the mean ascending node of the lunar orbit 235 | * on the ecliptic, measured from the mean equinox of date 236 | */ 237 | var OM = (util.mods3600(-6962890.539 * T + 450160.280) + (0.008 * T + 7.455) * T2) 238 | * constant.STR 239 | 240 | /** 241 | * mean longitude of the Sun minus the 242 | * mean longitude of the Sun's perigee 243 | */ 244 | var MS = (util.mods3600(129596581.224 * T + 1287099.804) - (0.012 * T + 0.577) * T2) 245 | * constant.STR 246 | 247 | /** 248 | * mean longitude of the Moon minus the 249 | * mean longitude of the Moon's perigee 250 | */ 251 | var MM = (util.mods3600(1717915922.633 * T + 485866.733) + (0.064 * T + 31.310) * T2) 252 | * constant.STR 253 | 254 | /** 255 | * mean longitude of the Moon minus the 256 | * mean longitude of the Moon's node 257 | */ 258 | var FF = (util.mods3600(1739527263.137 * T + 335778.877) + (0.011 * T - 13.257) * T2) 259 | * constant.STR 260 | 261 | /** 262 | * mean elongation of the Moon from the Sun. 263 | */ 264 | var DD = (util.mods3600(1602961601.328 * T + 1072261.307) + (0.019 * T - 6.891) * T2) 265 | * constant.STR 266 | 267 | /* Calculate sin( i*MM ), etc. for needed multiple angles */ 268 | this.sscc(0, MM, 3) 269 | this.sscc(1, MS, 2) 270 | this.sscc(2, FF, 4) 271 | this.sscc(3, DD, 4) 272 | this.sscc(4, OM, 2) 273 | 274 | var C = 0.0 275 | var D = 0.0 276 | var p = this.nt 277 | /* point to start of table */ 278 | 279 | var p_i = 0 280 | 281 | for (var i = 0; i < 105; i++) { 282 | /* argument of sine and cosine */ 283 | var k 284 | var k1 = false 285 | var cv = 0.0 286 | var sv = 0.0 287 | for (var m = 0; m < 5; m++) { 288 | var j = p[p_i++] // *p++; 289 | if (j) { 290 | k = j < 0 ? -j : j 291 | var su = this.ss[m][k - 1] 292 | /* sin(k*angle) */ 293 | if (j < 0) { 294 | su = -su 295 | } 296 | var cu = this.cc[m][k - 1] 297 | if (!k1) { /* set first angle */ 298 | sv = su 299 | cv = cu 300 | k1 = true 301 | } else { /* combine angles */ 302 | var sw = su * cv + cu * sv 303 | cv = cu * cv - su * sv 304 | sv = sw 305 | } 306 | } 307 | } 308 | /* longitude coefficient */ 309 | var f = p[p_i++] // *p++; 310 | k = p[p_i++] // *p++; 311 | if (k != 0) { 312 | f += T10 * k 313 | } 314 | 315 | /* obliquity coefficient */ 316 | var g = p[p_i++] // *p++; 317 | k = p[p_i++] // *p++; 318 | if (k != 0) { 319 | g += T10 * k 320 | } 321 | 322 | /* accumulate the terms */ 323 | C += f * sv 324 | D += g * cv 325 | } 326 | /* first terms, not in table: */ 327 | C += (-1742 * T10 - 171996) * this.ss[4][0] 328 | /* sin(OM) */ 329 | D += (89 * T10 + 92025) * this.cc[4][0] 330 | /* cos(OM) */ 331 | /* 332 | printf( "nutation: in longitude %.3f\", in obliquity %.3f\"\n", C, D ); 333 | */ 334 | /* Save answers, expressed in radians */ 335 | this.nutl = 0.0001 * constant.STR * C 336 | this.nuto = 0.0001 * constant.STR * D 337 | } 338 | 339 | /** 340 | * Prepare lookup table of sin and cos ( i*Lj ) 341 | * for required multiple angles 342 | */ 343 | nutation.sscc = function (k, arg, n) { 344 | var su = Math.sin(arg) 345 | var cu = Math.cos(arg) 346 | this.ss[k] = [] 347 | this.cc[k] = [] 348 | 349 | this.ss[k][0] = su 350 | /* sin(L) */ 351 | this.cc[k][0] = cu 352 | /* cos(L) */ 353 | var sv = 2 * su * cu 354 | var cv = cu * cu - su * su 355 | this.ss[k][1] = sv 356 | /* sin(2L) */ 357 | this.cc[k][1] = cv 358 | for (var i = 2; i < n; i++) { 359 | var s = su * cv + cu * sv 360 | cv = cu * cv - su * sv 361 | sv = s 362 | this.ss[k][i] = sv 363 | /* sin( i+1 L ) */ 364 | this.cc[k][i] = cv 365 | } 366 | } 367 | 368 | module.exports = nutation 369 | -------------------------------------------------------------------------------- /src/astronomy/moshier/plan404/venus.js: -------------------------------------------------------------------------------- 1 | var venus = { 2 | maxargs: 9, 3 | max_harmonic: [5, 14, 13, 8, 4, 5, 1, 0, 0], 4 | max_power_of_t: 5, 5 | distance: 7.2332982000000001e-01, 6 | timescale: 3652500.0, 7 | trunclvl: 1.0, 8 | lon_tbl: [ 9 | 9.08078, 55.42416, 21066413644.98911, 655127.20186, 10 | 0.00329, 0.10408, 11 | 0.00268, -0.01908, 12 | 0.00653, 0.00183, 13 | 0.15083, -0.21997, 14 | 6.08596, 2.34841, 3.70668, -0.22740, 15 | -2.29376, -1.46741, 16 | -0.03840, 0.01242, 17 | 0.00176, 0.00913, 18 | 0.00121, -0.01222, 19 | -1.22624, 0.65264, -1.15974, -1.28172, 20 | 1.00656, -0.66266, 21 | 0.01560, -0.00654, 0.00896, 0.00069, 22 | 0.21649, -0.01786, 23 | 0.01239, 0.00255, 24 | 0.00084, -0.06086, 25 | -0.00041, 0.00887, 26 | 0.13453, -0.20013, 0.08234, 0.01575, 27 | 0.00658, -0.00214, 28 | 0.00254, 0.00857, 29 | -0.01047, -0.00519, 30 | 0.63215, -0.40914, 0.34271, -1.53258, 31 | 0.00038, -0.01437, 32 | -0.02599, -2.27805, -0.36873, -1.01799, 33 | -0.36798, 1.41356, 34 | -0.08167, 0.01368, 0.20676, 0.06807, 35 | 0.02282, -0.04691, 36 | 0.30308, -0.20218, 0.24785, 0.27522, 37 | 0.00197, -0.00499, 38 | 1.43909, -0.46154, 0.93459, 2.99583, 39 | -3.43274, 0.05672, 40 | -0.06586, 0.12467, 0.02505, -0.08433, 41 | 0.00743, 0.00174, 42 | -0.04013, 0.17715, 43 | -0.00603, -0.01024, 44 | 0.01542, -0.02378, 45 | 0.00676, 0.00002, 46 | -0.00168, -4.89487, 47 | 0.02393, -0.03064, 48 | 0.00090, 0.00977, 49 | 0.01223, 0.00381, 50 | 0.28135, -0.09158, 0.18550, 0.58372, 51 | -0.67437, 0.01409, 52 | -0.25404, -0.06863, 53 | 0.06763, -0.02939, 54 | -0.00009, -0.04888, 55 | 0.01718, -0.00978, 56 | -0.01945, 0.08847, 57 | -0.00135, -11.29920, 58 | 0.01689, -0.04756, 59 | 0.02075, -0.01667, 60 | 0.01397, 0.00443, 61 | -0.28437, 0.07600, 0.17996, -0.44326, 62 | 0.29356, 1.41869, -1.58617, 0.03206, 63 | 0.00229, -0.00753, 64 | -0.03076, -2.96766, 65 | 0.00245, 0.00697, 66 | 0.01063, -0.02468, 67 | -0.00351, -0.18179, 68 | -0.01088, 0.00380, 69 | 0.00496, 0.02072, 70 | -0.12890, 0.16719, -0.06820, -0.03234, 71 | -60.36135, -11.74485, -11.03752, -3.80145, 72 | -21.33955, -284.54495, -763.43839, 248.50823, 73 | 1493.02775, 1288.79621, -2091.10921, -1851.15420, 74 | -0.00922, 0.06233, 75 | 0.00004, 0.00785, 76 | 0.10363, -0.16770, 0.45497, 0.24051, 77 | -0.28057, 0.61126, 78 | -0.02057, 0.00010, 79 | 0.00561, 0.01994, 80 | 0.01416, -0.00442, 81 | 0.03073, -0.14961, 82 | -0.06272, 0.08301, 83 | 0.02040, 7.12824, 84 | -0.00453, -0.01815, 85 | 0.00004, -0.00013, 86 | -0.03593, -0.18147, 0.20353, -0.00683, 87 | 0.00003, 0.06226, 88 | -0.00443, 0.00257, 89 | 0.03194, 0.03254, 90 | 0.00282, -0.01401, 91 | 0.00422, 1.03169, 92 | -0.00169, -0.00591, 93 | -0.00307, 0.00540, 94 | 0.05511, 0.00347, 95 | 0.07896, 0.06583, 96 | 0.00783, 0.01926, 97 | 0.03109, 0.15967, 98 | 0.00343, 0.88734, 99 | 0.01047, 0.32054, 100 | 0.00814, 0.00051, 101 | 0.02474, 0.00047, 102 | 0.00052, 0.03763, 103 | -57.06618, 20.34614, -45.06541, -115.20465, 104 | 136.46887, -84.67046, 92.93308, 160.44644, 105 | -0.00020, -0.00082, 106 | 0.02496, 0.00279, 107 | 0.00849, 0.00195, 108 | -0.05013, -0.04331, 109 | -0.00136, 0.14491, 110 | -0.00183, -0.00406, 111 | 0.01163, 0.00093, 112 | -0.00604, -0.00680, 113 | -0.00036, 0.06861, 114 | -0.00450, -0.00969, 115 | 0.00171, 0.00979, 116 | -0.00152, 0.03929, 117 | 0.00631, 0.00048, 118 | -0.00709, -0.00864, 119 | 1.51002, -0.24657, 1.27338, 2.64699, 120 | -2.40990, -0.57413, 121 | -0.00023, 0.03528, 122 | 0.00268, 0.00522, 123 | -0.00010, 0.01933, 124 | -0.00006, 0.01100, 125 | 0.06313, -0.09939, 0.08571, 0.03206, 126 | -0.00004, 0.00645 127 | ], 128 | lat_tbl: [ 129 | -23.91858, 31.44154, 25.93273, -67.68643, 130 | -0.00171, 0.00123, 131 | 0.00001, -0.00018, 132 | -0.00005, 0.00018, 133 | -0.00001, 0.00019, 134 | 0.00733, 0.00030, -0.00038, 0.00011, 135 | 0.00181, 0.00120, 136 | 0.00010, 0.00002, 137 | -0.00012, 0.00002, 138 | 0.00021, 0.00004, 139 | -0.00403, 0.00101, 0.00342, -0.00328, 140 | 0.01564, 0.01212, 141 | 0.00011, 0.00010, -0.00002, -0.00004, 142 | -0.00524, 0.00079, 143 | 0.00011, 0.00002, 144 | -0.00001, 0.00003, 145 | 0.00001, 0.00000, 146 | 0.00108, 0.00035, 0.00003, 0.00064, 147 | -0.00000, -0.00002, 148 | -0.00069, 0.00031, 149 | 0.00020, 0.00003, 150 | 0.00768, 0.03697, -0.07906, 0.01673, 151 | -0.00003, -0.00001, 152 | -0.00198, -0.01045, 0.01761, -0.00803, 153 | -0.00751, 0.04199, 154 | 0.00280, -0.00213, -0.00482, -0.00209, 155 | -0.01077, 0.00715, 156 | 0.00048, -0.00004, 0.00199, 0.00237, 157 | 0.00017, -0.00032, 158 | -0.07513, -0.00658, -0.04213, 0.16065, 159 | 0.27661, 0.06515, 160 | 0.02156, -0.08144, -0.23994, -0.05674, 161 | 0.00167, 0.00069, 162 | 0.00244, -0.01247, 163 | -0.00100, 0.00036, 164 | 0.00240, 0.00012, 165 | 0.00010, 0.00018, 166 | 0.00208, -0.00098, 167 | -0.00217, 0.00707, 168 | -0.00338, 0.01260, 169 | -0.00127, -0.00039, 170 | -0.03516, -0.00544, -0.01746, 0.08258, 171 | 0.10633, 0.02523, 172 | 0.00077, -0.00214, 173 | -0.02335, 0.00976, 174 | -0.00019, 0.00003, 175 | 0.00041, 0.00039, 176 | 0.00199, -0.01098, 177 | 0.00813, -0.00853, 178 | 0.02230, 0.00349, 179 | -0.02250, 0.08119, 180 | -0.00214, -0.00052, 181 | -0.00220, 0.15216, 0.17152, 0.08051, 182 | -0.01561, 0.27727, 0.25837, 0.07021, 183 | -0.00005, -0.00000, 184 | -0.02692, -0.00047, 185 | -0.00007, -0.00016, 186 | 0.01072, 0.01418, 187 | -0.00076, 0.00379, 188 | -0.00807, 0.03463, 189 | -0.05199, 0.06680, 190 | -0.00622, 0.00787, 0.00672, 0.00453, 191 | -10.69951, -67.43445, -183.55956, -37.87932, 192 | -102.30497, -780.40465, 2572.21990, -446.97798, 193 | 1665.42632, 5698.61327, -11889.66501, 2814.93799, 194 | 0.03204, -0.09479, 195 | 0.00014, -0.00001, 196 | -0.04118, -0.04562, 0.03435, -0.05878, 197 | 0.01700, 0.02566, 198 | -0.00121, 0.00170, 199 | 0.02390, 0.00403, 200 | 0.04629, 0.01896, 201 | -0.00521, 0.03215, 202 | -0.01051, 0.00696, 203 | -0.01332, -0.08937, 204 | -0.00469, -0.00751, 205 | 0.00016, -0.00035, 206 | 0.00492, -0.03930, -0.04742, -0.01013, 207 | 0.00065, 0.00021, 208 | -0.00006, 0.00017, 209 | 0.06768, -0.01558, 210 | -0.00055, 0.00322, 211 | -0.00287, -0.01656, 212 | 0.00061, -0.00041, 213 | 0.00030, 0.00047, 214 | -0.01436, -0.00148, 215 | 0.30302, -0.05511, 216 | -0.00020, -0.00005, 217 | 0.00042, -0.00025, 218 | 0.01270, 0.00458, 219 | -0.00593, -0.04480, 220 | 0.00005, -0.00008, 221 | 0.08457, -0.01569, 222 | 0.00062, 0.00018, 223 | 9.79942, -2.48836, 4.17423, 6.72044, 224 | -63.33456, 34.63597, 39.11878, -72.89581, 225 | -0.00066, 0.00036, 226 | -0.00045, -0.00062, 227 | -0.00287, -0.00118, 228 | -0.21879, 0.03947, 229 | 0.00086, 0.00671, 230 | -0.00113, 0.00122, 231 | -0.00193, -0.00029, 232 | -0.03612, 0.00635, 233 | 0.00024, 0.00207, 234 | -0.00273, 0.00443, 235 | -0.00055, 0.00030, 236 | -0.00451, 0.00175, 237 | -0.00110, -0.00015, 238 | -0.02608, 0.00480, 239 | 2.16555, -0.70419, 1.74648, 0.97514, 240 | -1.15360, 1.73688, 241 | 0.00004, 0.00105, 242 | 0.00187, -0.00311, 243 | 0.00005, 0.00055, 244 | 0.00004, 0.00032, 245 | -0.04629, 0.02292, -0.00363, -0.03807, 246 | 0.00002, 0.00020 247 | ], 248 | rad_tbl: [ 249 | -0.24459, 3.72698, -6.67281, 5.24378, 250 | 0.00030, 0.00003, 251 | -0.00002, -0.00000, 252 | -0.00000, 0.00001, 253 | 0.00032, 0.00021, 254 | -0.00326, 0.01002, 0.00067, 0.00653, 255 | 0.00243, -0.00417, 256 | -0.00004, -0.00010, 257 | -0.00002, -0.00001, 258 | 0.00004, -0.00002, 259 | -0.00638, -0.01453, 0.01458, -0.01235, 260 | 0.00755, 0.01030, 261 | 0.00006, 0.00014, 0.00000, 0.00009, 262 | 0.00063, 0.00176, 263 | 0.00003, -0.00022, 264 | 0.00112, 0.00001, 265 | -0.00014, -0.00001, 266 | 0.00485, 0.00322, -0.00035, 0.00198, 267 | 0.00004, 0.00013, 268 | -0.00015, -0.00003, 269 | 0.00011, -0.00025, 270 | 0.00634, 0.02207, 0.04620, 0.00160, 271 | 0.00045, 0.00001, 272 | -0.11563, 0.00643, -0.05947, 0.02018, 273 | 0.07704, 0.01574, 274 | -0.00090, -0.00471, -0.00322, 0.01104, 275 | 0.00265, -0.00038, 276 | 0.01395, 0.02165, -0.01948, 0.01713, 277 | -0.00057, -0.00019, 278 | 0.04889, 0.13403, -0.28327, 0.10597, 279 | -0.02325, -0.35829, 280 | 0.01171, -0.00904, 0.00747, 0.02546, 281 | 0.00029, -0.00190, 282 | -0.03408, -0.00703, 283 | 0.00176, -0.00109, 284 | 0.00463, 0.00293, 285 | 0.00000, 0.00148, 286 | 1.06691, -0.00054, 287 | -0.00935, -0.00790, 288 | 0.00552, -0.00084, 289 | -0.00100, 0.00336, 290 | 0.02874, 0.08604, -0.17876, 0.05973, 291 | -0.00720, -0.21195, 292 | 0.02134, -0.07980, 293 | 0.01500, 0.01398, 294 | 0.01758, -0.00004, 295 | 0.00371, 0.00650, 296 | -0.03375, -0.00723, 297 | 4.65465, -0.00040, 298 | 0.02040, 0.00707, 299 | -0.00727, -0.01144, 300 | -0.00196, 0.00620, 301 | -0.03396, -0.12904, 0.20160, 0.08092, 302 | -0.67045, 0.14014, -0.01571, -0.75141, 303 | 0.00361, 0.00110, 304 | 1.42165, -0.01499, 305 | -0.00334, 0.00117, 306 | 0.01187, 0.00507, 307 | 0.08935, -0.00174, 308 | -0.00211, -0.00525, 309 | 0.01035, -0.00252, 310 | -0.08355, -0.06442, 0.01616, -0.03409, 311 | 5.55241, -30.62428, 2.03824, -6.26978, 312 | 143.07279, -10.24734, -125.25411, -380.85360, 313 | -644.78411, 745.02852, 926.70000, -1045.09820, 314 | -0.03124, -0.00465, 315 | -0.00396, 0.00002, 316 | 0.08518, 0.05248, -0.12178, 0.23023, 317 | -0.30943, -0.14208, 318 | -0.00005, -0.01054, 319 | -0.00894, 0.00233, 320 | -0.00173, -0.00768, 321 | 0.07881, 0.01633, 322 | -0.04463, -0.03347, 323 | -3.92991, 0.00945, 324 | 0.01524, -0.00422, 325 | -0.00011, -0.00005, 326 | 0.10842, -0.02126, 0.00349, 0.12097, 327 | -0.03752, 0.00001, 328 | -0.00156, -0.00270, 329 | -0.01520, 0.01349, 330 | 0.00895, 0.00186, 331 | -0.67751, 0.00180, 332 | 0.00516, -0.00151, 333 | -0.00365, -0.00210, 334 | -0.00276, 0.03793, 335 | -0.02637, 0.03235, 336 | -0.01343, 0.00541, 337 | -0.11270, 0.02169, 338 | -0.63365, 0.00122, 339 | -0.24329, 0.00428, 340 | -0.00040, 0.00586, 341 | 0.00581, 0.01112, 342 | -0.02731, 0.00008, 343 | -2.69091, 0.42729, 2.78805, 3.43849, 344 | -0.87998, -6.62373, 0.56882, 4.69370, 345 | 0.00005, -0.00008, 346 | -0.00181, 0.01767, 347 | -0.00168, 0.00660, 348 | 0.01802, -0.01836, 349 | -0.11245, -0.00061, 350 | 0.00199, -0.00070, 351 | -0.00076, 0.00919, 352 | 0.00311, -0.00165, 353 | -0.05650, -0.00018, 354 | 0.00121, -0.00069, 355 | -0.00803, 0.00146, 356 | -0.03260, -0.00072, 357 | -0.00042, 0.00524, 358 | 0.00464, -0.00339, 359 | -0.06203, -0.00278, 0.04145, 0.02871, 360 | -0.01962, -0.01362, 361 | -0.03040, -0.00010, 362 | 0.00085, -0.00001, 363 | -0.01712, -0.00006, 364 | -0.00996, -0.00003, 365 | -0.00029, 0.00026, 0.00016, -0.00005, 366 | -0.00594, -0.00003 367 | ], 368 | arg_tbl: [ 369 | 0, 3, 370 | 2, 2, 5, -5, 6, 0, 371 | 3, 2, 2, 1, 3, -8, 4, 0, 372 | 3, 5, 1, -14, 2, 2, 3, 0, 373 | 3, 3, 2, -7, 3, 4, 4, 0, 374 | 2, 8, 2, -13, 3, 2, 375 | 3, 6, 2, -10, 3, 3, 5, 0, 376 | 1, 1, 7, 0, 377 | 2, 1, 5, -2, 6, 0, 378 | 2, 1, 2, -3, 4, 2, 379 | 2, 2, 5, -4, 6, 1, 380 | 1, 1, 6, 0, 381 | 3, 3, 2, -5, 3, 1, 5, 0, 382 | 3, 3, 2, -5, 3, 2, 5, 0, 383 | 2, 1, 5, -1, 6, 0, 384 | 2, 2, 2, -6, 4, 1, 385 | 2, 2, 5, -3, 6, 0, 386 | 1, 2, 6, 0, 387 | 2, 3, 5, -5, 6, 0, 388 | 1, 1, 5, 1, 389 | 2, 2, 5, -2, 6, 0, 390 | 2, 3, 2, -5, 3, 2, 391 | 2, 5, 2, -8, 3, 1, 392 | 1, 2, 5, 0, 393 | 2, 2, 1, -5, 2, 1, 394 | 2, 6, 2, -10, 3, 0, 395 | 2, 2, 2, -3, 3, 2, 396 | 2, 1, 2, -2, 3, 1, 397 | 2, 4, 2, -7, 3, 0, 398 | 2, 4, 2, -6, 3, 0, 399 | 1, 1, 4, 0, 400 | 2, 1, 2, -2, 4, 0, 401 | 2, 2, 2, -5, 4, 0, 402 | 2, 1, 2, -1, 3, 0, 403 | 2, 1, 1, -3, 2, 0, 404 | 2, 2, 2, -4, 3, 0, 405 | 2, 6, 2, -9, 3, 0, 406 | 2, 3, 2, -4, 3, 2, 407 | 2, 1, 1, -2, 2, 0, 408 | 1, 1, 3, 0, 409 | 2, 1, 2, -1, 4, 0, 410 | 2, 2, 2, -4, 4, 0, 411 | 2, 5, 2, -7, 3, 0, 412 | 2, 2, 2, -2, 3, 0, 413 | 2, 1, 2, -3, 5, 0, 414 | 2, 1, 2, -3, 3, 0, 415 | 2, 7, 2, -10, 3, 0, 416 | 2, 1, 2, -2, 5, 1, 417 | 2, 4, 2, -5, 3, 1, 418 | 3, 1, 2, 1, 5, -5, 6, 0, 419 | 2, 1, 2, -1, 5, 0, 420 | 3, 1, 2, -3, 5, 5, 6, 0, 421 | 2, 1, 2, -2, 6, 0, 422 | 2, 1, 2, -1, 6, 0, 423 | 1, 3, 4, 0, 424 | 2, 7, 2, -13, 3, 0, 425 | 3, 1, 2, 2, 5, -5, 6, 1, 426 | 1, 1, 2, 5, 427 | 2, 9, 2, -13, 3, 0, 428 | 3, 1, 2, 1, 5, -2, 6, 0, 429 | 2, 2, 2, -3, 4, 2, 430 | 2, 3, 2, -6, 4, 0, 431 | 2, 1, 2, 1, 5, 0, 432 | 2, 2, 2, -5, 3, 0, 433 | 2, 6, 2, -8, 3, 0, 434 | 2, 2, 1, -4, 2, 0, 435 | 2, 3, 2, -3, 3, 0, 436 | 1, 2, 3, 0, 437 | 2, 3, 2, -7, 3, 0, 438 | 2, 5, 2, -6, 3, 1, 439 | 2, 2, 2, -2, 4, 0, 440 | 2, 3, 2, -5, 4, 0, 441 | 2, 2, 2, -1, 3, 0, 442 | 2, 7, 2, -9, 3, 0, 443 | 2, 4, 2, -4, 3, 0, 444 | 2, 1, 2, 1, 3, 0, 445 | 2, 3, 2, -4, 4, 0, 446 | 2, 6, 2, -7, 3, 0, 447 | 2, 3, 2, -2, 3, 0, 448 | 2, 2, 2, -4, 5, 0, 449 | 2, 2, 2, -3, 5, 0, 450 | 2, 2, 2, -2, 5, 0, 451 | 2, 5, 2, -5, 3, 0, 452 | 2, 2, 2, -3, 6, 0, 453 | 2, 2, 2, -1, 5, 0, 454 | 2, 2, 2, -2, 6, 0, 455 | 1, 2, 2, 3, 456 | 2, 2, 2, 1, 5, 0, 457 | 2, 7, 2, -8, 3, 0, 458 | 2, 2, 1, -3, 2, 0, 459 | 2, 4, 2, -3, 3, 0, 460 | 2, 6, 2, -6, 3, 0, 461 | 2, 3, 2, -1, 3, 0, 462 | 2, 8, 2, -9, 3, 0, 463 | 2, 5, 2, -4, 3, 0, 464 | 2, 7, 2, -7, 3, 0, 465 | 2, 4, 2, -2, 3, 0, 466 | 2, 3, 2, -4, 5, 0, 467 | 2, 3, 2, -3, 5, 0, 468 | 2, 9, 2, -10, 3, 0, 469 | 2, 3, 2, -2, 5, 0, 470 | 1, 3, 2, 2, 471 | 2, 8, 2, -8, 3, 0, 472 | 2, 5, 2, -3, 3, 0, 473 | 2, 9, 2, -9, 3, 0, 474 | 2, 10, 2, -10, 3, 0, 475 | 1, 4, 2, 1, 476 | 2, 11, 2, -11, 3, 0, 477 | -1 478 | ] 479 | } 480 | 481 | module.exports = venus 482 | -------------------------------------------------------------------------------- /src/astronomy/moshier/transit.js: -------------------------------------------------------------------------------- 1 | var altaz = require('./altaz') 2 | var body = require('./body') 3 | var constant = require('./constant') 4 | var custom_constant = require('../../custom.constant') 5 | var delta = require('./delta') 6 | var julian = require('./julian') 7 | var kepler = require('./kepler') 8 | var util = require('./util') 9 | 10 | var transit = { 11 | /** Earth radii per au */ 12 | DISFAC: 2.3454780e4, 13 | 14 | /** cosine of 90 degrees 50 minutes: */ 15 | COSSUN: -0.014543897651582657, 16 | /** cosine of 90 degrees 34 minutes: */ 17 | COSZEN: -9.8900378587411476e-3, 18 | 19 | /* Returned transit, rise, and set times in radians (2 pi = 1 day) */ 20 | r_trnsit: 0.0, 21 | r_rise: 0.0, 22 | r_set: 0.0, 23 | elevation_threshold: 0.0, 24 | semidiameter: 0.0, 25 | f_trnsit: false, // boolean 26 | southern_hemisphere: false, // boolean 27 | 28 | /* Julian dates of rise, transit and set times. */ 29 | t_rise: 0.0, 30 | t_trnsit: 0.0, 31 | elevation_trnsit: 0.0, 32 | t_set: 0.0, 33 | 34 | STEP_SCALE: 0.5 35 | }; 36 | 37 | /** 38 | * Calculate time of transit 39 | * assuming RA and Dec change uniformly with time 40 | */ 41 | transit.calc = function (date, lha, dec) { 42 | var NR = [], YR = []; 43 | 44 | this.f_trnsit = false; 45 | /* Initialize to no-event flag value. */ 46 | this.r_rise = -10.0; 47 | this.r_set = -10.0; 48 | /* observer's geodetic latitude, in radians */ 49 | var x = constant.glat * constant.DTR; 50 | var coslat = Math.cos(x); 51 | var sinlat = Math.sin(x); 52 | var cosdec = Math.cos(dec); 53 | var sindec = Math.sin(dec); 54 | 55 | this.southern_hemisphere = sinlat < 0; 56 | 57 | /* Refer to same start of date as iter_trnsit, 58 | so r_trnsit means the same thing in both programs. */ 59 | x = Math.floor(date.universal - 0.5) + 0.5; // UT 60 | x = (date.universal - x) * constant.TPI; // UT 61 | /* adjust local hour angle */ 62 | var y = lha; 63 | /* printf ("%.7f,", lha); */ 64 | while (y < -Math.PI) { 65 | y += constant.TPI; 66 | } 67 | while (y > Math.PI) { 68 | y -= constant.TPI; 69 | } 70 | var lhay = y; 71 | y = y/(-constant.dradt/constant.TPI + 1.00273790934); 72 | this.r_trnsit = x - y; 73 | /* printf ("rt %.7f ", r_trnsit); */ 74 | /* Ordinarily never print here. */ 75 | var result = { 76 | approxLocalMeridian: util.hms (this.r_trnsit), 77 | UTdate: this.r_trnsit/constant.TPI 78 | }; 79 | 80 | if (coslat != 0.0 && cosdec != 0.0) { 81 | /* The time at which the upper limb of the body meets the 82 | * horizon depends on the body's angular diameter. 83 | */ 84 | switch (constant.body.key) { 85 | /* Sun */ 86 | case 'sun': 87 | this.semidiameter = 0.2666666666666667; 88 | this.elevation_threshold = -0.8333333333333333; 89 | NR[0] = this.COSSUN 90 | NR[1] = custom_constant.COSSUN 91 | break; 92 | 93 | /* Moon, elevation = -34' - semidiameter + parallax 94 | * semidiameter = 0.272453 * parallax + 0.0799" 95 | */ 96 | case 'moon': 97 | var N = 1/(this.DISFAC*constant.body.position.polar.distance); 98 | var D = Math.asin(N); /* the parallax */ 99 | this.semidiameter = 0.2725076*D + 3.874e-7; 100 | NR[0] = NR[1] = -9.890199094634534e-3 - this.semidiameter + D; 101 | this.semidiameter *= constant.RTD; 102 | this.elevation_threshold = -34/60 - this.semidiameter; 103 | NR[0] = NR[1] = Math.sin(NR[0]); 104 | break; 105 | 106 | /* Other object */ 107 | default: 108 | NR[0] = NR[1] = this.COSZEN 109 | this.semidiameter = 0.0; 110 | this.elevation_threshold = -0.5666666666666666; 111 | break; 112 | } 113 | 114 | YR[0] = (NR[0] - sinlat*sindec)/(coslat*cosdec); 115 | YR[1] = (NR[1] - sinlat*sindec)/(coslat*cosdec); 116 | 117 | if (YR[0] < 1 && YR[0] > -1 && YR[1] < 1 && YR[1] > -1) { 118 | this.f_trnsit = true; 119 | 120 | /* Derivative of y with respect to declination 121 | * times rate of change of declination: 122 | */ 123 | var z = -constant.ddecdt*(sinlat + this.COSZEN*sindec); 124 | z /= constant.TPI*coslat*cosdec*cosdec; 125 | /* Derivative of acos(y): */ 126 | var zArr = []; 127 | zArr[0] = z / Math.sqrt(1 - YR[0]*YR[0]); 128 | zArr[1] = z / Math.sqrt(1 - YR[1]*YR[1]); 129 | YR[0] = Math.acos(YR[0]); 130 | YR[1] = Math.acos(YR[1]); 131 | D = -constant.dradt/constant.TPI + 1.00273790934; 132 | this.r_rise = x - (lhay + YR[0])*(1 + zArr[0])/D; 133 | this.r_set = x - (lhay - YR[0])*(1 - zArr[0])/D; 134 | this.r_sanatan_rise = x - (lhay + YR[1])*(1 + zArr[1])/D; 135 | this.r_sanatan_set = x - (lhay - YR[1])*(1 - zArr[1])/D; 136 | /* Ordinarily never print here. */ 137 | 138 | result.dApproxRiseUT = this.r_rise; 139 | result.dApproxSetUT = this.r_set; 140 | result.approxRiseUT = util.hms (this.r_rise); 141 | result.approxSetUT = util.hms (this.r_set); 142 | result.dApproxSanatanRiseUT = this.r_sanatan_rise; 143 | result.dApproxSanatanSetUT = this.r_sanatan_set; 144 | result.approxSanatanRiseUT = util.hms (this.r_sanatan_rise); 145 | result.approxSanatanSetUT = util.hms (this.r_sanatan_set); 146 | } 147 | } 148 | return result; 149 | }; 150 | 151 | /** Compute estimate of lunar rise and set times for iterative solution. */ 152 | transit.iterator = function (time, callback) { 153 | var date = { 154 | julian: time 155 | }; 156 | 157 | julian.toGregorian (date); 158 | julian.calc (date); 159 | delta.calc (date); 160 | 161 | kepler (date, body.earth); 162 | 163 | callback (); 164 | }; 165 | 166 | /** Iterative computation of rise, transit, and set times. */ 167 | transit.iterateTransit = function (callback) { 168 | var date, t0; // double 169 | var isPrtrnsit = false; 170 | var loopctr = 0; 171 | // var retry = 0; 172 | /* Start iteration at time given by the user. */ 173 | var t1 = body.earth.position.date.universal; // UT 174 | 175 | /* Find transit time. */ 176 | do { 177 | t0 = t1; 178 | date = Math.floor (t0 - 0.5) + 0.5; 179 | this.iterator (t0, callback); 180 | t1 = date + this.r_trnsit / constant.TPI; 181 | if (++loopctr > 10) { 182 | break; 183 | // goto no_trnsit; 184 | } 185 | } while (Math.abs (t1 - t0) > .0001); 186 | 187 | if (loopctr <= 10) { 188 | this.t_trnsit = t1; 189 | this.elevation_trnsit = altaz.elevation; 190 | var trnsit1 = this.r_trnsit; 191 | var set1 = this.r_set; 192 | if (!this.f_trnsit) { 193 | /* Rise or set time not found. Apply a search technique to 194 | check near inferior transit if object is above horizon now. */ 195 | this.t_rise = -1.0; 196 | this.t_set = -1.0; 197 | if (altaz.elevation > this.elevation_threshold) { 198 | this.noRiseSet (callback); 199 | } 200 | // goto prtrnsit; 201 | } else { 202 | /* Set current date to be that of the transit just found. */ 203 | var date_trnsit = date; 204 | t1 = date + this.r_rise / constant.TPI; 205 | /* Choose rising no later than transit. */ 206 | if (t1 >= this.t_trnsit) { 207 | date -= 1; 208 | t1 = date + this.r_rise / constant.TPI; 209 | } 210 | loopctr = 0; 211 | do { 212 | t0 = t1; 213 | this.iterator (t0, callback); 214 | /* Skip out if no event found. */ 215 | if (!this.f_trnsit) { 216 | /* Rise or set time not found. Apply search technique. */ 217 | this.t_rise = -1.0; 218 | this.t_set = -1.0; 219 | this.noRiseSet (callback); 220 | isPrtrnsit = true; 221 | // goto prtrnsit; 222 | } else if (++loopctr > 10) { 223 | // Rise time did not converge 224 | this.f_trnsit = false; 225 | isPrtrnsit = true; 226 | // goto prtrnsit; 227 | } else { 228 | t1 = date + this.r_rise / constant.TPI; 229 | if (t1 > this.t_trnsit) { 230 | date -= 1; 231 | t1 = date + this.r_rise / constant.TPI; 232 | } 233 | } 234 | } while (Math.abs (t1 - t0) > .0001); 235 | 236 | if (!isPrtrnsit) { 237 | var rise1 = this.r_rise; 238 | this.t_rise = t1; 239 | 240 | /* Set current date to be that of the transit. */ 241 | date = date_trnsit; 242 | this.r_set = set1; 243 | /* Choose setting no earlier than transit. */ 244 | t1 = date + this.r_set / constant.TPI; 245 | if (t1 <= this.t_trnsit) { 246 | date += 1; 247 | t1 = date + this.r_set / constant.TPI; 248 | } 249 | loopctr = 0; 250 | do { 251 | t0 = t1; 252 | this.iterator (t0, callback); 253 | if (!this.f_trnsit) { 254 | /* Rise or set time not found. Apply search technique. */ 255 | this.t_rise = -1.0; 256 | this.t_set = -1.0; 257 | this.noRiseSet (callback); 258 | isPrtrnsit = true; 259 | // goto prtrnsit; 260 | } else if (++loopctr > 10) { 261 | // Set time did not converge 262 | this.f_trnsit = false; 263 | isPrtrnsit = true; 264 | // goto prtrnsit; 265 | } else { 266 | t1 = date + this.r_set / constant.TPI; 267 | if (t1 < this.t_trnsit) { 268 | date += 1; 269 | t1 = date + this.r_set / constant.TPI; 270 | } 271 | } 272 | } while (Math.abs(t1 - t0) > .0001); 273 | 274 | if (!isPrtrnsit) { 275 | this.t_set = t1; 276 | this.r_trnsit = trnsit1; 277 | this.r_rise = rise1; 278 | } 279 | } 280 | } 281 | // prtrnsit: 282 | var result = {}; 283 | result.localMeridianTransit = julian.toGregorian ({julian: this.t_trnsit}); 284 | if (this.t_rise != -1.0) { 285 | result.riseDate = julian.toGregorian ({julian: this.t_rise}); 286 | } 287 | if (this.t_set != -1.0) { 288 | result.setDate = julian.toGregorian ({julian: this.t_set}); 289 | if (this.t_rise != -1.0) { 290 | t0 = this.t_set - this.t_rise; 291 | if (t0 > 0 && t0 < 1) { 292 | result.visibleHours = 24 * t0; 293 | } 294 | } 295 | } 296 | 297 | if ( 298 | Math.abs(body.earth.position.date.julian - this.t_rise) > 0.5 && 299 | Math.abs(body.earth.position.date.julian - this.t_trnsit) > 0.5 && 300 | Math.abs(body.earth.position.date.julian - this.t_set) > 0.5 301 | ) { 302 | // wrong event date 303 | result.wrongEventDate = true; 304 | } 305 | } 306 | // no_trnsit: 307 | // prtflg = prtsave; 308 | this.f_trnsit = true; 309 | return result; 310 | }; 311 | 312 | /** 313 | * If the initial approximation fails to locate a rise or set time, 314 | * this function steps between the transit time and the previous 315 | * or next inferior transits to find an event more reliably. 316 | */ 317 | transit.noRiseSet = function (callback) { 318 | var t_trnsit0 = this.t_trnsit; // double 319 | var el_trnsit0 = this.elevation_trnsit; // double 320 | 321 | /* Step time toward previous inferior transit to find 322 | whether a rise event was missed. The step size is a function 323 | of the azimuth and decreases near the transit time. */ 324 | var t_above = t_trnsit0; 325 | var el_above = el_trnsit0; 326 | var t_below = -1.0; 327 | var el_below = el_above; 328 | var t = t_trnsit0 - 0.25; 329 | var e = 1.0; 330 | while (e > 0.005) { 331 | this.iterator (t, callback); 332 | if (altaz.elevation > this.elevation_threshold) { 333 | /* Object still above horizon. */ 334 | t_above = t; 335 | el_above = altaz.elevation; 336 | } else { 337 | /* Object is below horizon. Rise event is bracketed. 338 | Proceed to interval halving search. */ 339 | t_below = t; 340 | el_below = altaz.elevation; 341 | break; // goto search_rise; 342 | } 343 | /* Step time by an amount proportional to the azimuth deviation. */ 344 | e = altaz.azimuth/360; 345 | if (altaz.azimuth < 180) { 346 | if (this.southern_hemisphere) { 347 | t += this.STEP_SCALE * e; 348 | } else { 349 | t -= this.STEP_SCALE * e; 350 | } 351 | } else { 352 | e = 1 - e; 353 | if (this.southern_hemisphere) { 354 | t -= this.STEP_SCALE * e; 355 | } else { 356 | t += this.STEP_SCALE * e; 357 | } 358 | } 359 | } 360 | 361 | /* No rise event detected. */ 362 | if (altaz.elevation > this.elevation_threshold) { 363 | /* Previous inferior transit is above horizon. */ 364 | this.t_rise = -1.0; 365 | } else { 366 | /* Find missed rise time. */ 367 | // search_rise: 368 | this.t_rise = this.searchHalve (t_below, el_below, t_above, el_above, callback); 369 | this.f_trnsit = true; 370 | } 371 | 372 | /* Step forward in time toward the next inferior transit. */ 373 | t_above = t_trnsit0; 374 | el_above = el_trnsit0; 375 | t_below = -1.0; 376 | el_below = el_above; 377 | t = t_trnsit0 + 0.25; 378 | e = 1.0; 379 | while (e > 0.005) { 380 | this.iterator (t, callback); 381 | if (altaz.elevation > this.elevation_threshold) { 382 | /* Object still above horizon. */ 383 | t_above = t; 384 | el_above = altaz.elevation; 385 | } else { 386 | /* Object is below horizon. Event is bracketed. 387 | Proceed to interval halving search. */ 388 | t_below = t; 389 | el_below = altaz.elevation; 390 | break; // goto search_set; 391 | } 392 | /* Step time by an amount proportional to the azimuth deviation. */ 393 | e = altaz.azimuth/360; 394 | if (altaz.azimuth < 180) { 395 | if (this.southern_hemisphere) { 396 | t += this.STEP_SCALE * e; /* Southern hemisphere observer. */ 397 | } else { 398 | t -= this.STEP_SCALE * e; 399 | } 400 | } else { 401 | e = 1 - e; 402 | if (this.southern_hemisphere) { 403 | t -= this.STEP_SCALE * e; 404 | } else { 405 | t += this.STEP_SCALE * e; 406 | } 407 | } 408 | } 409 | 410 | if (altaz.elevation > this.elevation_threshold) { 411 | /* Next inferior transit is above horizon. */ 412 | this.t_set = -1.0; 413 | // return 0; 414 | } else { 415 | /* Find missed set time. */ 416 | // search_set: 417 | this.t_set = this.searchHalve (t, altaz.elevation, this.t_trnsit, this.elevation_trnsit, callback); 418 | this.f_trnsit = true; 419 | } 420 | }; 421 | 422 | /** 423 | * Search rise or set time by simple interval halving 424 | * after the event has been bracketed in time. 425 | */ 426 | transit.searchHalve = function (t1, y1, t2, y2, callback) { 427 | var e2 = y2 - this.elevation_threshold; 428 | var tm = 0.5 * (t1 + t2); 429 | 430 | while (Math.abs(t2 - t1) > .00001) { 431 | /* Evaluate at middle of current interval. */ 432 | tm = 0.5 * (t1 + t2); 433 | this.iterator (tm, callback); 434 | var em = altaz.elevation - this.elevation_threshold; 435 | /* Replace the interval boundary whose error has the same sign as em. */ 436 | if (em * e2 > 0) { 437 | t2 = tm; 438 | e2 = em; 439 | } else { 440 | t1 = tm; 441 | } 442 | } 443 | return tm; 444 | }; 445 | 446 | module.exports = transit 447 | -------------------------------------------------------------------------------- /src/astronomy/moshier/constellation.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | var precess = require('./precess') 3 | 4 | var constellation = { 5 | /** Constellation names */ 6 | constel: [ 7 | 'And Andromedae', 8 | 'Ant Antliae', 9 | 'Aps Apodis', 10 | 'Aql Aquilae', 11 | 'Aqr Aquarii', 12 | 'Ari Arietis', 13 | 'Ara Arae', 14 | 'Aur Aurigae', 15 | 'Boo Bootis', 16 | 'Cae Caeli', 17 | 'Cam Camelopardalis', 18 | 'Can Cancri', /* also abbreviated Cnc */ 19 | 'Cap Capricorni', 20 | 'Car Carinae', 21 | 'Cas Cassiopeiae', 22 | 'Cen Centauri', 23 | 'Cep Cephei', 24 | 'Cet Ceti', 25 | 'Cha Chamaeleontis', 26 | 'Cir Circini', 27 | 'CMa Canis Majoris', 28 | 'CMi Canis Minoris', 29 | 'Cnc Cancri', 30 | 'Col Columbae', 31 | 'Com Comae Berenices', 32 | 'CrA Coronae Austrinae', 33 | 'CrB Coronae Borealis', 34 | 'Crt Crateris', 35 | 'Cru Crucis', 36 | 'Crv Corvi', 37 | 'CVn Canum Venaticorum', 38 | 'Cyg Cygni', 39 | 'Del Delphini', 40 | 'Dor Doradus', 41 | 'Dra Draconis', 42 | 'Equ Equulei', 43 | 'Eri Eridani', 44 | 'For Fornacis', 45 | 'Gem Geminorum', 46 | 'Gru Gruis', 47 | 'Her Herculis', 48 | 'Hor Horologii', 49 | 'Hya Hydrae', 50 | 'Hyi Hydri', 51 | 'Ind Indi', 52 | 'Lac Lacertae', 53 | 'Leo Leonis', 54 | 'Lep Leporis', 55 | 'Lib Librae', 56 | 'LMi Leonis Minoris', 57 | 'Lup Lupi', 58 | 'Lyn Lyncis', 59 | 'Lyr Lyrae', 60 | 'Men Mensae', 61 | 'Mic Microscopii', 62 | 'Mon Monocerotis', 63 | 'Mus Muscae', 64 | 'Nor Normae', 65 | 'Oct Octantis', 66 | 'Oph Ophiuchi', 67 | 'Ori Orionis', 68 | 'Pav Pavonis', 69 | 'Peg Pegasi', 70 | 'Per Persei', 71 | 'Phe Phoenicis', 72 | 'Pic Pictoris', 73 | 'PsA Piscis Austrini', 74 | 'Psc Piscium', 75 | 'Pup Puppis', 76 | 'Pyx Pyxidis', 77 | 'Ret Reticuli', 78 | 'Scl Sculptoris', 79 | 'Sco Scorpii', 80 | 'Sct Scuti', 81 | 'Ser Serpentis', 82 | 'Sex Sextantis', 83 | 'Sge Sagittae', 84 | 'Sgr Sagittarii', 85 | 'Tau Tauri', 86 | 'Tel Telescopii', 87 | 'TrA Trianguli Australis', 88 | 'Tri Trianguli', 89 | 'Tuc Tucanae', 90 | 'UMa Ursae Majoris', 91 | 'UMi Ursae Minoris', 92 | 'Vel Velorum', 93 | 'Vir Virginis', 94 | 'Vol Volantis', 95 | 'Vul Vulpeculae' 96 | ], 97 | 98 | /** Greek letters */ 99 | greek: [ 100 | 'alpha', 101 | 'beta', 102 | 'gamma', 103 | 'delta', 104 | 'epsilon', 105 | 'zeta', 106 | 'eta', 107 | 'theta', 108 | 'iota', 109 | 'kappa', 110 | 'lambda', 111 | 'mu', 112 | 'nu', 113 | 'xi', 114 | 'omicron', 115 | 'pi', 116 | 'rho', 117 | 'sigma', 118 | 'tau', 119 | 'upsilon', 120 | 'phi', 121 | 'chi', 122 | 'psi', 123 | 'omega' 124 | ], 125 | 126 | /** 127 | * Table of constellation boundaries. 128 | * 129 | * Roman, Nancy Grace, "Identification of a Constellation from a Position" 130 | * Pub. Astron. Soc. Pac. 99, 695, (1987) 131 | * 132 | * Array items are 133 | * Lower Right Ascension, Upper Right Ascension, 134 | * both in units of hours times 3600; 135 | * Lower Declination, in units of degrees times 3600; 136 | * and array index of constellation name. 137 | */ 138 | bndries: [ 139 | 0, 86400, 316800, 84, 140 | 28800, 52200, 311400, 84, 141 | 75600, 82800, 310200, 84, 142 | 64800, 75600, 309600, 84, 143 | 0, 28800, 306000, 16, 144 | 33000, 38400, 295200, 10, 145 | 0, 18000, 288000, 16, 146 | 38400, 52200, 288000, 10, 147 | 63000, 64800, 288000, 84, 148 | 72600, 75600, 288000, 34, 149 | 0, 12630, 277200, 16, 150 | 41400, 48900, 277200, 10, 151 | 59520, 63000, 270000, 84, 152 | 72600, 74400, 270000, 16, 153 | 28680, 33000, 264600, 10, 154 | 33000, 40800, 264600, 34, 155 | 46800, 59520, 252000, 84, 156 | 11160, 12300, 244800, 14, 157 | 73500, 74400, 241200, 34, 158 | 40800, 43200, 239400, 34, 159 | 0, 1200, 237600, 16, 160 | 50400, 56400, 237600, 84, 161 | 84900, 86400, 237600, 16, 162 | 43200, 48600, 230400, 34, 163 | 48600, 51900, 226800, 34, 164 | 83400, 84900, 226800, 16, 165 | 21960, 25200, 223200, 10, 166 | 72000, 73500, 221400, 34, 167 | 73932, 74160, 219300, 16, 168 | 25200, 28680, 216000, 10, 169 | 28680, 30300, 216000, 83, 170 | 71160, 72000, 214200, 34, 171 | 72000, 73932, 214200, 16, 172 | 82320, 83400, 212700, 16, 173 | 0, 8760, 210600, 14, 174 | 69900, 71160, 208800, 34, 175 | 6120, 6870, 207000, 14, 176 | 8760, 11160, 205200, 14, 177 | 11160, 11400, 205200, 10, 178 | 80340, 82320, 202500, 16, 179 | 18000, 21960, 201600, 10, 180 | 50520, 51900, 199800, 83, 181 | 51900, 69900, 199800, 34, 182 | 11400, 12000, 198000, 10, 183 | 79680, 80340, 198000, 16, 184 | 74160, 79080, 197400, 16, 185 | 0, 6120, 194400, 14, 186 | 21960, 23400, 194400, 51, 187 | 43500, 48600, 190800, 83, 188 | 54900, 56700, 190800, 34, 189 | 79080, 79680, 189900, 16, 190 | 12000, 18000, 189000, 10, 191 | 82320, 84000, 189000, 14, 192 | 56700, 61200, 185400, 34, 193 | 7350, 9060, 181800, 63, 194 | 61200, 65640, 181800, 34, 195 | 0, 4920, 180000, 14, 196 | 4920, 6000, 180000, 63, 197 | 23400, 24480, 180000, 51, 198 | 84000, 86400, 180000, 14, 199 | 48600, 50520, 174600, 83, 200 | 0, 4020, 172800, 14, 201 | 84900, 86400, 172800, 14, 202 | 65430, 65640, 171000, 40, 203 | 65640, 68700, 171000, 34, 204 | 68700, 69000, 171000, 31, 205 | 6000, 7350, 169200, 63, 206 | 30300, 33000, 169200, 83, 207 | 600, 3120, 165600, 14, 208 | 43200, 43500, 162000, 83, 209 | 24480, 26520, 160200, 51, 210 | 78870, 79080, 158400, 31, 211 | 78750, 78870, 157500, 31, 212 | 69000, 69840, 156600, 31, 213 | 33000, 36600, 151200, 83, 214 | 36600, 38820, 144000, 83, 215 | 55560, 56700, 144000, 8, 216 | 56700, 58800, 144000, 40, 217 | 33300, 34500, 143100, 51, 218 | 0, 9060, 132300, 0, 219 | 9060, 9240, 132300, 63, 220 | 69690, 69840, 131400, 52, 221 | 16200, 16890, 129600, 63, 222 | 78240, 78750, 129600, 31, 223 | 78750, 79200, 129600, 45, 224 | 23520, 26520, 127800, 7, 225 | 26520, 27900, 127800, 51, 226 | 0, 7200, 126000, 0, 227 | 79200, 82140, 126000, 45, 228 | 82140, 82320, 124200, 45, 229 | 82320, 84600, 124200, 0, 230 | 9240, 9780, 122400, 63, 231 | 38820, 39600, 122400, 83, 232 | 43200, 44400, 122400, 30, 233 | 27900, 33300, 120600, 51, 234 | 33300, 35580, 120600, 49, 235 | 2580, 5070, 118800, 0, 236 | 54660, 55560, 118800, 8, 237 | 84600, 85500, 115500, 0, 238 | 44400, 47700, 115200, 30, 239 | 85500, 86400, 112800, 0, 240 | 50250, 50520, 110700, 30, 241 | 8700, 9780, 110400, 81, 242 | 9780, 16200, 110400, 63, 243 | 16200, 17100, 108000, 7, 244 | 65430, 69690, 108000, 52, 245 | 39600, 43200, 104400, 83, 246 | 70800, 75300, 104400, 31, 247 | 17100, 21180, 102600, 7, 248 | 35580, 37800, 102600, 49, 249 | 47700, 50250, 102600, 30, 250 | 0, 240, 100800, 0, 251 | 5070, 6000, 100800, 81, 252 | 21180, 23520, 100800, 7, 253 | 28380, 28800, 100800, 38, 254 | 75300, 78240, 100800, 31, 255 | 69330, 70800, 99000, 31, 256 | 6900, 8700, 98100, 81, 257 | 58200, 58800, 97200, 26, 258 | 54300, 54660, 93600, 8, 259 | 54660, 58200, 93600, 26, 260 | 66120, 67920, 93600, 52, 261 | 38700, 39600, 91800, 49, 262 | 67920, 69330, 91800, 52, 263 | 6000, 6900, 90000, 81, 264 | 2580, 3060, 85500, 67, 265 | 37800, 38700, 84600, 49, 266 | 76500, 77100, 84600, 88, 267 | 20520, 21180, 82200, 78, 268 | 240, 510, 79200, 0, 269 | 57300, 57720, 79200, 74, 270 | 21180, 22380, 77400, 38, 271 | 71400, 72900, 76500, 88, 272 | 67920, 69300, 75900, 88, 273 | 510, 3060, 75600, 0, 274 | 72900, 74040, 73800, 88, 275 | 28110, 28380, 72000, 38, 276 | 74040, 76500, 70200, 88, 277 | 69300, 71400, 69000, 88, 278 | 11820, 12120, 68400, 5, 279 | 67920, 68400, 66600, 76, 280 | 20520, 20760, 64800, 60, 281 | 22380, 22710, 63000, 38, 282 | 68400, 71400, 58200, 76, 283 | 17880, 19200, 57600, 78, 284 | 57300, 57900, 57600, 40, 285 | 71400, 72900, 56700, 76, 286 | 16620, 17880, 55800, 78, 287 | 19200, 20160, 55800, 78, 288 | 46200, 48600, 54000, 24, 289 | 62100, 65700, 51600, 40, 290 | 42720, 46200, 50400, 24, 291 | 27000, 28110, 48600, 38, 292 | 60300, 62100, 46200, 40, 293 | 0, 510, 45000, 62, 294 | 20160, 20760, 45000, 78, 295 | 25200, 27000, 45000, 38, 296 | 76020, 76800, 45000, 62, 297 | 22710, 24960, 43200, 38, 298 | 65700, 67920, 43200, 40, 299 | 75150, 75780, 42600, 32, 300 | 75780, 76020, 42600, 62, 301 | 41460, 42720, 39600, 46, 302 | 22470, 22710, 36000, 60, 303 | 24960, 25200, 36000, 38, 304 | 28110, 28530, 36000, 22, 305 | 85800, 86400, 36000, 62, 306 | 6000, 11820, 35700, 5, 307 | 72510, 73080, 30600, 32, 308 | 48600, 54300, 28800, 8, 309 | 81900, 85800, 27000, 62, 310 | 28530, 33300, 25200, 22, 311 | 33300, 38700, 25200, 46, 312 | 65700, 67184, 22500, 59, 313 | 67184, 67920, 22500, 3, 314 | 75000, 75150, 21600, 32, 315 | 25200, 25260, 19800, 21, 316 | 65700, 66330, 16200, 74, 317 | 57900, 60300, 14400, 40, 318 | 65700, 66330, 10800, 59, 319 | 77280, 78000, 9900, 62, 320 | 0, 7200, 7200, 67, 321 | 66900, 67920, 7200, 74, 322 | 73080, 75000, 7200, 32, 323 | 75000, 76800, 7200, 35, 324 | 76800, 77280, 7200, 62, 325 | 79200, 81900, 7200, 62, 326 | 78000, 79200, 6300, 62, 327 | 25260, 25920, 5400, 21, 328 | 12900, 16620, 0, 78, 329 | 16620, 16800, 0, 60, 330 | 25920, 29100, 0, 21, 331 | 52800, 54300, 0, 86, 332 | 64200, 65700, 0, 59, 333 | 9540, 11820, -6300, 17, 334 | 11820, 12900, -6300, 78, 335 | 54300, 58560, -11700, 74, 336 | 16800, 18300, -14400, 60, 337 | 21000, 22470, -14400, 60, 338 | 64200, 64680, -14400, 74, 339 | 65700, 66900, -14400, 74, 340 | 66900, 67920, -14400, 3, 341 | 81900, 85800, -14400, 67, 342 | 38700, 41460, -21600, 46, 343 | 41460, 42600, -21600, 86, 344 | 0, 1200, -25200, 67, 345 | 85800, 86400, -25200, 67, 346 | 51300, 52800, -28800, 86, 347 | 57300, 58560, -28800, 59, 348 | 72000, 73920, -32400, 3, 349 | 76800, 78720, -32400, 4, 350 | 61800, 64680, -36000, 59, 351 | 21000, 29100, -39600, 55, 352 | 17700, 18300, -39600, 36, 353 | 18300, 21000, -39600, 60, 354 | 29100, 30120, -39600, 42, 355 | 34500, 38700, -39600, 75, 356 | 42600, 46200, -39600, 86, 357 | 63300, 63600, -42000, 59, 358 | 67920, 72000, -43320, 3, 359 | 17400, 17700, -52200, 36, 360 | 73920, 76800, -54000, 4, 361 | 61800, 65700, -57600, 74, 362 | 65700, 67920, -57600, 73, 363 | 30120, 30900, -61200, 42, 364 | 58560, 58950, -65700, 59, 365 | 30900, 32700, -68400, 42, 366 | 38700, 39000, -68400, 27, 367 | 58560, 58950, -69300, 59, 368 | 56400, 57300, -72000, 48, 369 | 45300, 46200, -79200, 29, 370 | 46200, 51300, -79200, 86, 371 | 32700, 35100, -86400, 42, 372 | 6000, 9540, -87780, 17, 373 | 9540, 13500, -87780, 36, 374 | 39000, 42600, -88200, 27, 375 | 42600, 45300, -88200, 29, 376 | 51300, 53700, -88200, 48, 377 | 58560, 60300, -88500, 59, 378 | 0, 6000, -91800, 17, 379 | 76800, 78720, -91800, 12, 380 | 78720, 85800, -91800, 4, 381 | 85800, 86400, -91800, 17, 382 | 35100, 36900, -95400, 42, 383 | 16920, 17400, -98100, 36, 384 | 17400, 22020, -98100, 47, 385 | 72000, 76800, -100800, 12, 386 | 36900, 38100, -105000, 42, 387 | 45300, 53700, -106200, 42, 388 | 53700, 56400, -106200, 48, 389 | 56400, 57600, -106200, 72, 390 | 16500, 16920, -108000, 36, 391 | 60300, 63360, -108000, 59, 392 | 63360, 64200, -108000, 77, 393 | 38100, 39000, -112200, 42, 394 | 22020, 26520, -118800, 20, 395 | 44100, 45300, -118800, 42, 396 | 39000, 44100, -126000, 42, 397 | 12600, 13500, -129600, 37, 398 | 30120, 33720, -132300, 69, 399 | 15360, 16500, -133200, 36, 400 | 64200, 69000, -133200, 77, 401 | 76800, 82800, -133200, 66, 402 | 82800, 84000, -133200, 71, 403 | 10800, 12600, -142500, 37, 404 | 33720, 39600, -143100, 1, 405 | 0, 6000, -144000, 71, 406 | 6000, 10800, -144000, 37, 407 | 13920, 15360, -144000, 36, 408 | 84000, 86400, -144000, 71, 409 | 51000, 53700, -151200, 15, 410 | 56400, 57600, -151200, 50, 411 | 57600, 59115, -151200, 72, 412 | 17400, 18000, -154800, 9, 413 | 18000, 23700, -154800, 23, 414 | 28800, 30120, -154800, 68, 415 | 12300, 13920, -158400, 36, 416 | 59115, 64200, -163800, 72, 417 | 64200, 69000, -163800, 25, 418 | 69000, 73200, -163800, 77, 419 | 73200, 76800, -163800, 54, 420 | 10800, 12300, -165600, 36, 421 | 16200, 17400, -167400, 9, 422 | 55200, 56400, -172800, 50, 423 | 0, 8400, -173400, 64, 424 | 9600, 10800, -176400, 36, 425 | 14700, 15360, -176400, 41, 426 | 15360, 16200, -176400, 9, 427 | 76800, 79200, -180000, 39, 428 | 21600, 28800, -182700, 68, 429 | 28800, 29400, -182700, 85, 430 | 8700, 9600, -183600, 36, 431 | 13800, 14700, -183600, 41, 432 | 0, 6600, -185400, 64, 433 | 21600, 22200, -189000, 13, 434 | 29400, 30420, -190800, 85, 435 | 12600, 13800, -191400, 41, 436 | 13800, 14400, -191400, 33, 437 | 0, 5700, -192600, 64, 438 | 7800, 8700, -194400, 36, 439 | 16200, 18000, -194400, 65, 440 | 54180, 55200, -194400, 50, 441 | 30420, 31800, -196200, 85, 442 | 22200, 23400, -198000, 13, 443 | 42600, 46200, -198000, 15, 444 | 51000, 54180, -198000, 50, 445 | 54180, 55200, -198000, 57, 446 | 14400, 15600, -203400, 33, 447 | 31800, 39600, -203400, 85, 448 | 39600, 40500, -203400, 15, 449 | 63000, 64800, -205200, 6, 450 | 64800, 73200, -205200, 79, 451 | 79200, 84000, -205200, 39, 452 | 11520, 12600, -207000, 41, 453 | 18000, 19800, -207000, 65, 454 | 23400, 24600, -208800, 13, 455 | 0, 4800, -210600, 64, 456 | 4800, 7800, -210600, 36, 457 | 84000, 86400, -210600, 64, 458 | 15600, 16500, -212400, 33, 459 | 55200, 59115, -216000, 57, 460 | 73200, 76800, -216000, 44, 461 | 19800, 21600, -219600, 65, 462 | 54600, 55200, -219600, 19, 463 | 59115, 59700, -219600, 6, 464 | 53700, 54600, -228900, 19, 465 | 59700, 60300, -228900, 6, 466 | 21600, 24600, -230400, 65, 467 | 24600, 32520, -230400, 13, 468 | 40500, 42600, -230400, 15, 469 | 42600, 46200, -230400, 28, 470 | 46200, 52320, -230400, 15, 471 | 48600, 49200, -234000, 19, 472 | 60300, 60600, -234000, 6, 473 | 7800, 11520, -243000, 41, 474 | 11520, 16500, -243000, 70, 475 | 53100, 53700, -243000, 19, 476 | 60600, 63000, -243000, 6, 477 | 63000, 64800, -243000, 61, 478 | 79200, 84000, -243000, 82, 479 | 16500, 23700, -252000, 33, 480 | 49200, 53100, -252000, 19, 481 | 53100, 61200, -252000, 80, 482 | 0, 4800, -270000, 82, 483 | 12600, 16500, -270000, 43, 484 | 23700, 32520, -270000, 87, 485 | 32520, 40500, -270000, 13, 486 | 40500, 49200, -270000, 56, 487 | 64800, 76800, -270000, 61, 488 | 76800, 84000, -270000, 44, 489 | 84000, 86400, -270000, 82, 490 | 2700, 4800, -273600, 82, 491 | 0, 12600, -297000, 43, 492 | 27600, 49200, -297000, 18, 493 | 49200, 64800, -297000, 2, 494 | 12600, 27600, -306000, 53, 495 | 0, 86400, -324000, 58 496 | ] 497 | } 498 | 499 | /** 500 | * Return the constellation name corresponding to a given mean equatorial 501 | * position P. EPOCH is the precessional equinox and ecliptic date 502 | * of P. 503 | */ 504 | constellation.calc = function (pp, epoch) { 505 | var p = { 506 | longitude: pp.longitude, 507 | latitude: pp.latitude, 508 | distance: pp.distance 509 | } 510 | 511 | /* Precess from given epoch to J2000. */ 512 | precess.calc(p, epoch, 1) 513 | /* Precess from J2000 to Besselian epoch 1875.0. */ 514 | precess.calc(p, {julian: 2405889.25855}, -1) 515 | var d = Math.sqrt(p.longitude * p.longitude 516 | + p.latitude * p.latitude + p.distance * p.distance 517 | ) 518 | var ra = Math.atan2(p.latitude, p.longitude) * (constant.RTD * 3600 / 15) 519 | if (ra < 0) { 520 | ra += 86400.0 521 | } 522 | var dec = Math.asin(p.distance / d) * (constant.RTD * 3600) 523 | 524 | /* FIND CONSTELLATION SUCH THAT THE DECLINATION ENTERED IS HIGHER THAN 525 | THE LOWER BOUNDARY OF THE CONSTELLATION WHEN THE UPPER AND LOWER 526 | RIGHT ASCENSIONS FOR THE CONSTELLATION BOUND THE ENTERED RIGHT 527 | ASCENSION 528 | */ 529 | for (var i = 0; i < this.bndries.length / 4; i++) { 530 | var k = i << 2 531 | if (ra >= this.bndries[k] && ra < this.bndries[k + 1] && dec > this.bndries[k + 2]) { 532 | k = this.bndries[k + 3] 533 | return k 534 | } 535 | } 536 | return -1 537 | } 538 | 539 | module.exports = constellation 540 | -------------------------------------------------------------------------------- /src/astronomy/moshier/plan404/mercury.js: -------------------------------------------------------------------------------- 1 | var mercury = { 2 | maxargs: 9, 3 | max_harmonic: [11, 14, 10, 11, 4, 5, 2, 0, 0], 4 | max_power_of_t: 6, 5 | distance: 3.8709830979999998e-01, 6 | timescale: 3652500.0, 7 | trunclvl: 1.0, 8 | lon_tbl: [ 9 | 35.85255, -163.26379, 53810162857.56026, 908082.18475, 10 | 0.05214, -0.07712, 11 | 1.07258, 0.04008, 0.49259, 0.00230, 12 | 0.02324, 0.05869, 13 | 0.24516, 0.22898, -0.06037, 0.13023, 14 | 0.00331, -0.03576, 15 | 0.06464, 0.00089, 16 | 0.03103, 0.05078, 17 | -0.01133, 0.01520, 18 | 0.14654, 0.07538, 0.25112, -0.24473, 19 | -0.17928, -0.53366, 20 | -0.06367, 0.20458, -0.42985, 0.14848, 21 | -0.35317, -0.61364, 22 | 0.00325, -0.08617, -0.23180, 0.08576, 23 | 0.22995, 0.43569, 24 | 1.92114, 2.89319, -5.55637, 4.70329, 25 | -4.91411, -5.45521, 26 | 0.02607, 0.04468, 27 | -0.05439, 0.13476, -0.07329, -0.00985, 28 | -0.00278, 0.05377, 29 | 0.07474, -0.09658, 0.29818, 0.20422, 30 | -0.29074, 0.44962, 31 | -0.15411, -0.04287, 0.29907, -1.02948, 32 | 3.62183, 0.84869, 33 | -0.08157, 0.02754, 34 | -0.03610, -0.12909, 0.09195, -0.04424, 35 | -0.08845, 0.09347, 36 | -0.27140, 0.08185, 37 | 0.24783, 0.19543, -0.25154, 0.41371, 38 | -0.00046, 0.01524, 39 | 0.04127, 0.06663, 40 | 0.43023, 0.11790, 41 | 0.04427, 0.05329, 42 | 0.00411, -0.71074, 43 | -0.07111, -0.09824, 44 | 0.01264, -0.02075, 45 | -0.00068, -0.01678, 46 | 0.01186, 0.00181, 47 | 0.00302, -0.21963, 48 | -0.06412, -0.10155, -0.36856, 0.20240, 49 | 0.32282, 0.65133, 50 | -0.07178, -0.01876, 0.13399, -0.39522, 51 | 1.28413, 0.33790, 52 | 0.05040, -0.01679, 53 | -0.00794, 0.01117, 54 | 0.02630, 0.00575, 55 | -0.07113, -0.11414, 0.16422, -0.23060, 56 | 0.35198, 0.05409, 57 | 1.11486, -0.35833, 0.87313, 1.66304, 58 | -1.28434, 0.72067, 59 | 0.01400, 0.00971, 60 | 0.21044, -0.87385, 3.20820, 0.67957, 61 | -0.01716, 0.00111, 62 | -0.13776, -0.02650, 63 | -0.06778, 0.00908, 0.00616, -0.04520, 64 | -0.31625, -0.61913, 65 | 0.36184, 0.09373, 66 | 0.00984, -0.03292, 67 | 0.01944, 0.00530, 68 | 0.00243, -0.00123, 69 | 0.01589, 0.02223, 70 | -0.02992, -0.01086, 71 | 4356.04809, -5859.86328, 2918.27323, -4796.67315, 72 | 510.24783, -1220.02233, 127.48927, 250.10654, 73 | 3250.43013, -904.27614, -5667.40042, -22634.00922, 74 | -82471.79425, 18615.92342, 75 | 0.01941, 0.00372, 76 | 0.01830, -0.00652, 77 | -0.02548, -0.01157, 78 | 0.00635, 0.02343, 79 | -0.00980, 0.00961, 80 | 0.12137, 0.10068, 0.16676, -0.07257, 81 | -0.07267, -0.13761, 0.25305, -0.28112, 82 | -0.07974, 0.07866, 83 | -0.41726, 0.49991, -1.55187, -1.14150, 84 | 1.54754, -2.35141, 85 | -0.00862, 0.00808, 86 | 0.00218, -0.03726, 87 | 0.06914, -0.08986, 88 | -0.00501, 2.09577, 89 | -0.01409, -0.01842, 90 | 0.04138, 0.05961, 91 | -0.12276, -0.04929, 92 | -0.03963, -0.06080, 93 | -0.27697, -0.09329, 94 | -0.01011, 0.00295, 95 | -0.01374, 0.01328, 96 | -0.00171, 0.25815, 97 | 0.01446, 0.00782, 98 | 0.17909, -0.04683, 99 | 0.03765, -0.04990, 100 | 0.00036, 0.00528, 101 | 0.05508, -0.01369, 102 | -0.11751, -0.10624, -0.14448, 0.10522, 103 | -0.00884, 0.43006, 104 | 0.01162, 0.01659, 105 | -0.00076, 0.10143, 106 | 0.55779, 0.05510, 0.12350, -0.34025, 107 | 0.01320, 0.92985, 108 | -0.00026, -0.03426, 109 | 0.01305, 0.00041, 110 | 0.13187, -0.11903, 111 | 0.00058, 0.09877, 112 | -33.10230, -41.96782, -268.28908, 174.29259, 113 | 731.20089, 1508.07639, 5223.99114, -3008.08849, 114 | -3909.34957, -9646.69156, 115 | 0.02988, 0.03182, 116 | 0.07149, 0.04513, 117 | -0.02356, -0.01641, 118 | -0.03188, -0.03711, 0.15084, -0.22436, 119 | 0.61987, 0.25706, 120 | 0.02425, 0.01200, 121 | -0.05543, -0.14435, -0.53398, 0.10997, 122 | 0.00465, -0.01893, 123 | 0.01260, -0.01314, 124 | 0.00650, -0.05499, 125 | -0.06804, 0.01608, 126 | 0.02134, 0.04160, 127 | 0.00636, 0.01293, 128 | -0.03470, -0.02697, 129 | -0.11323, 0.02409, 130 | -0.02618, 0.00827, 131 | 0.01879, 0.16838, 0.08978, 0.01934, 132 | -0.23564, 0.05565, 133 | 0.03686, 0.02644, 134 | -0.02471, 0.00558, 135 | -140.22669, -120.40692, -501.88143, 434.05868, 136 | 1044.54998, 1162.72084, 1527.78437, -882.37371, 137 | -0.00768, 0.02213, 138 | -0.04090, 0.16718, 139 | -0.05923, -0.12595, 140 | 0.01154, -0.00025, 141 | -0.00776, -0.01653, 142 | -0.01213, -0.02773, 143 | 0.00344, 0.02180, 144 | -0.02558, -0.05682, 145 | -0.00490, 0.01050, 146 | 38.75496, -78.17502, -189.90700, -136.33371, 147 | -249.94062, 319.76423, 205.73478, 272.64549, 148 | -0.01132, -0.01071, -0.04607, -0.00390, 149 | 0.02903, -0.02070, 150 | 0.01326, -0.00901, 151 | 35.38435, 7.45358, 31.08987, -70.52685, 152 | -92.13879, -51.58876, -51.80016, 48.98102, 153 | -0.00124, -0.01159, 154 | 0.47335, 13.71886, 23.71637, 5.55804, 155 | 10.06850, -25.65292, -11.85300, -10.20802, 156 | -4.72861, 1.27151, -0.47322, 7.46754, 157 | 6.99528, 1.79089, 2.05336, -2.90866, 158 | -1.97528, 0.72236, -0.25084, 1.90269, 159 | 0.72127, 0.41354, 160 | -0.30286, -0.53125, -0.50883, -0.01200, 161 | -0.08301, 0.18083, 162 | -0.04286, -0.10963, -0.04544, -0.01645, 163 | -0.00013, -0.00986 164 | ], 165 | lat_tbl: [ 166 | 68.33369, 422.77623, -2057.26405, -2522.29068, 167 | -0.00030, -0.00009, 168 | 0.02400, -0.06471, 0.02074, -0.00904, 169 | 0.00044, 0.00261, 170 | -0.00174, -0.00088, -0.00027, 0.00003, 171 | 0.00005, -0.00004, 172 | -0.00036, 0.00200, 173 | 0.01432, 0.01199, 174 | 0.00006, -0.00004, 175 | 0.00236, 0.00803, 0.01235, 0.00406, 176 | -0.03253, 0.00179, 177 | -0.00243, 0.00132, -0.00352, 0.00011, 178 | -0.00146, -0.01154, 179 | 0.00824, -0.01195, -0.01829, -0.00465, 180 | 0.12540, 0.09997, 181 | 0.00400, 0.00288, -0.02848, 0.01094, 182 | -0.02273, -0.07051, 183 | 0.01305, 0.01078, 184 | -0.00119, 0.00136, -0.00107, -0.00066, 185 | 0.00097, -0.00315, 186 | 0.00120, 0.00430, -0.00710, -0.00157, 187 | 0.06052, -0.04777, 188 | 0.00192, -0.00229, -0.02077, 0.00647, 189 | 0.06907, 0.07644, 190 | -0.00717, 0.00451, 191 | 0.00052, -0.00262, 0.00345, 0.00039, 192 | -0.00674, 0.00346, 193 | -0.02880, 0.00807, 194 | 0.00054, 0.00206, -0.01745, 0.00517, 195 | -0.00044, 0.00049, 196 | 0.01749, 0.01230, 197 | 0.01703, 0.01563, 198 | 0.00934, 0.02372, 199 | 0.01610, -0.01136, 200 | 0.00186, -0.00503, 201 | 0.00082, -0.00673, 202 | 0.00170, -0.00539, 203 | 0.00042, 0.00037, 204 | 0.00415, -0.00430, 205 | 0.00258, -0.00914, -0.01761, -0.00251, 206 | 0.15909, 0.13276, 207 | 0.02436, -0.00791, 0.00491, 0.03890, 208 | -0.02982, 0.05645, 209 | -0.00003, 0.00427, 210 | -0.00363, 0.00221, 211 | 0.00077, 0.00130, 212 | 0.00131, -0.00071, 0.00796, 0.00453, 213 | 0.01186, 0.01631, 214 | 0.12949, -0.02546, 0.03613, 0.32854, 215 | -0.43001, 0.01417, 216 | 0.00034, 0.00095, 217 | -0.03268, 0.04034, 0.11407, 0.15049, 218 | -0.00079, -0.00052, 219 | -0.04009, 0.00988, 220 | -0.00259, -0.00085, 0.00221, -0.00133, 221 | 0.00003, -0.01733, 222 | 0.01055, 0.01976, 223 | 0.00222, 0.00085, 224 | 0.00089, 0.00087, 225 | 0.00014, 0.00001, 226 | 0.00145, 0.00802, 227 | 0.00122, 0.00068, 228 | 947.79367, -1654.39690, 542.00864, -1281.09901, 229 | 90.02068, -318.36115, -87.67090, 92.91960, 230 | 376.98232, -419.10705, 5094.60412, 2476.97098, 231 | -18160.57888, 16010.48165, 232 | 0.00621, -0.00128, 233 | 0.00186, -0.00153, 234 | -0.00790, 0.00011, 235 | -0.00032, 0.00165, 236 | -0.00277, 0.00539, 237 | 0.00552, 0.00682, 0.01086, -0.00978, 238 | -0.02292, -0.01300, 0.02940, -0.04427, 239 | -0.02051, 0.04860, 240 | -0.05020, 0.29089, -0.50763, -0.04900, 241 | 0.11177, -0.41357, 242 | -0.00222, 0.00504, 243 | -0.00006, -0.00459, 244 | -0.00175, -0.02691, 245 | 0.05921, 0.18938, 246 | -0.00181, -0.00154, 247 | 0.00322, 0.00586, 248 | -0.01098, -0.00520, 249 | -0.00861, -0.01342, 250 | -0.02694, -0.00706, 251 | -0.00103, 0.00012, 252 | -0.00284, 0.00797, 253 | 0.00743, 0.02523, 254 | 0.00872, 0.00096, 255 | 0.03155, -0.01644, 256 | 0.00414, -0.00583, 257 | 0.00029, 0.00066, 258 | 0.00935, -0.00619, 259 | -0.02498, -0.01600, -0.03545, 0.07623, 260 | 0.01649, 0.06498, 261 | 0.00148, 0.00209, 262 | 0.00621, 0.02014, 263 | 0.17407, -0.05022, -0.03485, -0.17012, 264 | 0.06164, 0.20059, 265 | -0.00804, -0.01475, 266 | 0.00296, -0.00068, 267 | 0.01880, -0.03797, 268 | 0.00608, 0.02270, 269 | 5.89651, -6.62562, -37.41057, -10.51542, 270 | -47.22373, 95.76862, 494.45951, -5.37252, 271 | -3991.04809, -2886.97750, 272 | 0.01232, 0.00487, 273 | 0.03163, 0.00561, 274 | -0.01847, -0.00207, 275 | -0.10138, 0.01430, -0.04269, -0.22338, 276 | 0.24955, -0.02066, 277 | 0.01119, -0.00186, 278 | 0.03416, 0.01805, -0.12498, 0.10385, 279 | -0.00210, -0.01011, 280 | 0.00346, -0.00682, 281 | -0.00683, -0.02227, 282 | -0.01649, 0.01259, 283 | 0.01392, 0.01174, 284 | 0.00440, 0.00351, 285 | -0.02871, -0.00375, 286 | -0.03170, 0.02246, 287 | -0.00833, 0.00596, 288 | 0.04081, 0.06666, 0.05400, -0.02387, 289 | -0.07852, 0.05781, 290 | 0.01881, 0.00324, 291 | -0.00868, 0.00606, 292 | -6.52157, -19.74446, -72.46009, 43.12366, 293 | 321.78233, 215.45201, 452.61804, -1025.05619, 294 | 0.00119, 0.01169, 295 | 0.02239, 0.09003, 296 | -0.05329, -0.03974, 297 | 0.00688, -0.00421, 298 | -0.00676, -0.00515, 299 | -0.01171, -0.00952, 300 | 0.01337, 0.01270, 301 | -0.02791, -0.02184, 302 | 0.00058, 0.00679, 303 | 8.42102, -11.87757, -49.07247, -25.34584, 304 | -43.54829, 161.26509, 261.70993, 56.25777, 305 | 0.00568, 0.00871, -0.02656, 0.01582, 306 | 0.00875, -0.02114, 307 | 0.00464, -0.01075, 308 | 9.08966, 1.37810, 3.44548, -27.44651, 309 | -59.62749, -0.73611, -0.77613, 65.72607, 310 | -0.00664, -0.00723, 311 | 1.04214, 4.78920, 11.67397, -1.84524, 312 | -4.16685, -19.14211, -16.14483, 3.02496, 313 | -1.98140, 1.16261, 1.81526, 4.21224, 314 | 5.59020, -2.55741, -1.54151, -3.85817, 315 | -1.08723, 1.23372, 1.12378, 1.51554, 316 | 0.88937, -0.57631, 317 | -0.50549, -0.25617, -0.37618, 0.42163, 318 | 0.18902, 0.19575, 319 | -0.15402, -0.04062, -0.04017, 0.05717, 320 | -0.01665, -0.00199 321 | ], 322 | rad_tbl: [ 323 | -8.30490, -11.68232, 86.54880, 4361.05018, 324 | 0.00002, -0.00001, 325 | -0.01102, 0.00410, 0.00007, -0.00276, 326 | 0.00117, 0.00082, 327 | 0.00049, 0.00007, 0.00003, -0.00001, 328 | 0.00012, 0.00005, 329 | -0.00186, -0.00534, 330 | -0.03301, 0.01808, 331 | 0.00008, 0.00005, 332 | -0.00394, 0.00202, 0.02362, -0.00359, 333 | 0.00638, -0.06767, 334 | 0.00422, -0.00493, 0.00660, 0.00513, 335 | -0.00417, 0.00708, 336 | 0.05849, -0.00213, -0.07647, -0.16162, 337 | -0.30551, 0.13856, 338 | -0.02789, 0.01811, -0.04155, -0.06229, 339 | 0.05729, -0.03694, 340 | -0.03087, 0.01610, 341 | -0.00297, -0.00167, 0.00041, -0.00157, 342 | -0.00115, 0.00058, 343 | 0.00796, 0.00436, -0.01393, 0.02921, 344 | -0.05902, -0.02363, 345 | 0.00459, -0.01512, 0.10038, 0.02964, 346 | -0.08369, 0.34570, 347 | -0.00749, -0.02653, 348 | 0.01361, -0.00326, 0.00406, 0.00952, 349 | -0.00594, -0.00829, 350 | -0.02763, -0.09933, 351 | -0.04143, 0.05152, -0.08436, -0.05294, 352 | -0.00329, -0.00016, 353 | -0.04340, 0.02566, 354 | -0.03027, 0.10904, 355 | 0.03665, -0.03070, 356 | 0.23525, 0.00182, 357 | 0.03092, -0.02212, 358 | 0.01255, 0.00777, 359 | -0.01025, 0.00042, 360 | -0.00065, 0.00440, 361 | 0.08688, 0.00136, 362 | 0.05700, -0.03616, -0.11272, -0.20838, 363 | -0.37048, 0.18314, 364 | 0.00717, -0.02911, 0.15848, 0.05266, 365 | -0.13451, 0.51639, 366 | 0.00688, 0.02029, 367 | 0.00596, 0.00423, 368 | -0.00253, 0.01196, 369 | 0.05264, -0.03301, 0.10669, 0.07558, 370 | -0.02461, 0.16282, 371 | -0.18481, -0.57118, 0.85303, -0.44876, 372 | 0.37090, 0.65915, 373 | -0.00458, 0.00660, 374 | 0.41186, 0.09829, -0.31999, 1.51149, 375 | -0.00052, -0.00809, 376 | 0.01384, -0.07114, 377 | -0.00435, -0.03237, 0.02162, 0.00294, 378 | 0.29742, -0.15430, 379 | -0.04508, 0.17436, 380 | 0.01577, 0.00485, 381 | -0.00258, 0.00946, 382 | 0.00061, 0.00119, 383 | 0.01095, -0.00788, 384 | 0.00530, -0.01478, 385 | 2885.06380, 2152.76256, 2361.91098, 1442.28586, 386 | 602.45147, 251.18991, -121.68155, 71.20167, 387 | 404.94753, 1607.37580, 11211.04090, -2905.37340, 388 | -9066.27933, -40747.62807, 389 | -0.00189, 0.00957, 390 | 0.00332, 0.00907, 391 | 0.00574, -0.01255, 392 | -0.01134, 0.00291, 393 | -0.00666, -0.00615, 394 | -0.04947, 0.06182, 0.03965, 0.08091, 395 | 0.06846, -0.03612, 0.13966, 0.12543, 396 | -0.05494, -0.05043, 397 | -0.24454, -0.20507, 0.56201, -0.75997, 398 | 1.15728, 0.76203, 399 | -0.00559, -0.00536, 400 | 0.01872, 0.00104, 401 | 0.03044, 0.02504, 402 | -1.07241, -0.00288, 403 | 0.00950, -0.00760, 404 | -0.03211, 0.02261, 405 | 0.02678, -0.06868, 406 | 0.03008, -0.02062, 407 | 0.04997, -0.15164, 408 | -0.00176, -0.00580, 409 | -0.00730, -0.00676, 410 | -0.13906, -0.00089, 411 | -0.00362, 0.00817, 412 | 0.02021, 0.07719, 413 | 0.02788, 0.02061, 414 | -0.00274, 0.00016, 415 | 0.00566, 0.02293, 416 | 0.04691, -0.05005, -0.05095, -0.06225, 417 | -0.19770, -0.00456, 418 | -0.00848, 0.00595, 419 | -0.04506, -0.00172, 420 | -0.01960, 0.22971, 0.14459, 0.04362, 421 | -0.40199, 0.00386, 422 | 0.01442, -0.00088, 423 | -0.00020, 0.00544, 424 | 0.04768, 0.05222, 425 | -0.04069, -0.00003, 426 | 15.71084, -12.28846, -66.23443, -109.83758, 427 | -586.31996, 311.09606, 1070.75040, 2094.34080, 428 | 3839.04103, -1797.34193, 429 | -0.01216, 0.01244, 430 | -0.01666, 0.02627, 431 | 0.00687, -0.01291, 432 | 0.00939, -0.01905, 0.09401, 0.05027, 433 | -0.09398, 0.23942, 434 | -0.00379, 0.00834, 435 | 0.05632, -0.01907, -0.04654, -0.21243, 436 | 0.00255, 0.00179, 437 | 0.00540, 0.00497, 438 | 0.01427, 0.00243, 439 | -0.00697, -0.02792, 440 | -0.01524, 0.00810, 441 | -0.00461, 0.00238, 442 | 0.00899, -0.01515, 443 | -0.01011, -0.04390, 444 | -0.00447, -0.00992, 445 | -0.06110, 0.00975, -0.00261, 0.03415, 446 | -0.02336, -0.08776, 447 | -0.00883, 0.01346, 448 | -0.00229, -0.00895, 449 | 42.18049, -48.21316, -148.61588, -171.57236, 450 | -414.27195, 343.09118, 394.59044, 511.79914, 451 | -0.00911, -0.00220, 452 | -0.06315, -0.00988, 453 | 0.04357, -0.02389, 454 | 0.00004, 0.00232, 455 | 0.00581, -0.00317, 456 | 0.00948, -0.00497, 457 | -0.00734, 0.00300, 458 | 0.01883, -0.01055, 459 | -0.00365, -0.00126, 460 | 24.18074, 12.28004, 43.18187, -58.69806, 461 | -102.40566, -79.48349, -74.81060, 89.71332, 462 | 0.00241, -0.00135, -0.00136, -0.01617, 463 | 0.00818, 0.00873, 464 | 0.00368, 0.00383, 465 | -2.25893, 10.18542, 20.73104, 9.07389, 466 | 13.73458, -29.10491, -20.62071, -10.63404, 467 | 0.00382, -0.00143, 468 | -3.77385, 0.12725, -1.30842, 6.75795, 469 | 7.94463, 1.79092, 1.24458, -4.73211, 470 | -0.36978, -1.25710, -2.06373, 0.06194, 471 | -0.00509, 2.08851, 1.07491, 0.04112, 472 | -0.28582, -0.51413, -0.53312, 0.11936, 473 | 0.04447, 0.23945, 474 | 0.12450, -0.11821, -0.06100, -0.12924, 475 | -0.05193, 0.02219, 476 | 0.01977, -0.02933, -0.00771, -0.01077, 477 | 0.00109, -0.00273 478 | ], 479 | arg_tbl: [ 480 | 0, 3, 481 | 3, 1, 1, -10, 3, 11, 4, 0, 482 | 2, 2, 5, -5, 6, 2, 483 | 3, 5, 1, -14, 2, 2, 3, 1, 484 | 3, 1, 1, -5, 2, 4, 3, 0, 485 | 1, 1, 6, 0, 486 | 1, 2, 6, 0, 487 | 3, 2, 1, -7, 2, 3, 3, 0, 488 | 1, 1, 5, 2, 489 | 2, 1, 1, -4, 3, 2, 490 | 1, 2, 5, 2, 491 | 2, 2, 1, -5, 2, 2, 492 | 1, 3, 5, 0, 493 | 2, 4, 1, -10, 2, 1, 494 | 2, 3, 1, -8, 2, 0, 495 | 2, 1, 1, -3, 2, 2, 496 | 2, 1, 1, -2, 2, 2, 497 | 1, 1, 3, 0, 498 | 2, 3, 1, -7, 2, 1, 499 | 2, 1, 1, -3, 3, 0, 500 | 1, 1, 2, 0, 501 | 2, 2, 1, -4, 2, 1, 502 | 2, 4, 1, -9, 2, 0, 503 | 1, 2, 3, 0, 504 | 2, 1, 1, -2, 3, 0, 505 | 2, 1, 1, -4, 2, 0, 506 | 2, 1, 1, -1, 2, 0, 507 | 2, 3, 1, -6, 2, 0, 508 | 1, 3, 3, 0, 509 | 2, 2, 1, -7, 2, 0, 510 | 2, 1, 1, -2, 4, 0, 511 | 2, 1, 1, -1, 3, 0, 512 | 1, 2, 2, 2, 513 | 2, 2, 1, -3, 2, 2, 514 | 2, 4, 1, -8, 2, 0, 515 | 2, 3, 1, -10, 2, 0, 516 | 2, 1, 1, -4, 5, 0, 517 | 2, 1, 1, -3, 5, 2, 518 | 2, 1, 1, -5, 2, 2, 519 | 2, 1, 1, -5, 6, 0, 520 | 2, 1, 1, -2, 5, 1, 521 | 3, 1, 1, -4, 5, 5, 6, 0, 522 | 1, 4, 3, 0, 523 | 2, 1, 1, -3, 6, 1, 524 | 2, 1, 1, -1, 5, 0, 525 | 2, 1, 1, -2, 6, 0, 526 | 2, 1, 1, -1, 6, 0, 527 | 2, 1, 1, -2, 7, 0, 528 | 2, 1, 1, -1, 7, 0, 529 | 3, 4, 1, -14, 2, 2, 3, 0, 530 | 3, 1, 1, 2, 5, -5, 6, 0, 531 | 1, 1, 1, 6, 532 | 3, 2, 1, -10, 3, 11, 4, 0, 533 | 3, 1, 1, -2, 5, 5, 6, 0, 534 | 3, 6, 1, -14, 2, 2, 3, 0, 535 | 2, 1, 1, 1, 6, 0, 536 | 2, 1, 1, 2, 6, 0, 537 | 2, 1, 1, 1, 5, 1, 538 | 2, 2, 1, -4, 3, 1, 539 | 2, 1, 1, 2, 5, 0, 540 | 2, 3, 1, -5, 2, 2, 541 | 2, 1, 1, 3, 5, 0, 542 | 2, 5, 1, -10, 2, 0, 543 | 1, 3, 2, 0, 544 | 2, 2, 1, -2, 2, 0, 545 | 2, 1, 1, 1, 3, 0, 546 | 2, 4, 1, -7, 2, 0, 547 | 2, 2, 1, -3, 3, 0, 548 | 2, 1, 1, 1, 2, 0, 549 | 2, 3, 1, -4, 2, 0, 550 | 2, 5, 1, -9, 2, 0, 551 | 2, 1, 1, 2, 3, 0, 552 | 2, 2, 1, -2, 3, 0, 553 | 1, 4, 2, 0, 554 | 2, 2, 1, -1, 2, 0, 555 | 2, 4, 1, -6, 2, 0, 556 | 2, 2, 1, -2, 4, 0, 557 | 2, 2, 1, -1, 3, 0, 558 | 2, 1, 1, 2, 2, 1, 559 | 2, 3, 1, -3, 2, 0, 560 | 2, 5, 1, -8, 2, 0, 561 | 2, 2, 1, -3, 5, 0, 562 | 1, 5, 2, 1, 563 | 2, 2, 1, -2, 5, 0, 564 | 2, 1, 1, 4, 3, 0, 565 | 2, 2, 1, -3, 6, 0, 566 | 2, 2, 1, -1, 5, 0, 567 | 2, 2, 1, -2, 6, 0, 568 | 1, 2, 1, 4, 569 | 2, 2, 1, 1, 5, 0, 570 | 2, 3, 1, -4, 3, 0, 571 | 2, 2, 1, 2, 5, 0, 572 | 2, 4, 1, -5, 2, 2, 573 | 2, 1, 1, 3, 2, 0, 574 | 2, 3, 1, -2, 2, 1, 575 | 2, 3, 1, -3, 3, 0, 576 | 2, 2, 1, 1, 2, 0, 577 | 2, 4, 1, -4, 2, 0, 578 | 2, 3, 1, -2, 3, 0, 579 | 2, 3, 1, -1, 2, 0, 580 | 2, 3, 1, -1, 3, 0, 581 | 2, 2, 1, 2, 2, 0, 582 | 2, 4, 1, -3, 2, 0, 583 | 2, 3, 1, -3, 5, 0, 584 | 2, 1, 1, 5, 2, 1, 585 | 2, 3, 1, -2, 5, 0, 586 | 2, 3, 1, -1, 5, 0, 587 | 2, 3, 1, -2, 6, 0, 588 | 1, 3, 1, 3, 589 | 2, 4, 1, -4, 3, 0, 590 | 2, 5, 1, -5, 2, 0, 591 | 2, 4, 1, -2, 2, 0, 592 | 2, 5, 1, -4, 2, 0, 593 | 2, 4, 1, -2, 3, 0, 594 | 2, 5, 1, -3, 2, 0, 595 | 2, 2, 1, 5, 2, 0, 596 | 2, 4, 1, -2, 5, 0, 597 | 2, 4, 1, -1, 5, 0, 598 | 1, 4, 1, 3, 599 | 2, 6, 1, -5, 2, 1, 600 | 2, 5, 1, -2, 2, 0, 601 | 2, 5, 1, -2, 5, 0, 602 | 1, 5, 1, 3, 603 | 2, 7, 1, -5, 2, 0, 604 | 1, 6, 1, 3, 605 | 1, 7, 1, 3, 606 | 1, 8, 1, 2, 607 | 1, 9, 1, 2, 608 | 1, 10, 1, 1, 609 | 1, 11, 1, 0, 610 | -1 611 | ] 612 | } 613 | 614 | module.exports = mercury 615 | -------------------------------------------------------------------------------- /src/astronomy/moshier/gplan.js: -------------------------------------------------------------------------------- 1 | var constant = require('./constant') 2 | var epsilon = require('./epsilon') 3 | var plan404 = require('./plan404') 4 | var util = require('./util') 5 | 6 | var gplan = { 7 | /** From Simon et al (1994) */ 8 | freqs: [ 9 | /* Arc sec per 10000 Julian years. */ 10 | 53810162868.8982, 11 | 21066413643.3548, 12 | 12959774228.3429, 13 | 6890507749.3988, 14 | 1092566037.7991, 15 | 439960985.5372, 16 | 154248119.3933, 17 | 78655032.0744, 18 | 52272245.1795 19 | ], 20 | 21 | phases: [ 22 | /* Arc sec. */ 23 | 252.25090552 * 3600, 24 | 181.97980085 * 3600, 25 | 100.46645683 * 3600, 26 | 355.43299958 * 3600, 27 | 34.35151874 * 3600, 28 | 50.07744430 * 3600, 29 | 314.05500511 * 3600, 30 | 304.34866548 * 3600, 31 | 860492.1546 32 | ], 33 | 34 | ss: [], 35 | cc: [], 36 | 37 | Args: [], 38 | LP_equinox: 0, 39 | NF_arcsec: 0, 40 | Ea_arcsec: 0, 41 | pA_precession: 0 42 | 43 | } 44 | 45 | /** Routines to chew through tables of perturbations. */ 46 | gplan.calc = function (date, body_ptable) { 47 | var j, ip, nt // int 48 | var su, cu // double 49 | 50 | var T = (date.julian - constant.j2000) / body_ptable.timescale 51 | var n = body_ptable.maxargs 52 | /* Calculate sin( i*MM ), etc. for needed multiple angles. */ 53 | for (var i = 0; i < n; i++) { 54 | j = body_ptable.max_harmonic[i] 55 | if (j > 0) { 56 | sr = (util.mods3600(this.freqs[i] * T) + this.phases[i]) * constant.STR 57 | this.sscc(i, sr, j) 58 | } 59 | } 60 | 61 | /* Point to start of table of arguments. */ 62 | var p = body_ptable.arg_tbl 63 | 64 | /* Point to tabulated cosine and sine amplitudes. */ 65 | var pl = body_ptable.lon_tbl 66 | var pb = body_ptable.lat_tbl 67 | var pr = body_ptable.rad_tbl 68 | 69 | var sl = 0.0 70 | var sb = 0.0 71 | var sr = 0.0 72 | 73 | var p_i = 0 74 | var pl_i = 0 75 | var pb_i = 0 76 | var pr_i = 0 77 | 78 | for (; ;) { 79 | /* argument of sine and cosine */ 80 | /* Number of periodic arguments. */ 81 | var np = p[p_i++] // np = *p++ 82 | if (np < 0) { 83 | break 84 | } 85 | if (np == 0) { /* It is a polynomial term. */ 86 | nt = p[p_i++] // nt = *p++ 87 | /* Longitude polynomial. */ 88 | cu = pl[pl_i++] // cu = *pl++; 89 | for (ip = 0; ip < nt; ip++) { 90 | cu = cu * T + pl[pl_i++] // *pl++; 91 | } 92 | sl += util.mods3600(cu) 93 | /* Latitude polynomial. */ 94 | cu = pb[pb_i++] // *pb++; 95 | for (ip = 0; ip < nt; ip++) { 96 | cu = cu * T + pb[pb_i++] // *pb++; 97 | } 98 | sb += cu 99 | /* Radius polynomial. */ 100 | cu = pr[pr_i++] // *pr++; 101 | for (ip = 0; ip < nt; ip++) { 102 | cu = cu * T + pr[pr_i++] // *pr++; 103 | } 104 | sr += cu 105 | continue 106 | } 107 | var k1 = false 108 | var cv = 0.0 109 | var sv = 0.0 110 | for (ip = 0; ip < np; ip++) { 111 | /* What harmonic. */ 112 | j = p[p_i++] // *p++; 113 | /* Which planet. */ 114 | var m = p[p_i++] - 1 // *p++ - 1 115 | if (j) { 116 | var k = j < 0 ? -j : j 117 | k -= 1 118 | su = this.ss[m][k] 119 | /* sin(k*angle) */ 120 | if (j < 0) { 121 | su = -su 122 | } 123 | cu = this.cc[m][k] 124 | if (!k1) { /* set first angle */ 125 | sv = su 126 | cv = cu 127 | k1 = true 128 | } 129 | else { /* combine angles */ 130 | var tmp = su * cv + cu * sv 131 | cv = cu * cv - su * sv 132 | sv = tmp 133 | } 134 | } 135 | } 136 | /* Highest power of T. */ 137 | nt = p[p_i++] // *p++; 138 | /* Longitude */ 139 | cu = pl[pl_i++] // *pl++; 140 | su = pl[pl_i++] // *pl++; 141 | for (ip = 0; ip < nt; ip++) { 142 | cu = cu * T + pl[pl_i++] // *pl++; 143 | su = su * T + pl[pl_i++] // *pl++; 144 | } 145 | sl += cu * cv + su * sv 146 | /* Latitiude */ 147 | cu = pb[pb_i++] // *pb++; 148 | su = pb[pb_i++] // *pb++; 149 | for (ip = 0; ip < nt; ip++) { 150 | cu = cu * T + pb[pb_i++] // *pb++; 151 | su = su * T + pb[pb_i++] // *pb++; 152 | } 153 | sb += cu * cv + su * sv 154 | /* Radius */ 155 | cu = pr[pr_i++] // *pr++; 156 | su = pr[pr_i++] // *pr++; 157 | for (ip = 0; ip < nt; ip++) { 158 | cu = cu * T + pr[pr_i++] // *pr++; 159 | su = su * T + pr[pr_i++] // *pr++; 160 | } 161 | sr += cu * cv + su * sv 162 | } 163 | 164 | return { 165 | longitude: constant.STR * sl, 166 | latitude: constant.STR * sb, 167 | distance: constant.STR * body_ptable.distance * sr + body_ptable.distance 168 | } 169 | } 170 | 171 | /** 172 | * Prepare lookup table of sin and cos ( i*Lj ) 173 | * for required multiple angles 174 | */ 175 | gplan.sscc = function (k, arg, n) { 176 | var su = Math.sin(arg) 177 | var cu = Math.cos(arg) 178 | this.ss[k] = [] 179 | this.cc[k] = [] 180 | this.ss[k][0] = su 181 | /* sin(L) */ 182 | this.cc[k][0] = cu 183 | /* cos(L) */ 184 | var sv = 2 * su * cu 185 | var cv = cu * cu - su * su 186 | this.ss[k][1] = sv 187 | /* sin(2L) */ 188 | this.cc[k][1] = cv 189 | for (var i = 2; i < n; i++) { 190 | var s = su * cv + cu * sv 191 | cv = cu * cv - su * sv 192 | sv = s 193 | this.ss[k][i] = sv 194 | /* sin( i+1 L ) */ 195 | this.cc[k][i] = cv 196 | } 197 | } 198 | 199 | /** Compute mean elements at Julian date J. */ 200 | gplan.meanElements = function (date) { 201 | /* Time variables. T is in Julian centuries. */ 202 | var T = (date.julian - 2451545.0) / 36525.0 203 | var T2 = T * T 204 | 205 | /* Mean longitudes of planets (Simon et al, 1994) 206 | .047" subtracted from constant term for offset to DE403 origin. */ 207 | 208 | /* Mercury */ 209 | var x = util.mods3600(538101628.6889819 * T + 908103.213) 210 | x += (6.39e-6 * T 211 | - 0.0192789) * T2 212 | this.Args[0] = constant.STR * x 213 | 214 | /* Venus */ 215 | x = util.mods3600(210664136.4335482 * T + 655127.236) 216 | x += (-6.27e-6 * T 217 | + 0.0059381) * T2 218 | this.Args[1] = constant.STR * x 219 | 220 | /* Earth */ 221 | x = util.mods3600(129597742.283429 * T + 361679.198) 222 | x += (-5.23e-6 * T 223 | - 2.04411e-2) * T2 224 | this.Ea_arcsec = x 225 | this.Args[2] = constant.STR * x 226 | 227 | /* Mars */ 228 | x = util.mods3600(68905077.493988 * T + 1279558.751) 229 | x += (-1.043e-5 * T 230 | + 0.0094264) * T2 231 | this.Args[3] = constant.STR * x 232 | 233 | /* Jupiter */ 234 | x = util.mods3600(10925660.377991 * T + 123665.420) 235 | x += ((((-3.4e-10 * T 236 | + 5.91e-8) * T 237 | + 4.667e-6) * T 238 | + 5.706e-5) * T 239 | - 3.060378e-1) * T2 240 | this.Args[4] = constant.STR * x 241 | 242 | /* Saturn */ 243 | x = util.mods3600(4399609.855372 * T + 180278.752) 244 | x += ((((8.3e-10 * T 245 | - 1.452e-7) * T 246 | - 1.1484e-5) * T 247 | - 1.6618e-4) * T 248 | + 7.561614E-1) * T2 249 | this.Args[5] = constant.STR * x 250 | 251 | /* Uranus */ 252 | x = util.mods3600(1542481.193933 * T + 1130597.971) 253 | + (0.00002156 * T - 0.0175083) * T2 254 | this.Args[6] = constant.STR * x 255 | 256 | /* Neptune */ 257 | x = util.mods3600(786550.320744 * T + 1095655.149) 258 | + (-0.00000895 * T + 0.0021103) * T2 259 | this.Args[7] = constant.STR * x 260 | 261 | /* Copied from cmoon.c, DE404 version. */ 262 | /* Mean elongation of moon = D */ 263 | x = util.mods3600(1.6029616009939659e+09 * T + 1.0722612202445078e+06) 264 | x += (((((-3.207663637426e-013 * T 265 | + 2.555243317839e-011) * T 266 | + 2.560078201452e-009) * T 267 | - 3.702060118571e-005) * T 268 | + 6.9492746836058421e-03) * T /* D, t^3 */ 269 | - 6.7352202374457519e+00) * T2 270 | /* D, t^2 */ 271 | this.Args[9] = constant.STR * x 272 | 273 | /* Mean distance of moon from its ascending node = F */ 274 | x = util.mods3600(1.7395272628437717e+09 * T + 3.3577951412884740e+05) 275 | x += (((((4.474984866301e-013 * T 276 | + 4.189032191814e-011) * T 277 | - 2.790392351314e-009) * T 278 | - 2.165750777942e-006) * T 279 | - 7.5311878482337989e-04) * T /* F, t^3 */ 280 | - 1.3117809789650071e+01) * T2 281 | /* F, t^2 */ 282 | this.NF_arcsec = x 283 | this.Args[10] = constant.STR * x 284 | 285 | /* Mean anomaly of sun = l' (J. Laskar) */ 286 | x = util.mods3600(1.2959658102304320e+08 * T + 1.2871027407441526e+06) 287 | x += (((((((( 288 | 1.62e-20 * T 289 | - 1.0390e-17) * T 290 | - 3.83508e-15) * T 291 | + 4.237343e-13) * T 292 | + 8.8555011e-11) * T 293 | - 4.77258489e-8) * T 294 | - 1.1297037031e-5) * T 295 | + 8.7473717367324703e-05) * T 296 | - 5.5281306421783094e-01) * T2 297 | this.Args[11] = constant.STR * x 298 | 299 | /* Mean anomaly of moon = l */ 300 | x = util.mods3600(1.7179159228846793e+09 * T + 4.8586817465825332e+05) 301 | x += (((((-1.755312760154e-012 * T 302 | + 3.452144225877e-011) * T 303 | - 2.506365935364e-008) * T 304 | - 2.536291235258e-004) * T 305 | + 5.2099641302735818e-02) * T /* l, t^3 */ 306 | + 3.1501359071894147e+01) * T2 307 | /* l, t^2 */ 308 | this.Args[12] = constant.STR * x 309 | 310 | /* Mean longitude of moon, re mean ecliptic and equinox of date = L */ 311 | x = util.mods3600(1.7325643720442266e+09 * T + 7.8593980921052420e+05) 312 | x += (((((7.200592540556e-014 * T 313 | + 2.235210987108e-010) * T 314 | - 1.024222633731e-008) * T 315 | - 6.073960534117e-005) * T 316 | + 6.9017248528380490e-03) * T /* L, t^3 */ 317 | - 5.6550460027471399e+00) * T2 318 | /* L, t^2 */ 319 | this.LP_equinox = x 320 | this.Args[13] = constant.STR * x 321 | 322 | /* Precession of the equinox */ 323 | x = (((((((((-8.66e-20 * T - 4.759e-17) * T 324 | + 2.424e-15) * T 325 | + 1.3095e-12) * T 326 | + 1.7451e-10) * T 327 | - 1.8055e-8) * T 328 | - 0.0000235316) * T 329 | + 0.000076) * T 330 | + 1.105414) * T 331 | + 5028.791959) * T 332 | /* Moon's longitude re fixed J2000 equinox. */ 333 | /* 334 | Args[13] -= x; 335 | */ 336 | this.pA_precession = constant.STR * x 337 | 338 | /* Free librations. */ 339 | /* longitudinal libration 2.891725 years */ 340 | x = util.mods3600(4.48175409e7 * T + 8.060457e5) 341 | this.Args[14] = constant.STR * x 342 | /* libration P, 24.2 years */ 343 | x = util.mods3600(5.36486787e6 * T - 391702.8) 344 | this.Args[15] = constant.STR * x 345 | 346 | /* libration W, 74.7 years. */ 347 | x = util.mods3600(1.73573e6 * T) 348 | this.Args[17] = constant.STR * x 349 | } 350 | 351 | /** 352 | * Generic program to accumulate sum of trigonometric series 353 | * in three variables (e.g., longitude, latitude, radius) 354 | * of the same list of arguments. 355 | */ 356 | gplan.calc3 = function (date, body_ptable, body_number) { 357 | var j, ip, nt // int 358 | var su, cu // double 359 | 360 | this.meanElements(date) 361 | 362 | var T = (date.julian - constant.j2000) / body_ptable.timescale 363 | var n = body_ptable.maxargs 364 | /* Calculate sin( i*MM ), etc. for needed multiple angles. */ 365 | for (var i = 0; i < n; i++) { 366 | j = body_ptable.max_harmonic[i] 367 | if (j > 0) { 368 | this.sscc(i, this.Args[i], j) 369 | } 370 | } 371 | 372 | /* Point to start of table of arguments. */ 373 | var p = body_ptable.arg_tbl 374 | /* Point to tabulated cosine and sine amplitudes. */ 375 | var pl = body_ptable.lon_tbl 376 | var pb = body_ptable.lat_tbl 377 | var pr = body_ptable.rad_tbl 378 | 379 | var sl = 0.0 380 | var sb = 0.0 381 | var sr = 0.0 382 | 383 | var p_i = 0 384 | var pl_i = 0 385 | var pb_i = 0 386 | var pr_i = 0 387 | 388 | for (; ;) { 389 | /* argument of sine and cosine */ 390 | /* Number of periodic arguments. */ 391 | var np = p[p_i++] // *p++; 392 | if (np < 0) { 393 | break 394 | } 395 | if (np == 0) { /* It is a polynomial term. */ 396 | nt = p[p_i++] // *p++; 397 | /* "Longitude" polynomial (phi). */ 398 | cu = pl[pl_i++] // *pl++; 399 | for (ip = 0; ip < nt; ip++) { 400 | cu = cu * T + pl[pl_i++] // *pl++; 401 | } 402 | /* sl += mods3600 (cu); */ 403 | sl += cu 404 | /* "Latitude" polynomial (theta). */ 405 | cu = pb[pb_i++] // *pb++; 406 | for (ip = 0; ip < nt; ip++) { 407 | cu = cu * T + pb[pb_i++] // *pb++; 408 | } 409 | sb += cu 410 | /* Radius polynomial (psi). */ 411 | cu = pr[pr_i++] // *pr++; 412 | for (ip = 0; ip < nt; ip++) { 413 | cu = cu * T + pr[pr_i++] // *pr++; 414 | } 415 | sr += cu 416 | continue 417 | } 418 | var k1 = false 419 | var cv = 0.0 420 | var sv = 0.0 421 | for (ip = 0; ip < np; ip++) { 422 | /* What harmonic. */ 423 | j = p[p_i++] // *p++; 424 | /* Which planet. */ 425 | var m = p[p_i++] - 1 // *p++ - 1; 426 | if (j) { 427 | /* var k = abs (j); */ 428 | var k = j < 0 ? -j : j 429 | k -= 1 430 | su = this.ss[m][k] 431 | /* sin(k*angle) */ 432 | if (j < 0) { 433 | su = -su 434 | } 435 | cu = this.cc[m][k] 436 | if (!k1) { /* set first angle */ 437 | sv = su 438 | cv = cu 439 | k1 = true 440 | } 441 | else { /* combine angles */ 442 | var tmp = su * cv + cu * sv 443 | cv = cu * cv - su * sv 444 | sv = tmp 445 | } 446 | } 447 | } 448 | /* Highest power of T. */ 449 | nt = p[p_i++] // *p++; 450 | /* Longitude. */ 451 | cu = pl[pl_i++] // *pl++; 452 | su = pl[pl_i++] // *pl++; 453 | for (ip = 0; ip < nt; ip++) { 454 | cu = cu * T + pl[pl_i++] // *pl++; 455 | su = su * T + pl[pl_i++] // *pl++; 456 | } 457 | sl += cu * cv + su * sv 458 | /* Latitiude. */ 459 | cu = pb[pb_i++] // *pb++; 460 | su = pb[pb_i++] // *pb++; 461 | for (ip = 0; ip < nt; ip++) { 462 | cu = cu * T + pb[pb_i++] // *pb++; 463 | su = su * T + pb[pb_i++] // *pb++; 464 | } 465 | sb += cu * cv + su * sv 466 | /* Radius. */ 467 | cu = pr[pr_i++] // *pr++; 468 | su = pr[pr_i++] // *pr++; 469 | for (ip = 0; ip < nt; ip++) { 470 | cu = cu * T + pr[pr_i++] // *pr++; 471 | su = su * T + pr[pr_i++] // *pr++; 472 | } 473 | sr += cu * cv + su * sv 474 | } 475 | var t = body_ptable.trunclvl 476 | return { 477 | longitude: this.Args[body_number - 1] + constant.STR * t * sl, 478 | latitude: constant.STR * t * sb, 479 | distance: body_ptable.distance * (1 + constant.STR * t * sr) 480 | } 481 | } 482 | 483 | /** 484 | * Generic program to accumulate sum of trigonometric series 485 | * in two variables (e.g., longitude, radius) 486 | * of the same list of arguments. 487 | */ 488 | gplan.calc2 = function (date, body_ptable) { 489 | var j, ip, nt // int 490 | var su, cu // double 491 | 492 | this.meanElements(date) 493 | 494 | var T = (date.julian - constant.j2000) / body_ptable.timescale 495 | var n = body_ptable.maxargs 496 | /* Calculate sin( i*MM ), etc. for needed multiple angles. */ 497 | for (var i = 0; i < n; i++) { 498 | j = body_ptable.max_harmonic[i] 499 | if (j > 0) { 500 | this.sscc(i, this.Args[i], j) 501 | } 502 | } 503 | 504 | /* Point to start of table of arguments. */ 505 | var p = body_ptable.arg_tbl 506 | /* Point to tabulated cosine and sine amplitudes. */ 507 | var pl = body_ptable.lon_tbl 508 | var pr = body_ptable.rad_tbl 509 | 510 | var p_i = 0 511 | var pl_i = 0 512 | var pr_i = 0 513 | var sl = 0.0 514 | var sr = 0.0 515 | 516 | for (; ;) { 517 | /* argument of sine and cosine */ 518 | /* Number of periodic arguments. */ 519 | var np = p[p_i++] // *p++; 520 | if (np < 0) { 521 | break 522 | } 523 | if (np == 0) { /* It is a polynomial term. */ 524 | nt = p[p_i++] // *p++; 525 | /* Longitude polynomial. */ 526 | cu = pl[pl_i++] // *pl++; 527 | for (ip = 0; ip < nt; ip++) { 528 | cu = cu * T + pl[pl_i++] // *pl++; 529 | } 530 | /* sl += mods3600 (cu); */ 531 | sl += cu 532 | /* Radius polynomial. */ 533 | cu = pr[pr_i++] // *pr++; 534 | for (ip = 0; ip < nt; ip++) { 535 | cu = cu * T + pr[pr_i++] // *pr++; 536 | } 537 | sr += cu 538 | continue 539 | } 540 | var k1 = false 541 | var cv = 0.0 542 | var sv = 0.0 543 | for (ip = 0; ip < np; ip++) { 544 | /* What harmonic. */ 545 | j = p[p_i++] // *p++; 546 | /* Which planet. */ 547 | var m = p[p_i++] - 1 // *p++ - 1; 548 | if (j) { 549 | /* var k = abs (j); */ 550 | var k = j < 0 ? -j : j 551 | k -= 1 552 | su = this.ss[m][k] 553 | /* sin(k*angle) */ 554 | if (j < 0) { 555 | su = -su 556 | } 557 | cu = this.cc[m][k] 558 | if (!k1) { /* set first angle */ 559 | sv = su 560 | cv = cu 561 | k1 = true 562 | } 563 | else { /* combine angles */ 564 | var tmp = su * cv + cu * sv 565 | cv = cu * cv - su * sv 566 | sv = tmp 567 | } 568 | } 569 | } 570 | /* Highest power of T. */ 571 | nt = p[p_i++] // *p++; 572 | /* Longitude. */ 573 | cu = pl[pl_i++] // *pl++; 574 | su = pl[pl_i++] // *pl++; 575 | for (ip = 0; ip < nt; ip++) { 576 | cu = cu * T + pl[pl_i++] // *pl++; 577 | su = su * T + pl[pl_i++] // *pl++; 578 | } 579 | sl += cu * cv + su * sv 580 | /* Radius. */ 581 | cu = pr[pr_i++] // *pr++; 582 | su = pr[pr_i++] // *pr++; 583 | for (ip = 0; ip < nt; ip++) { 584 | cu = cu * T + pr[pr_i++] // *pr++; 585 | su = su * T + pr[pr_i++] // *pr++; 586 | } 587 | sr += cu * cv + su * sv 588 | } 589 | var t = body_ptable.trunclvl 590 | return { 591 | longitude: t * sl, 592 | latitude: null, 593 | distance: t * sr 594 | } 595 | } 596 | 597 | /** 598 | * Generic program to accumulate sum of trigonometric series 599 | * in one variable. 600 | */ 601 | gplan.calc1 = function (date, body_ptable) { 602 | var j, ip, nt // int 603 | var su, cu // double 604 | 605 | var T = (date.julian - constant.j2000) / body_ptable.timescale 606 | this.meanElements(date) 607 | /* Calculate sin( i*MM ), etc. for needed multiple angles. */ 608 | for (var i = 0; i < this.Args.length; i++) { 609 | j = body_ptable.max_harmonic[i] 610 | if (j > 0) { 611 | this.sscc(i, this.Args[i], j) 612 | } 613 | } 614 | 615 | /* Point to start of table of arguments. */ 616 | var p = body_ptable.arg_tbl 617 | /* Point to tabulated cosine and sine amplitudes. */ 618 | var pl = body_ptable.lon_tbl 619 | 620 | var sl = 0.0 621 | var p_i = 0 622 | var pl_i = 0 623 | 624 | for (; ;) { 625 | /* argument of sine and cosine */ 626 | /* Number of periodic arguments. */ 627 | var np = p[p_i++] // *p++; 628 | if (np < 0) { 629 | break 630 | } 631 | if (np == 0) { /* It is a polynomial term. */ 632 | nt = p[p_i++] // *p++; 633 | cu = pl[pl_i++] // *pl++; 634 | for (ip = 0; ip < nt; ip++) { 635 | cu = cu * T + pl[pl_i++] // *pl++; 636 | } 637 | /* sl += mods3600 (cu); */ 638 | sl += cu 639 | continue 640 | } 641 | var k1 = false 642 | var cv = 0.0 643 | var sv = 0.0 644 | for (ip = 0; ip < np; ip++) { 645 | /* What harmonic. */ 646 | j = p[p_i++] // *p++; 647 | /* Which planet. */ 648 | var m = p[p_i++] - 1 // *p++ - 1; 649 | if (j) { 650 | /* var k = abs (j); */ 651 | var k = j < 0 ? -j : j 652 | k -= 1 653 | su = this.ss[m][k] 654 | /* sin(k*angle) */ 655 | if (j < 0) { 656 | su = -su 657 | } 658 | cu = this.cc[m][k] 659 | if (!k1) { /* set first angle */ 660 | sv = su 661 | cv = cu 662 | k1 = true 663 | } 664 | else { /* combine angles */ 665 | var tmp = su * cv + cu * sv 666 | cv = cu * cv - su * sv 667 | sv = tmp 668 | } 669 | } 670 | } 671 | /* Highest power of T. */ 672 | nt = p[p_i++] // *p++; 673 | /* Cosine and sine coefficients. */ 674 | cu = pl[pl_i++] // *pl++; 675 | su = pl[pl_i++] // *pl++; 676 | for (ip = 0; ip < nt; ip++) { 677 | cu = cu * T + pl[pl_i++] // *pl++; 678 | su = su * T + pl[pl_i++] // *pl++; 679 | } 680 | sl += cu * cv + su * sv 681 | } 682 | return body_ptable.trunclvl * sl 683 | } 684 | 685 | /** Compute geocentric moon. */ 686 | gplan.moon = function (date, rect, pol) { 687 | var moonpol = this.calc2(date, plan404.moonlr) 688 | var x = moonpol.longitude + this.LP_equinox 689 | if (x < -6.48e5) { 690 | x += 1.296e6 691 | } 692 | if (x > 6.48e5) { 693 | x -= 1.296e6 694 | } 695 | pol = pol || {} 696 | pol.longitude = constant.STR * x 697 | pol.latitude = constant.STR * this.calc1(date, plan404.moonlat) 698 | pol.distance = (1 + constant.STR * moonpol.distance) * plan404.moonlr.distance 699 | /* Convert ecliptic polar to equatorial rectangular coordinates. */ 700 | epsilon.calc(date) 701 | var cosB = Math.cos(pol.latitude) 702 | var sinB = Math.sin(pol.latitude) 703 | var cosL = Math.cos(pol.longitude) 704 | var sinL = Math.sin(pol.longitude) 705 | rect.longitude = cosB * cosL * pol.distance 706 | rect.latitude = (epsilon.coseps * cosB * sinL - epsilon.sineps * sinB) * pol.distance 707 | rect.distance = (epsilon.sineps * cosB * sinL + epsilon.coseps * sinB) * pol.distance 708 | } 709 | 710 | module.exports = gplan 711 | --------------------------------------------------------------------------------