1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.models.earth;
18
19 import org.hipparchus.geometry.euclidean.threed.Line;
20 import org.hipparchus.geometry.euclidean.threed.Rotation;
21 import org.hipparchus.geometry.euclidean.threed.Vector3D;
22 import org.hipparchus.util.FastMath;
23 import org.junit.jupiter.api.Assertions;
24 import org.junit.jupiter.api.BeforeAll;
25 import org.junit.jupiter.api.BeforeEach;
26 import org.junit.jupiter.api.Test;
27 import org.orekit.Utils;
28 import org.orekit.bodies.GeodeticPoint;
29 import org.orekit.forces.gravity.potential.EGMFormatReader;
30 import org.orekit.forces.gravity.potential.GravityFieldFactory;
31 import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider;
32 import org.orekit.frames.Frame;
33 import org.orekit.frames.FramesFactory;
34 import org.orekit.frames.StaticTransform;
35 import org.orekit.frames.Transform;
36 import org.orekit.time.AbsoluteDate;
37
38 import java.util.Arrays;
39
40 import static org.hamcrest.CoreMatchers.is;
41 import static org.hamcrest.CoreMatchers.nullValue;
42 import static org.hamcrest.CoreMatchers.sameInstance;
43 import static org.hamcrest.MatcherAssert.assertThat;
44 import static org.orekit.OrekitMatchers.closeTo;
45 import static org.orekit.OrekitMatchers.geodeticPointCloseTo;
46 import static org.orekit.OrekitMatchers.vectorCloseTo;
47
48
49
50
51
52
53 public class GeoidTest {
54
55
56 private static final int maxOrder = 360;
57
58 private static final int maxDegree = 360;
59
60 private static ReferenceEllipsoid WGS84 = new ReferenceEllipsoid(
61 6378137.00, 1 / 298.257223563, FramesFactory.getGCRF(),
62 3.986004418e14, 7292115e-11);
63
64
65
66
67 private static NormalizedSphericalHarmonicsProvider potential;
68
69 private static AbsoluteDate date;
70
71
72
73
74
75
76 @BeforeAll
77 public static void setUpBefore() throws Exception {
78 Utils.setDataRoot("geoid:regular-data");
79 GravityFieldFactory.clearPotentialCoefficientsReaders();
80 GravityFieldFactory.addPotentialCoefficientsReader(
81 new EGMFormatReader("egm96", false));
82 potential = GravityFieldFactory.getNormalizedProvider(
83 maxDegree, maxOrder);
84 date = null;
85 }
86
87
88 private double[][] reference;
89
90
91 @BeforeEach
92 public void setUp() {
93 reference = new double[][]{
94 {0, 75, -100.3168},
95 {-30, 60, 14.9214},
96 {0, 130, 76.6053},
97 {60, -30, 63.7979},
98 {40, -75, -34.0402},
99 {28, 92, -30.4056},
100 {45, 250, -7.4825},
101
102 {38.6281550, 269.7791550, -31.628},
103 {-14.6212170, 305.0211140, -2.969},
104 {46.8743190, 102.4487290, -43.575},
105 {-23.6174460, 133.8747120, 15.871},
106 {38.6254730, 359.9995000, 50.066},
107 {-.4667440, .0023000, 17.329}};
108 }
109
110
111
112
113
114
115
116 private Geoid getComponent() {
117 return new Geoid(potential, WGS84);
118 }
119
120
121 @Test
122 public void testGeoid() {
123 Geoid geoid = getComponent();
124
125 Assertions.assertEquals(WGS84, geoid.getEllipsoid());
126
127 Assertions.assertEquals(WGS84.getBodyFrame(), geoid.getBodyFrame());
128 }
129
130
131 @Test
132 public void testGeoidNullPotential() {
133 Assertions.assertThrows(NullPointerException.class, () -> {
134 new Geoid(null, WGS84);
135 });
136 }
137
138
139 @Test
140 public void testGeoidNullEllipsoid() {
141 Assertions.assertThrows(NullPointerException.class, () -> {
142 new Geoid(potential, null);
143 });
144 }
145
146
147
148
149
150
151
152
153
154
155 @Test
156 public void testGetUndulation() {
157
158
159
160
161 final double maxError = 3;
162
163
164 Geoid geoid = getComponent();
165 for (double[] row : reference) {
166 double lat = row[0];
167 double lon = row[1];
168 double undulation = geoid.getUndulation(FastMath.toRadians(lat),
169 FastMath.toRadians(lon), date);
170 double expected = row[2];
171
172
173 Assertions.assertEquals(undulation, expected, maxError, String.format("lat: %5g, lon: %5g", lat, lon));
174 }
175 }
176
177
178
179
180
181 @Test
182 public void testGetIntersectionPoint() {
183
184 Geoid geoid = getComponent();
185 Frame frame = geoid.getBodyFrame();
186
187 for (double[] point : reference) {
188 GeodeticPoint gp = new GeodeticPoint(FastMath.toRadians(point[0]),
189 FastMath.toRadians(point[1]), 0);
190 Vector3D expected = geoid.transform(gp);
191
192 Vector3D slope = gp.getZenith().scalarMultiply(0.1)
193 .add(gp.getNorth().scalarMultiply(0.9));
194 Vector3D close = expected.add(slope.scalarMultiply(100e3));
195 Vector3D pointOnLine = expected.add(slope);
196 Line line = new Line(close, pointOnLine, 0);
197
198 Line otherDirection = new Line(pointOnLine, close, 0);
199
200
201 GeodeticPoint actual = geoid.getIntersectionPoint(line, close,
202 frame, date);
203
204 GeodeticPoint actualReversed = geoid.getIntersectionPoint(
205 otherDirection, close, frame, date);
206
207
208 String message = String.format("point: %s%n",
209 Arrays.toString(point));
210
211 assertThat(message, actualReversed, geodeticPointCloseTo(gp, 1.3e-6));
212 assertThat(message, actual, geodeticPointCloseTo(gp, 1.3e-6));
213 }
214 }
215
216
217
218
219
220 @Test
221 public void testGetIntersectionPointFrame() {
222
223 Geoid geoid = getComponent();
224 Frame frame = new Frame(
225 geoid.getBodyFrame(),
226 new Transform(
227 date,
228 new Transform(
229 date,
230 new Vector3D(-1, 2, -3),
231 new Vector3D(4, -5, 6)),
232 new Transform(
233 date,
234 new Rotation(-7, 8, -9, 10, true),
235 new Vector3D(-11, 12, -13))),
236 "test frame");
237 GeodeticPoint gp = new GeodeticPoint(FastMath.toRadians(46.8743190),
238 FastMath.toRadians(102.4487290), 0);
239 Vector3D expected = geoid.transform(gp);
240
241 Vector3D slope = gp.getZenith().scalarMultiply(0.1)
242 .add(gp.getNorth().scalarMultiply(0.9));
243 Vector3D close = expected.add(slope.scalarMultiply(100));
244 Line line = new Line(expected.add(slope), close, 0);
245 StaticTransform xform = geoid.getBodyFrame().getStaticTransformTo(frame, date);
246
247 close = xform.transformPosition(close);
248 line = xform.transformLine(line);
249
250
251 GeodeticPoint actual = geoid.getIntersectionPoint(line, close, frame,
252 date);
253
254
255 assertThat(actual, geodeticPointCloseTo(gp, 1e-6));
256 }
257
258
259
260
261
262 @Test
263 public void testGetIntersectionPointNoIntersection() {
264 Geoid geoid = getComponent();
265 Vector3D closeMiss = new Vector3D(geoid.getEllipsoid()
266 .getEquatorialRadius() + 18, 0, 0);
267 Line line = new Line(closeMiss, closeMiss.add(Vector3D.PLUS_J), 0);
268
269
270 final GeodeticPoint actual = geoid.getIntersectionPoint(line,
271 closeMiss, geoid.getBodyFrame(), date);
272
273
274 assertThat(actual, nullValue());
275 }
276
277
278
279
280
281 @Test
282 public void testTransformVector3DFrameAbsoluteDate()
283 {
284
285 Frame frame = FramesFactory.getGCRF();
286 AbsoluteDate date = AbsoluteDate.CCSDS_EPOCH;
287
288 Geoid geoid = getComponent();
289
290 Vector3D point = new Vector3D(WGS84.getEquatorialRadius(), 0, 0);
291 double undulation = geoid.getUndulation(0, 0, date);
292
293
294 GeodeticPoint ellipsoidal = geoid.getEllipsoid().transform(
295 point, frame, date);
296 GeodeticPoint geoidal = geoid.transform(point, frame, date);
297 assertThat(ellipsoidal.getAltitude() - geoidal.getAltitude(),
298 is(undulation));
299
300
301 point = new Vector3D(0.5, 0.4, 0.31).scalarMultiply(WGS84
302 .getEquatorialRadius());
303 Vector3D expected = geoid
304 .transform(geoid.transform(point, frame, date));
305
306 assertThat(point, vectorCloseTo(expected, 2));
307
308 }
309
310
311
312
313
314 @Test
315 public void testTransformGeodeticPoint() {
316
317 Geoid geoid = getComponent();
318
319 ReferenceEllipsoid ellipsoid = geoid.getEllipsoid();
320
321 GeodeticPoint orthometric = new GeodeticPoint(0, 75, 5);
322
323 double undulation = geoid.getUndulation(orthometric.getLatitude(),
324 orthometric.getLongitude(), date);
325
326 GeodeticPoint point = new GeodeticPoint(orthometric.getLatitude(),
327 orthometric.getLongitude(), orthometric.getAltitude()
328 + undulation);
329
330
331 Vector3D expected = ellipsoid.transform(point);
332 Vector3D actual = geoid.transform(orthometric);
333 assertThat(actual, is(expected));
334
335
336 expected = new Vector3D(WGS84.getEquatorialRadius()
337 + geoid.getUndulation(0, 0, date), 0, 0);
338 actual = geoid.transform(new GeodeticPoint(0, 0, 0));
339 assertThat(actual, vectorCloseTo(expected, 0));
340 }
341
342
343 @Test
344 public void testGetEllipsoid() {
345
346 Geoid geoid = new Geoid(potential, WGS84);
347
348
349 assertThat(geoid.getEllipsoid(), sameInstance(WGS84));
350 }
351
352
353
354
355 @Test
356 public void testProjectToGround() {
357
358 Vector3D p = new Vector3D(7e8, 1e3, 200);
359 Geoid geoid = new Geoid(potential, WGS84);
360
361
362 Vector3D actual = geoid.projectToGround(p, date, FramesFactory.getGCRF());
363
364
365 assertThat(
366 geoid.transform(actual, geoid.getBodyFrame(), date).getAltitude(),
367 closeTo(0.0, 1.1e-9));
368 }
369
370 }