1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.models.earth.tessellation;
18
19 import java.io.IOException;
20 import java.util.List;
21
22 import org.hipparchus.geometry.euclidean.threed.Vector3D;
23 import org.hipparchus.geometry.partitioning.Region.Location;
24 import org.hipparchus.geometry.partitioning.RegionFactory;
25 import org.hipparchus.geometry.spherical.twod.S2Point;
26 import org.hipparchus.geometry.spherical.twod.Sphere2D;
27 import org.hipparchus.geometry.spherical.twod.SphericalPolygonsSet;
28 import org.hipparchus.util.FastMath;
29 import org.junit.Assert;
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.orekit.Utils;
33 import org.orekit.bodies.GeodeticPoint;
34 import org.orekit.bodies.OneAxisEllipsoid;
35 import org.orekit.errors.OrekitException;
36 import org.orekit.errors.OrekitMessages;
37 import org.orekit.frames.Frame;
38 import org.orekit.frames.FramesFactory;
39 import org.orekit.orbits.CircularOrbit;
40 import org.orekit.orbits.Orbit;
41 import org.orekit.orbits.PositionAngle;
42 import org.orekit.time.AbsoluteDate;
43 import org.orekit.time.TimeScalesFactory;
44 import org.orekit.utils.Constants;
45 import org.orekit.utils.IERSConventions;
46
47 public class EllipsoidTessellatorTest {
48
49 @Test
50 public void testTilesAlongDescendingTrackWithoutTruncation() {
51 final EllipsoidTessellator tessellator =
52 new EllipsoidTessellator(ellipsoid, new AlongTrackAiming(ellipsoid, orbit, false), 16);
53 final List<List<Tile>> tiles = tessellator.tessellate(buildFrance(),
54 50000.0, 150000.0, 5000.0, 5000.0,
55 false, false);
56 Assert.assertEquals(2, tiles.size());
57 Assert.assertEquals(109, FastMath.max(tiles.get(0).size(), tiles.get(1).size()));
58 Assert.assertEquals(4, FastMath.min(tiles.get(0).size(), tiles.get(1).size()));
59
60 }
61
62 @Test
63 public void testTilesAlongDescendingTrackWithTruncation() {
64 final EllipsoidTessellator tessellator =
65 new EllipsoidTessellator(ellipsoid, new AlongTrackAiming(ellipsoid, orbit, false), 16);
66 final List<List<Tile>> tiles = tessellator.tessellate(buildFrance(),
67 50000.0, 150000.0, 5000.0, 5000.0,
68 true, true);
69 Assert.assertEquals(2, tiles.size());
70 Assert.assertEquals(108, FastMath.max(tiles.get(0).size(), tiles.get(1).size()));
71 Assert.assertEquals(4, FastMath.min(tiles.get(0).size(), tiles.get(1).size()));
72
73 }
74
75 @Test
76 public void testSampleAlongDescendingTrack() {
77 final EllipsoidTessellator tessellator =
78 new EllipsoidTessellator(ellipsoid, new AlongTrackAiming(ellipsoid, orbit, false), 4);
79 final List<List<GeodeticPoint>> samples = tessellator.sample(buildFrance(), 25000.0, 50000.0);
80 Assert.assertEquals(2, samples.size());
81 Assert.assertEquals(452, FastMath.max(samples.get(0).size(), samples.get(1).size()));
82 Assert.assertEquals(9, FastMath.min(samples.get(0).size(), samples.get(1).size()));
83 }
84
85 @Test
86 public void testTilesAlongAscendingTrack() {
87 final EllipsoidTessellator tessellator =
88 new EllipsoidTessellator(ellipsoid, new AlongTrackAiming(ellipsoid, orbit, true), 4);
89 final List<List<Tile>> tiles = tessellator.tessellate(buildFrance(),
90 50000.0, 150000.0, 5000.0, 5000.0,
91 false, false);
92 Assert.assertEquals(2, tiles.size());
93 Assert.assertEquals(112, FastMath.max(tiles.get(0).size(), tiles.get(1).size()));
94 Assert.assertEquals(6, FastMath.min(tiles.get(0).size(), tiles.get(1).size()));
95 }
96
97 @Test
98 public void testSampleAlongAscendingTrack() {
99 final EllipsoidTessellator tessellator =
100 new EllipsoidTessellator(ellipsoid, new AlongTrackAiming(ellipsoid, orbit, true), 4);
101 final List<List<GeodeticPoint>> samples = tessellator.sample(buildFrance(),
102 25000.0, 50000.0);
103 Assert.assertEquals(2, samples.size());
104 Assert.assertEquals(452, FastMath.max(samples.get(0).size(), samples.get(1).size()));
105 Assert.assertEquals(10, FastMath.min(samples.get(0).size(), samples.get(1).size()));
106 }
107
108 @Test
109 public void testTilesConstantAzimuth() {
110 final EllipsoidTessellator tessellator =
111 new EllipsoidTessellator(ellipsoid, new ConstantAzimuthAiming(ellipsoid, FastMath.toRadians(120)), 4);
112 final List<List<Tile>> tiles = tessellator.tessellate(buildFrance(),
113 50000.0, 150000.0, -5000.0, -5000.0,
114 false, false);
115 Assert.assertEquals(2, tiles.size());
116 Assert.assertEquals(86, FastMath.max(tiles.get(0).size(), tiles.get(1).size()));
117 Assert.assertEquals(4, FastMath.min(tiles.get(0).size(), tiles.get(1).size()));
118 checkTilesDontOverlap(tiles);
119 }
120
121 @Test
122 public void testSampleConstantAzimuth() {
123 final EllipsoidTessellator tessellator =
124 new EllipsoidTessellator(ellipsoid, new ConstantAzimuthAiming(ellipsoid, FastMath.toRadians(120)), 4);
125 final List<List<GeodeticPoint>> samples = tessellator.sample(buildFrance(), 25000.0, 50000.0);
126 Assert.assertEquals(2, samples.size());
127 Assert.assertEquals(455, FastMath.max(samples.get(0).size(), samples.get(1).size()));
128 Assert.assertEquals(9, FastMath.min(samples.get(0).size(), samples.get(1).size()));
129 }
130
131 @Test
132 public void testTilesIslandJoining() {
133 final EllipsoidTessellator tessellator =
134 new EllipsoidTessellator(ellipsoid, new ConstantAzimuthAiming(ellipsoid, FastMath.toRadians(120.0)), 4);
135 final List<List<Tile>> tiles = tessellator.tessellate(buildFrance(),
136 150000.0, 250000.0, -5000.0, -5000.0,
137 false, false);
138 Assert.assertEquals(1, tiles.size());
139 Assert.assertEquals(28, tiles.get(0).size());
140 checkTilesDontOverlap(tiles);
141 }
142
143 @Test
144 public void testTilesSmallZoneWithoutTruncation() throws IOException {
145
146 TileAiming aiming = new ConstantAzimuthAiming(ellipsoid, FastMath.toRadians(193.7));
147 EllipsoidTessellator tessellator =
148 new EllipsoidTessellator(ellipsoid, aiming, 16);
149
150 SphericalPolygonsSet small = buildSimpleZone(1.0e-10, new double[][] {
151 { 43.6543, 1.4268 }, { 43.6120, 1.4179 }, { 43.6016, 1.3994 }, { 43.5682, 1.4159 },
152 { 43.5707, 1.4358 }, { 43.5573, 1.4941 }, { 43.6041, 1.4866 }
153 });
154
155 final List<List<Tile>> tiles = tessellator.tessellate(small, 50000.0, 150000.0, 0, 0,
156 false, false);
157 Assert.assertEquals(1, tiles.size());
158 Assert.assertEquals(1, tiles.get(0).size());
159 Tile t = tiles.get(0).get(0);
160
161
162
163 Assert.assertEquals(150000.0,
164 Vector3D.distance(ellipsoid.transform(t.getVertices()[0]),
165 ellipsoid.transform(t.getVertices()[1])),
166 140.0);
167 Assert.assertEquals( 50000.0,
168 Vector3D.distance(ellipsoid.transform(t.getVertices()[1]),
169 ellipsoid.transform(t.getVertices()[2])),
170 0.4);
171 Assert.assertEquals(150000.0,
172 Vector3D.distance(ellipsoid.transform(t.getVertices()[2]),
173 ellipsoid.transform(t.getVertices()[3])),
174 140.0);
175 Assert.assertEquals( 50000.0,
176 Vector3D.distance(ellipsoid.transform(t.getVertices()[3]),
177 ellipsoid.transform(t.getVertices()[0])),
178 0.4);
179
180 }
181
182 @Test
183 public void testTilesSmallZoneWithTruncation() throws IOException {
184
185 TileAiming aiming = new ConstantAzimuthAiming(ellipsoid, FastMath.toRadians(193.7));
186 EllipsoidTessellator tessellator =
187 new EllipsoidTessellator(ellipsoid, aiming, 16);
188
189 SphericalPolygonsSet small = buildSimpleZone(1.0e-10, new double[][] {
190 { 43.6543, 1.4268 }, { 43.6120, 1.4179 }, { 43.6016, 1.3994 }, { 43.5682, 1.4159 },
191 { 43.5707, 1.4358 }, { 43.5573, 1.4941 }, { 43.6041, 1.4866 }
192 });
193
194 final List<List<Tile>> tiles = tessellator.tessellate(small, 50000.0, 150000.0, 0, 0,
195 true, true);
196 Assert.assertEquals(1, tiles.size());
197 Assert.assertEquals(1, tiles.get(0).size());
198 Tile t = tiles.get(0).get(0);
199
200
201 Assert.assertEquals(3.0 / 16.0 * 150000.0,
202 Vector3D.distance(ellipsoid.transform(t.getVertices()[0]),
203 ellipsoid.transform(t.getVertices()[1])),
204 10.0);
205 Assert.assertEquals(4.0 / 16.0 * 50000.0,
206 Vector3D.distance(ellipsoid.transform(t.getVertices()[1]),
207 ellipsoid.transform(t.getVertices()[2])),
208 0.01);
209 Assert.assertEquals(3.0 / 16.0 * 150000.0,
210 Vector3D.distance(ellipsoid.transform(t.getVertices()[2]),
211 ellipsoid.transform(t.getVertices()[3])),
212 10.0);
213 Assert.assertEquals(4.0 / 16.0 * 50000.0,
214 Vector3D.distance(ellipsoid.transform(t.getVertices()[3]),
215 ellipsoid.transform(t.getVertices()[0])),
216 0.01);
217 }
218
219 @Test
220 public void testStairedTruncatedTiles() {
221
222 TileAiming aiming = new ConstantAzimuthAiming(ellipsoid, FastMath.toRadians(170.0));
223 EllipsoidTessellator tessellator =
224 new EllipsoidTessellator(ellipsoid, aiming, 16);
225
226 SphericalPolygonsSet small = buildSimpleZone(1.0e-10, new double[][] {
227 { 45.335, 0.457 },
228 { 45.342, 0.469 },
229 { 45.371, 0.424 }
230 });
231
232 final double maxWidth = 800.0;
233 final double maxLength = 10000.0;
234 final List<List<Tile>> tiles = tessellator.tessellate(small, maxWidth, maxLength, 0, 0,
235 false, true);
236 Assert.assertEquals(1, tiles.size());
237 Assert.assertEquals(4, tiles.get(0).size());
238 for (final Tile tile : tiles.get(0)) {
239 Vector3D v0 = ellipsoid.transform(tile.getVertices()[0]);
240 Vector3D v1 = ellipsoid.transform(tile.getVertices()[1]);
241 Vector3D v2 = ellipsoid.transform(tile.getVertices()[2]);
242 Vector3D v3 = ellipsoid.transform(tile.getVertices()[3]);
243 Assert.assertTrue(Vector3D.distance(v0, v1) < (6.0002 / 16.0) * maxLength);
244 Assert.assertTrue(Vector3D.distance(v2, v3) < (6.0002 / 16.0) * maxLength);
245 Assert.assertEquals(maxWidth, Vector3D.distance(v1, v2), 1.0e-3);
246 Assert.assertEquals(maxWidth, Vector3D.distance(v3, v0), 1.0e-3);
247 }
248
249 }
250
251 @Test
252 public void testTooThinRemainingRegion() {
253 TileAiming aiming = new ConstantAzimuthAiming(ellipsoid, -0.2185);
254 EllipsoidTessellator tessellator =
255 new EllipsoidTessellator(ellipsoid, aiming, 16);
256
257 SphericalPolygonsSet small = buildSimpleZone(1.0e-10, new double[][]{
258 { 32.7342, -16.9407 }, { 32.7415, -16.9422 }, { 32.7481, -16.9463 }, { 32.7531, -16.9528 },
259 { 32.7561, -16.9608 }, { 32.7567, -16.9696 }, { 32.7549, -16.9781 }, { 32.7508, -16.9855 },
260 { 32.7450, -16.9909 }, { 32.7379, -16.9937 }, { 32.7305, -16.9937 }, { 32.7235, -16.9909 },
261 { 32.7177, -16.9855 }, { 32.7136, -16.9781 }, { 32.7118, -16.9696 }, { 32.7124, -16.9608 },
262 { 32.7154, -16.9528 }, { 32.7204, -16.9463 }, { 32.7269, -16.9422 }
263 });
264
265 final double maxWidth = 40000.0;
266 final double maxLength = 40000.0;
267 final List<List<Tile>> tiles = tessellator.tessellate(small, maxWidth, maxLength, 0, 0,
268 false, true);
269 Assert.assertEquals(1, tiles.size());
270 Assert.assertEquals(1, tiles.get(0).size());
271 for (final Tile tile : tiles.get(0)) {
272 Vector3D v0 = ellipsoid.transform(tile.getVertices()[0]);
273 Vector3D v1 = ellipsoid.transform(tile.getVertices()[1]);
274 Vector3D v2 = ellipsoid.transform(tile.getVertices()[2]);
275 Vector3D v3 = ellipsoid.transform(tile.getVertices()[3]);
276 Assert.assertTrue(Vector3D.distance(v0, v1) < 0.3 * maxLength);
277 Assert.assertEquals(maxWidth, Vector3D.distance(v1, v2), 0.1);
278 Assert.assertTrue(Vector3D.distance(v2, v3) < 0.3 * maxLength);
279 Assert.assertEquals(maxWidth, Vector3D.distance(v3, v0), 0.1);
280 }
281
282 }
283
284 @Test
285 public void testNormalZoneTolerance() {
286 doTestVariableTolerance(1.0e-10);
287 }
288
289 @Test
290 public void testLargeZoneTolerance() {
291
292 doTestVariableTolerance(1.0e-6);
293 }
294
295 @Test
296 public void testHugeZoneTolerance() {
297
298
299 doTestVariableTolerance(1.0e-4);
300 }
301
302 private void doTestVariableTolerance(final double tolerance) {
303 final ConstantAzimuthAiming aiming = new ConstantAzimuthAiming(ellipsoid,
304 FastMath.toRadians(-168.178485));
305 EllipsoidTessellator tessellator =
306 new EllipsoidTessellator(ellipsoid, aiming, 16);
307
308 SphericalPolygonsSet small = buildSimpleZone(tolerance, new double[][]{
309 { -0.01048739, 0.01598931 }, { -0.00789627, 0.01555693 }, { -0.00558595, 0.01430664 },
310 { -0.00380677, 0.01237394 }, { -0.00275154, 0.00996826 }, { -0.00253461, 0.00735029 },
311 { -0.00317949, 0.00480374 }, { -0.00461629, 0.00260455 }, { -0.00668931, 0.00099105 },
312 { -0.00917392, 0.00013808 }, { -0.01180086, 0.00013808 }, { -0.01428546, 0.00099105 },
313 { -0.01635849, 0.00260455 }, { -0.01779529, 0.00480374 }, { -0.01844016, 0.00735029 },
314 { -0.01822323, 0.00996826 }, { -0.01716800, 0.01237394 }, { -0.01538882, 0.01430664 },
315 { -0.01307850, 0.01555693 }
316 });
317
318 final double maxWidth = 40000.0;
319 final double maxLength = 40000.0;
320 final List<List<Tile>> tiles =
321 tessellator.tessellate(small, maxWidth, maxLength, 0, 0, false, true);
322 Assert.assertEquals(1, tiles.size());
323 Assert.assertEquals(1, tiles.get(0).size());
324
325 }
326
327 private void checkTilesDontOverlap(final List<List<Tile>> tiles) {
328 for (final List<Tile> list : tiles) {
329 for (final Tile tile : list) {
330 final SphericalPolygonsSet quadrilateral =
331 new SphericalPolygonsSet(1.0e-10,
332 toS2Point(tile.getVertices()[0]),
333 toS2Point(tile.getVertices()[1]),
334 toS2Point(tile.getVertices()[2]),
335 toS2Point(tile.getVertices()[3]));
336 for (final List<Tile> otherList : tiles) {
337 for (final Tile otherTile : otherList) {
338 if (otherTile != tile) {
339 for (final GeodeticPoint vertex : otherTile.getVertices()) {
340 Assert.assertEquals("tiles overlap at: " + vertex,
341 Location.OUTSIDE, quadrilateral.checkPoint(toS2Point(vertex)));
342 }
343 }
344 }
345 }
346 }
347 }
348 }
349
350 @Test
351 public void testSampleAroundPoleConstantAzimuth() {
352 SphericalPolygonsSet aoi = new SphericalPolygonsSet(1.e-9, new S2Point[] {
353 new S2Point(FastMath.toRadians(-120.0), FastMath.toRadians(5.0)),
354 new S2Point(FastMath.toRadians( 0.0), FastMath.toRadians(5.0)),
355 new S2Point(FastMath.toRadians( 120.0), FastMath.toRadians(5.0))
356 });
357 doTestSampleAroundPole(aoi, new ConstantAzimuthAiming(ellipsoid, 0.0), -1);
358 }
359
360 @Test
361 public void testSampleAroundPoleDivertedSingularity() {
362 SphericalPolygonsSet aoi = new SphericalPolygonsSet(1.e-9, new S2Point[] {
363 new S2Point(FastMath.toRadians(-120.0), FastMath.toRadians(5.0)),
364 new S2Point(FastMath.toRadians( 0.0), FastMath.toRadians(5.0)),
365 new S2Point(FastMath.toRadians( 120.0), FastMath.toRadians(5.0))
366 });
367 doTestSampleAroundPole(aoi, new DivertedSingularityAiming(aoi), 993);
368 }
369
370 private void doTestSampleAroundPole(final SphericalPolygonsSet aoi, final TileAiming aiming, final int expectedNodes) {
371 EllipsoidTessellator tessellator = new EllipsoidTessellator(ellipsoid, aiming, 1);
372 try {
373 List<List<GeodeticPoint>> sampledZone = tessellator.sample(aoi, 20000.0, 20000.0);
374 if (expectedNodes < 0) {
375 Assert.fail("an exception should have been thrown");
376 } else {
377 Assert.assertEquals(1, sampledZone.size());
378 Assert.assertEquals(expectedNodes, sampledZone.get(0).size());
379 }
380 } catch (OrekitException oe) {
381 Assert.assertEquals(OrekitMessages.CANNOT_COMPUTE_AIMING_AT_SINGULAR_POINT, oe.getSpecifier());
382 }
383
384 }
385
386 private S2Point toS2Point(final GeodeticPoint point) {
387 return new S2Point(point.getLongitude(), 0.5 * FastMath.PI - point.getLatitude());
388 }
389
390 @Before
391 public void setUp() {
392 Utils.setDataRoot("regular-data");
393
394
395
396
397
398
399
400
401
402
403
404 AbsoluteDate date = new AbsoluteDate("2012-01-01T00:00:00.000", TimeScalesFactory.getUTC());
405 Frame eme2000 = FramesFactory.getEME2000();
406 orbit = new CircularOrbit(7173352.811913891,
407 -4.029194321683225E-4, 0.0013530362644647786,
408 FastMath.toRadians(98.63218182243709),
409 FastMath.toRadians(77.55565567747836),
410 FastMath.PI, PositionAngle.TRUE,
411 eme2000, date, Constants.EIGEN5C_EARTH_MU);
412 ellipsoid =
413 new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
414 Constants.WGS84_EARTH_FLATTENING,
415 FramesFactory.getITRF(IERSConventions.IERS_2010, true));
416 }
417
418 private SphericalPolygonsSet buildFrance() {
419
420 final SphericalPolygonsSet continental = buildSimpleZone(1.0e-10, new double[][] {
421 { 51.14850, 2.51357 }, { 50.94660, 1.63900 }, { 50.12717, 1.33876 }, { 49.34737, -0.98946 },
422 { 49.77634, -1.93349 }, { 48.64442, -1.61651 }, { 48.90169, -3.29581 }, { 48.68416, -4.59234 },
423 { 47.95495, -4.49155 }, { 47.57032, -2.96327 }, { 46.01491, -1.19379 }, { 44.02261, -1.38422 },
424 { 43.42280, -1.90135 }, { 43.03401, -1.50277 }, { 42.34338, 1.82679 }, { 42.47301, 2.98599 },
425 { 43.07520, 3.10041 }, { 43.39965, 4.55696 }, { 43.12889, 6.52924 }, { 43.69384, 7.43518 },
426 { 44.12790, 7.54959 }, { 45.02851, 6.74995 }, { 45.33309, 7.09665 }, { 46.42967, 6.50009 },
427 { 46.27298, 6.02260 }, { 46.72577, 6.03738 }, { 47.62058, 7.46675 }, { 49.01778, 8.09927 },
428 { 49.20195, 6.65822 }, { 49.44266, 5.89775 }, { 49.98537, 4.79922 }
429 });
430
431 final SphericalPolygonsSet corsica =
432 EllipsoidTessellator.buildSimpleZone(1.0e-10,
433 new GeodeticPoint(FastMath.toRadians(42.15249),
434 FastMath.toRadians(9.56001),
435 0.0),
436 new GeodeticPoint(FastMath.toRadians(43.00998),
437 FastMath.toRadians(9.39000),
438 0.0),
439 new GeodeticPoint(FastMath.toRadians(42.62812),
440 FastMath.toRadians(8.74600),
441 0.0),
442 new GeodeticPoint(FastMath.toRadians(42.25651),
443 FastMath.toRadians(8.54421),
444 0.0),
445 new GeodeticPoint(FastMath.toRadians(41.58361),
446 FastMath.toRadians(8.77572),
447 0.0),
448 new GeodeticPoint(FastMath.toRadians(41.38000),
449 FastMath.toRadians(9.22975),
450 0.0));
451
452 return (SphericalPolygonsSet) new RegionFactory<Sphere2D>().union(continental, corsica);
453
454 }
455
456 private SphericalPolygonsSet buildSimpleZone(double tolerance, double[][] points) {
457 for (int i = 0; i < points.length; ++i) {
458 points[i][0] = FastMath.toRadians(points[i][0]);
459 points[i][1] = FastMath.toRadians(points[i][1]);
460 }
461 return EllipsoidTessellator.buildSimpleZone(tolerance, points);
462 }
463
464 private Orbit orbit;
465 private OneAxisEllipsoid ellipsoid;
466
467 }