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