1   /* Copyright 2002-2025 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.models.earth.tessellation;
18  
19  import org.hipparchus.geometry.euclidean.threed.Vector3D;
20  import org.hipparchus.util.FastMath;
21  import org.hipparchus.util.MathUtils;
22  import org.junit.jupiter.api.Assertions;
23  import org.junit.jupiter.api.BeforeEach;
24  import org.junit.jupiter.api.Test;
25  import org.orekit.Utils;
26  import org.orekit.bodies.GeodeticPoint;
27  import org.orekit.bodies.OneAxisEllipsoid;
28  import org.orekit.frames.FramesFactory;
29  import org.orekit.orbits.CircularOrbit;
30  import org.orekit.orbits.Orbit;
31  import org.orekit.orbits.PositionAngleType;
32  import org.orekit.time.AbsoluteDate;
33  import org.orekit.time.TimeScalesFactory;
34  import org.orekit.utils.Constants;
35  import org.orekit.utils.IERSConventions;
36  
37  public class AlongTrackAimingTest {
38  
39      @Test
40      public void testAscending() {
41          final AlongTrackAiming tileAiming = new AlongTrackAiming(ellipsoid, orbit, true);
42          for (double latitude = FastMath.toRadians(-50.21); latitude < FastMath.toRadians(50.21); latitude += 0.001) {
43              final GeodeticPoint gp = new GeodeticPoint(latitude, 0.0, 0.0);
44              final Vector3D aiming = tileAiming.alongTileDirection(ellipsoid.transform(gp), gp);
45              Assertions.assertEquals(1.0, aiming.getNorm(), 1.0e-12);
46              final double elevation = 0.5 * FastMath.PI - Vector3D.angle(aiming, gp.getZenith());
47              final double azimuth = FastMath.atan2(Vector3D.dotProduct(aiming, gp.getEast()),
48                                                    Vector3D.dotProduct(aiming, gp.getNorth()));
49              Assertions.assertEquals(0.0, FastMath.toDegrees(elevation), 1.0e-6);
50              if (FastMath.abs(FastMath.toDegrees(latitude)) > 49.6) {
51                  Assertions.assertTrue(FastMath.toDegrees(azimuth) > 80.0);
52              }
53              if (FastMath.abs(FastMath.toDegrees(latitude)) < 5.0) {
54                  Assertions.assertTrue(FastMath.toDegrees(azimuth) < 37.0);
55              }
56              Assertions.assertTrue(FastMath.toDegrees(azimuth) > 36.7);
57          }
58      }
59  
60      @Test
61      public void testDescending() {
62          final AlongTrackAiming tileAiming = new AlongTrackAiming(ellipsoid, orbit, false);
63          for (double latitude = FastMath.toRadians(-50.21); latitude < FastMath.toRadians(50.21); latitude += 0.001) {
64              final GeodeticPoint gp = new GeodeticPoint(latitude, 0.0, 0.0);
65              final Vector3D aiming = tileAiming.alongTileDirection(ellipsoid.transform(gp), gp);
66              Assertions.assertEquals(1.0, aiming.getNorm(), 1.0e-12);
67              final double elevation = 0.5 * FastMath.PI - Vector3D.angle(aiming, gp.getZenith());
68              final double azimuth = MathUtils.normalizeAngle(FastMath.atan2(Vector3D.dotProduct(aiming, gp.getEast()),
69                                                                             Vector3D.dotProduct(aiming, gp.getNorth())),
70                                                              FastMath.PI);
71              Assertions.assertEquals(0.0, FastMath.toDegrees(elevation), 1.0e-6);
72              if (FastMath.abs(FastMath.toDegrees(latitude)) > 49.7) {
73                  Assertions.assertTrue(FastMath.toDegrees(azimuth) < 99.0);
74              }
75              if (FastMath.abs(FastMath.toDegrees(latitude)) < 5.0) {
76                  Assertions.assertTrue(FastMath.toDegrees(azimuth) > 143);
77              }
78              Assertions.assertTrue(FastMath.toDegrees(azimuth) < 143.3);
79          }
80      }
81  
82      @Test
83      public void testTooNorthernLatitudePrograde() {
84          final AlongTrackAiming tileAiming = new AlongTrackAiming(ellipsoid, orbit, true);
85          final GeodeticPoint gp = new GeodeticPoint(FastMath.toRadians(51.0), 0.0, 0.0);
86          final Vector3D direction = tileAiming.alongTileDirection(ellipsoid.transform(gp), gp);
87          Assertions.assertEquals(0.0, Vector3D.angle(direction, gp.getEast()), 1.0e-15);
88      }
89  
90      @Test
91      public void testTooNorthernLatitudeRetrograde() {
92          final AlongTrackAiming tileAiming = new AlongTrackAiming(ellipsoid,
93                                                                   new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(130.), FastMath.toRadians(270.),
94                                                                                     FastMath.toRadians(5.300), PositionAngleType.MEAN,
95                                                                                     FramesFactory.getEME2000(),
96                                                                                     new AbsoluteDate(2008, 4, 7, 0, 0, 0, TimeScalesFactory.getUTC()),
97                                                                                     Constants.EIGEN5C_EARTH_MU),
98                                                                   true);
99          final GeodeticPoint gp = new GeodeticPoint(FastMath.toRadians(51.0), 0.0, 0.0);
100         final Vector3D direction = tileAiming.alongTileDirection(ellipsoid.transform(gp), gp);
101         Assertions.assertEquals(0.0, Vector3D.angle(direction, gp.getWest()), 1.0e-15);
102     }
103 
104     @Test
105     public void testTooSouthernLatitudePrograde() {
106         final AlongTrackAiming tileAiming = new AlongTrackAiming(ellipsoid, orbit, true);
107         final GeodeticPoint gp = new GeodeticPoint(FastMath.toRadians(-51.0), 0.0, 0.0);
108         final Vector3D direction = tileAiming.alongTileDirection(ellipsoid.transform(gp), gp);
109         Assertions.assertEquals(0.0, Vector3D.angle(direction, gp.getEast()), 1.0e-15);
110     }
111 
112     @Test
113     public void testTooSouthernLatitudeRetrrograde() {
114         final AlongTrackAiming tileAiming = new AlongTrackAiming(ellipsoid,
115                                                                  new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(130.), FastMath.toRadians(270.),
116                                                                                    FastMath.toRadians(5.300), PositionAngleType.MEAN,
117                                                                                    FramesFactory.getEME2000(),
118                                                                                    new AbsoluteDate(2008, 4, 7, 0, 0, 0, TimeScalesFactory.getUTC()),
119                                                                                    Constants.EIGEN5C_EARTH_MU),
120                                                                  true);
121         final GeodeticPoint gp = new GeodeticPoint(FastMath.toRadians(-51.0), 0.0, 0.0);
122         final Vector3D direction = tileAiming.alongTileDirection(ellipsoid.transform(gp), gp);
123         Assertions.assertEquals(0.0, Vector3D.angle(direction, gp.getWest()), 1.0e-15);
124     }
125 
126     @BeforeEach
127     public void setUp() {
128         Utils.setDataRoot("regular-data");
129         orbit = new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(50.), FastMath.toRadians(270.),
130                                   FastMath.toRadians(5.300), PositionAngleType.MEAN,
131                                   FramesFactory.getEME2000(),
132                                   new AbsoluteDate(2008, 4, 7, 0, 0, 0, TimeScalesFactory.getUTC()),
133                                   Constants.EIGEN5C_EARTH_MU);
134         ellipsoid = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
135                                          Constants.WGS84_EARTH_FLATTENING,
136                                          FramesFactory.getITRF(IERSConventions.IERS_2010, true));
137     }
138 
139     private Orbit orbit;
140     private OneAxisEllipsoid ellipsoid;
141 
142 }