UNPKG

5.58 kBJavaScriptView Raw
1/**
2 * @copyright 2013 Sonia Keys
3 * @copyright 2016 commenthol
4 * @license MIT
5 * @module kepler
6 */
7/**
8 * Kepler: Chapter 30, Equation of Kepler.
9 */
10
11import base from './base';
12import iterate from './iterate';
13
14/**
15 * True returns true anomaly ν for given eccentric anomaly E.
16 *
17 * @param {number} e - eccentricity
18 * @param {number} E - eccentric anomaly in radians.
19 * @return true anomaly ν in radians.
20 */
21export function trueAnomaly(E, e) {
22 // (30.1) p. 195
23 return 2 * Math.atan(Math.sqrt((1 + e) / (1 - e)) * Math.tan(E * 0.5));
24}
25
26/**
27 * Radius returns radius distance r for given eccentric anomaly E.
28 *
29 * Result unit is the unit of semimajor axis a (typically AU.)
30 *
31 * @param {number} e - eccentricity
32 * @param {number} E - eccentric anomaly in radians
33 * @param {number} a - semimajor axis
34 * @return {number} radius distance in unit of `a`
35 */
36export function radius(E, e, a) {
37 // (E, e, a float64) float64
38 // (30.2) p. 195
39 return a * (1 - e * Math.cos(E));
40}
41
42/**
43 * Kepler1 solves Kepler's equation by iteration.
44 *
45 * The iterated formula is
46 *
47 * E1 = m + e * sin(E0)
48 *
49 * For some vaues of e and M it will fail to converge and the
50 * function will return an error.
51 *
52 * @throws Error
53 * @param {number} e - eccentricity
54 * @param {number} m - mean anomaly in radians
55 * @param {number} places - (int) desired number of decimal places in the result
56 * @return {number} eccentric anomaly `E` in radians.
57 */
58export function kepler1(e, m, places) {
59 var f = function f(E0) {
60 return m + e * Math.sin(E0); // (30.5) p. 195
61 };
62 return iterate.decimalPlaces(f, m, places, places * 5);
63}
64
65/**
66 * Kepler2 solves Kepler's equation by iteration.
67 *
68 * The iterated formula is
69 *
70 * E1 = E0 + (m + e * sin(E0) - E0) / (1 - e * cos(E0))
71 *
72 * The function converges over a wider range of inputs than does Kepler1
73 * but it also fails to converge for some values of e and M.
74 *
75 * @throws Error
76 * @param {number} e - eccentricity
77 * @param {number} m - mean anomaly in radians
78 * @param {number} places - (int) desired number of decimal places in the result
79 * @return {number} eccentric anomaly `E` in radians.
80 */
81export function kepler2(e, m, places) {
82 // (e, M float64, places int) (E float64, err error)
83 var f = function f(E0) {
84 var _base$sincos = base.sincos(E0),
85 se = _base$sincos[0],
86 ce = _base$sincos[1];
87
88 return E0 + (m + e * se - E0) / (1 - e * ce); // (30.7) p. 199
89 };
90 return iterate.decimalPlaces(f, m, places, places);
91}
92
93/**
94 * Kepler2a solves Kepler's equation by iteration.
95 *
96 * The iterated formula is the same as in Kepler2 but a limiting function
97 * avoids divergence.
98 *
99 * @throws Error
100 * @param {number} e - eccentricity
101 * @param {number} m - mean anomaly in radians
102 * @param {number} places - (int) desired number of decimal places in the result
103 * @return {number} eccentric anomaly `E` in radians.
104 */
105export function kepler2a(e, m, places) {
106 // (e, M float64, places int) (E float64, err error)
107 var f = function f(E0) {
108 var _base$sincos2 = base.sincos(E0),
109 se = _base$sincos2[0],
110 ce = _base$sincos2[1];
111 // method of Leingärtner, p. 205
112
113
114 return E0 + Math.asin(Math.sin((m + e * se - E0) / (1 - e * ce)));
115 };
116 return iterate.decimalPlaces(f, m, places, places * 5);
117}
118
119/**
120 * Kepler2b solves Kepler's equation by iteration.
121 *
122 * The iterated formula is the same as in Kepler2 but a (different) limiting
123 * function avoids divergence.
124 *
125 * @throws Error
126 * @param {number} e - eccentricity
127 * @param {number} m - mean anomaly in radians
128 * @param {number} places - (int) desired number of decimal places in the result
129 * @return {number} eccentric anomaly `E` in radians.
130 */
131export function kepler2b(e, m, places) {
132 // (e, M float64, places int) (E float64, err error)
133 var f = function f(E0) {
134 var _base$sincos3 = base.sincos(E0),
135 se = _base$sincos3[0],
136 ce = _base$sincos3[1];
137
138 var d = (m + e * se - E0) / (1 - e * ce);
139 // method of Steele, p. 205
140 if (d > 0.5) {
141 d = 0.5;
142 } else if (d < -0.5) {
143 d = -0.5;
144 }
145 return E0 + d;
146 };
147 return iterate.decimalPlaces(f, m, places, places);
148}
149
150/**
151 * Kepler3 solves Kepler's equation by binary search.
152 *
153 * @throws Error
154 * @param {number} e - eccentricity
155 * @param {number} m - mean anomaly in radians
156 * @return {number} eccentric anomaly `E` in radians.
157 */
158export function kepler3(e, m) {
159 // (e, m float64) (E float64)
160 // adapted from BASIC, p. 206
161 m = base.pmod(m, 2 * Math.PI);
162 var f = 1;
163 if (m > Math.PI) {
164 f = -1;
165 m = 2 * Math.PI - m;
166 }
167 var E0 = Math.PI * 0.5;
168 var d = Math.PI * 0.25;
169 for (var i = 0; i < 53; i++) {
170 var M1 = E0 - e * Math.sin(E0);
171 if (m - M1 < 0) {
172 E0 -= d;
173 } else {
174 E0 += d;
175 }
176 d *= 0.5;
177 }
178 if (f < 0) {
179 return -E0;
180 }
181 return E0;
182}
183
184/**
185 * Kepler4 returns an approximate solution to Kepler's equation.
186 *
187 * It is valid only for small values of e.
188 *
189 * @param {number} e - eccentricity
190 * @param {number} m - mean anomaly in radians
191 * @return {number} eccentric anomaly `E` in radians.
192 */
193export function kepler4(e, m) {
194 // (e, m float64) (E float64)
195 var _base$sincos4 = base.sincos(m),
196 sm = _base$sincos4[0],
197 cm = _base$sincos4[1];
198
199 return Math.atan2(sm, cm - e); // (30.8) p. 206
200}
201
202export default {
203 trueAnomaly: trueAnomaly,
204 true: trueAnomaly, // BACKWARDS-COMPATIBILITY
205 radius: radius,
206 kepler1: kepler1,
207 kepler2: kepler2,
208 kepler2a: kepler2a,
209 kepler2b: kepler2b,
210 kepler3: kepler3,
211 kepler4: kepler4
212};
\No newline at end of file