1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.bodies;
18
19 import java.io.Serializable;
20
21 import org.hipparchus.geometry.euclidean.threed.Vector3D;
22 import org.hipparchus.geometry.euclidean.twod.Vector2D;
23 import org.hipparchus.util.FastMath;
24 import org.hipparchus.util.MathArrays;
25 import org.orekit.frames.Frame;
26 import org.orekit.utils.TimeStampedPVCoordinates;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 public class Ellipse implements Serializable {
42
43
44 private static final long serialVersionUID = 20140925L;
45
46
47 private static final double ANGULAR_THRESHOLD = 1.0e-12;
48
49
50 private final Vector3D center;
51
52
53 private final Vector3D u;
54
55
56 private final Vector3D v;
57
58
59 private final double a;
60
61
62 private final double b;
63
64
65 private final Frame frame;
66
67
68 private final double a2;
69
70
71 private final double b2;
72
73
74 private final double e2;
75
76
77 private final double g;
78
79
80 private final double g2;
81
82
83 private final double evoluteFactorX;
84
85
86 private final double evoluteFactorY;
87
88
89
90
91
92
93
94
95
96 public Ellipse(final Vector3D center, final Vector3D u,
97 final Vector3D v, final double a, final double b,
98 final Frame frame) {
99 this.center = center;
100 this.u = u;
101 this.v = v;
102 this.a = a;
103 this.b = b;
104 this.frame = frame;
105 this.a2 = a * a;
106 this.g = b / a;
107 this.g2 = g * g;
108 this.e2 = 1 - g2;
109 this.b2 = b * b;
110 this.evoluteFactorX = (a2 - b2) / (a2 * a2);
111 this.evoluteFactorY = (b2 - a2) / (b2 * b2);
112 }
113
114
115
116
117 public Vector3D getCenter() {
118 return center;
119 }
120
121
122
123
124 public Vector3D getU() {
125 return u;
126 }
127
128
129
130
131 public Vector3D getV() {
132 return v;
133 }
134
135
136
137
138 public double getA() {
139 return a;
140 }
141
142
143
144
145 public double getB() {
146 return b;
147 }
148
149
150
151
152 public Frame getFrame() {
153 return frame;
154 }
155
156
157
158
159
160 public Vector3D pointAt(final double theta) {
161 return toSpace(new Vector2D(a * FastMath.cos(theta), b * FastMath.sin(theta)));
162 }
163
164
165
166
167
168
169 public Vector3D toSpace(final Vector2D p) {
170 return new Vector3D(1, center, p.getX(), u, p.getY(), v);
171 }
172
173
174
175
176
177
178 public Vector2D toPlane(final Vector3D p) {
179 final Vector3D delta = p.subtract(center);
180 return new Vector2D(Vector3D.dotProduct(delta, u), Vector3D.dotProduct(delta, v));
181 }
182
183
184
185
186
187 public Vector2D projectToEllipse(final Vector2D p) {
188
189 final double x = FastMath.abs(p.getX());
190 final double y = p.getY();
191
192 if (x <= ANGULAR_THRESHOLD * FastMath.abs(y)) {
193
194
195 final double osculatingRadius = a2 / b;
196 final double evoluteCuspZ = FastMath.copySign(a * e2 / g, -y);
197 final double deltaZ = y - evoluteCuspZ;
198 final double ratio = osculatingRadius / FastMath.hypot(deltaZ, x);
199 return new Vector2D(FastMath.copySign(ratio * x, p.getX()),
200 evoluteCuspZ + ratio * deltaZ);
201 }
202
203 if (FastMath.abs(y) <= ANGULAR_THRESHOLD * x) {
204
205
206 final double osculatingRadius = b2 / a;
207 final double evoluteCuspR = a * e2;
208 final double deltaR = x - evoluteCuspR;
209 if (deltaR >= 0) {
210
211
212 final double ratio = osculatingRadius / FastMath.hypot(y, deltaR);
213 return new Vector2D(FastMath.copySign(evoluteCuspR + ratio * deltaR, p.getX()),
214 ratio * y);
215 }
216
217
218
219 final double rEllipse = x / e2;
220 return new Vector2D(FastMath.copySign(rEllipse, p.getX()),
221 FastMath.copySign(g * FastMath.sqrt(a2 - rEllipse * rEllipse), y));
222
223 } else {
224 final double k = FastMath.hypot(x / a, y / b);
225 double projectedX = x / k;
226 double projectedY = y / k;
227 double deltaX = Double.POSITIVE_INFINITY;
228 double deltaY = Double.POSITIVE_INFINITY;
229 int count = 0;
230 final double threshold = ANGULAR_THRESHOLD * ANGULAR_THRESHOLD * a2;
231 while ((deltaX * deltaX + deltaY * deltaY) > threshold && count++ < 100) {
232 final double omegaX = evoluteFactorX * projectedX * projectedX * projectedX;
233 final double omegaY = evoluteFactorY * projectedY * projectedY * projectedY;
234 final double dx = x - omegaX;
235 final double dy = y - omegaY;
236 final double alpha = b2 * dx * dx + a2 * dy * dy;
237 final double beta = b2 * omegaX * dx + a2 * omegaY * dy;
238 final double gamma = b2 * omegaX * omegaX + a2 * omegaY * omegaY - a2 * b2;
239 final double deltaPrime = MathArrays.linearCombination(beta, beta, -alpha, gamma);
240 final double ratio = (beta <= 0) ?
241 (FastMath.sqrt(deltaPrime) - beta) / alpha :
242 -gamma / (FastMath.sqrt(deltaPrime) + beta);
243 final double previousX = projectedX;
244 final double previousY = projectedY;
245 projectedX = omegaX + ratio * dx;
246 projectedY = omegaY + ratio * dy;
247 deltaX = projectedX - previousX;
248 deltaY = projectedY - previousY;
249 }
250 return new Vector2D(FastMath.copySign(projectedX, p.getX()), projectedY);
251 }
252 }
253
254
255
256
257
258 public TimeStampedPVCoordinates projectToEllipse(final TimeStampedPVCoordinates pv) {
259
260
261 final Vector2D p2D = toPlane(pv.getPosition());
262 final Vector2D e2D = projectToEllipse(p2D);
263
264
265 final double fx = -a2 * e2D.getY();
266 final double fy = b2 * e2D.getX();
267 final double f2 = fx * fx + fy * fy;
268 final double f = FastMath.sqrt(f2);
269 final Vector2D tangent = new Vector2D(fx / f, fy / f);
270
271
272 final Vector2D normal = new Vector2D(-tangent.getY(), tangent.getX());
273
274
275 final double x2 = e2D.getX() * e2D.getX();
276 final double y2 = e2D.getY() * e2D.getY();
277 final double eX = evoluteFactorX * x2;
278 final double eY = evoluteFactorY * y2;
279 final double omegaX = eX * e2D.getX();
280 final double omegaY = eY * e2D.getY();
281
282
283 final double rho = FastMath.hypot(e2D.getX() - omegaX, e2D.getY() - omegaY);
284 final double d = FastMath.hypot(p2D.getX() - omegaX, p2D.getY() - omegaY);
285 final double projectionRatio = rho / d;
286
287
288 final Vector2D pDot2D = new Vector2D(Vector3D.dotProduct(pv.getVelocity(), u),
289 Vector3D.dotProduct(pv.getVelocity(), v));
290 final double pDotTangent = pDot2D.dotProduct(tangent);
291 final double pDotNormal = pDot2D.dotProduct(normal);
292 final double eDotTangent = projectionRatio * pDotTangent;
293 final Vector2D eDot2D = new Vector2D(eDotTangent, tangent);
294 final Vector2D tangentDot = new Vector2D(a2 * b2 * (e2D.getX() * eDot2D.getY() - e2D.getY() * eDot2D.getX()) / f2,
295 normal);
296
297
298 final double omegaXDot = 3 * eX * eDotTangent * tangent.getX();
299 final double omegaYDot = 3 * eY * eDotTangent * tangent.getY();
300
301
302 final double voz = omegaXDot * tangent.getY() - omegaYDot * tangent.getX();
303 final double vsz = -pDotNormal;
304 final double projectionRatioDot = ((rho - d) * voz - rho * vsz) / (d * d);
305
306
307 final Vector2D pDotDot2D = new Vector2D(Vector3D.dotProduct(pv.getAcceleration(), u),
308 Vector3D.dotProduct(pv.getAcceleration(), v));
309 final double pDotDotTangent = pDotDot2D.dotProduct(tangent);
310 final double pDotTangentDot = pDot2D.dotProduct(tangentDot);
311 final double eDotDotTangent = projectionRatio * (pDotDotTangent + pDotTangentDot) +
312 projectionRatioDot * pDotTangent;
313 final Vector2D eDotDot2D = new Vector2D(eDotDotTangent, tangent, eDotTangent, tangentDot);
314
315
316 final Vector3D e3D = toSpace(e2D);
317 final Vector3D eDot3D = new Vector3D(eDot2D.getX(), u, eDot2D.getY(), v);
318 final Vector3D eDotDot3D = new Vector3D(eDotDot2D.getX(), u, eDotDot2D.getY(), v);
319
320 return new TimeStampedPVCoordinates(pv.getDate(), e3D, eDot3D, eDotDot3D);
321
322 }
323
324
325
326
327
328
329 public Vector2D getCenterOfCurvature(final Vector2D point) {
330 final Vector2D projected = projectToEllipse(point);
331 return new Vector2D(evoluteFactorX * projected.getX() * projected.getX() * projected.getX(),
332 evoluteFactorY * projected.getY() * projected.getY() * projected.getY());
333 }
334
335 }