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 |
|
11 | import base from './base';
|
12 | import 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 | */
|
21 | export 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 | */
|
36 | export 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 | */
|
58 | export 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 | */
|
81 | export 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 | */
|
105 | export 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 | */
|
131 | export 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 | */
|
158 | export 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 | */
|
193 | export 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 |
|
202 | export 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 |