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.bodies;
18  
19  import org.hipparchus.geometry.euclidean.threed.Vector3D;
20  import org.hipparchus.geometry.euclidean.twod.Vector2D;
21  import org.hipparchus.util.FastMath;
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.frames.FramesFactory;
27  import org.orekit.time.AbsoluteDate;
28  import org.orekit.time.TimeInterpolator;
29  import org.orekit.utils.CartesianDerivativesFilter;
30  import org.orekit.utils.Constants;
31  import org.orekit.utils.IERSConventions;
32  import org.orekit.utils.TimeStampedPVCoordinates;
33  import org.orekit.utils.TimeStampedPVCoordinatesHermiteInterpolator;
34  
35  import java.util.ArrayList;
36  import java.util.List;
37  
38  
39  public class EllipseTest {
40  
41      @Test
42      void testMeridianShape() {
43          OneAxisEllipsoid model =
44                  new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
45                                       Constants.WGS84_EARTH_FLATTENING,
46                                       FramesFactory.getITRF(IERSConventions.IERS_2010, true));
47          Ellipse e = model.getPlaneSection(new Vector3D(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, 0, 0),
48                                            Vector3D.PLUS_J);
49          Assertions.assertEquals(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
50                              e.getA(),
51                              1.0e-15 * Constants.WGS84_EARTH_EQUATORIAL_RADIUS);
52          Assertions.assertEquals(Constants.WGS84_EARTH_EQUATORIAL_RADIUS * (1 - Constants.WGS84_EARTH_FLATTENING),
53                              e.getB(),
54                              1.0e-15 * Constants.WGS84_EARTH_EQUATORIAL_RADIUS);
55          Assertions.assertEquals(0.5 * FastMath.PI, Vector3D.angle(Vector3D.PLUS_J, e.getU()), 1.0e-15);
56          Assertions.assertEquals(0.5 * FastMath.PI, Vector3D.angle(Vector3D.PLUS_K, e.getU()), 1.0e-15);
57          Assertions.assertEquals(0.5 * FastMath.PI, Vector3D.angle(Vector3D.PLUS_I, e.getV()), 1.0e-15);
58          Assertions.assertEquals(0.5 * FastMath.PI, Vector3D.angle(Vector3D.PLUS_J, e.getV()), 1.0e-15);
59      }
60  
61      @Test
62      void testEquatorialShape() {
63          OneAxisEllipsoid model =
64                  new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
65                                       Constants.WGS84_EARTH_FLATTENING,
66                                       FramesFactory.getITRF(IERSConventions.IERS_2010, true));
67          Ellipse e = model.getPlaneSection(new Vector3D(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, 0, 0),
68                                            Vector3D.PLUS_K);
69          Assertions.assertEquals(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
70                              e.getA(),
71                              1.0e-15 * Constants.WGS84_EARTH_EQUATORIAL_RADIUS);
72          Assertions.assertEquals(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
73                              e.getB(),
74                              1.0e-15 * Constants.WGS84_EARTH_EQUATORIAL_RADIUS);
75      }
76  
77      @Test
78      void testProjectionDerivatives() {
79          Ellipse e = new Ellipse(Vector3D.ZERO, Vector3D.PLUS_I, Vector3D.PLUS_J,
80                                  6.4e6, 6.3e6, FramesFactory.getGCRF());
81          TimeStampedPVCoordinates linearMotion =
82                  new TimeStampedPVCoordinates(AbsoluteDate.J2000_EPOCH,
83                                               new Vector3D(7.0e6, 5.0e6, 0.0),
84                                               new Vector3D(3.0e3, 4.0e3, 0.0),
85                                               Vector3D.ZERO);
86          TimeStampedPVCoordinates g0 = e.projectToEllipse(linearMotion);
87          List<TimeStampedPVCoordinates> sample = new ArrayList<TimeStampedPVCoordinates>();
88          for (double dt = -0.25; dt <= 0.25; dt += 0.125) {
89              sample.add(e.projectToEllipse(linearMotion.shiftedBy(dt)));
90          }
91  
92          // create interpolator
93          final TimeInterpolator<TimeStampedPVCoordinates> interpolator =
94                  new TimeStampedPVCoordinatesHermiteInterpolator(sample.size(), CartesianDerivativesFilter.USE_P);
95  
96          TimeStampedPVCoordinates ref = interpolator.interpolate(g0.getDate(), sample);
97          Assertions.assertEquals(0,
98                              Vector3D.distance(g0.getPosition(), ref.getPosition()) / ref.getPosition().getNorm(),
99                              1.0e-15);
100         Assertions.assertEquals(0,
101                             Vector3D.distance(g0.getVelocity(), ref.getVelocity()) / ref.getVelocity().getNorm(),
102                             6.0e-12);
103         Assertions.assertEquals(0,
104                             Vector3D.distance(g0.getAcceleration(), ref.getAcceleration()) / ref.getAcceleration().getNorm(),
105                             8.0e-8);
106 
107     }
108 
109     @Test
110     void testMinRadiusOfCurvature() {
111         final double a = 100.0;
112         final double b =  50.0;
113         Ellipse e = new Ellipse(Vector3D.ZERO, Vector3D.PLUS_I, Vector3D.PLUS_J,
114                                 a, b, FramesFactory.getGCRF());
115         Vector2D point = new Vector2D(10 * a, 0.0);
116         Assertions.assertEquals(b * b / a,
117                            Vector2D.distance(e.projectToEllipse(point), e.getCenterOfCurvature(point)),
118                            1.0e-15);
119     }
120 
121     @Test
122     void testMaxRadiusOfCurvature() {
123         final double a = 100.0;
124         final double b =  50.0;
125         Ellipse e = new Ellipse(Vector3D.ZERO, Vector3D.PLUS_I, Vector3D.PLUS_J,
126                                 a, b, FramesFactory.getGCRF());
127         Vector2D point = new Vector2D(0.0, 10 * b);
128         Assertions.assertEquals(a * a / b,
129                            Vector2D.distance(e.projectToEllipse(point), e.getCenterOfCurvature(point)),
130                            1.0e-15);
131     }
132 
133     @Test
134     void testFlatEllipse() {
135         final double a = 0.839;
136         final double b = 0.176;
137         final Ellipse  ellipse   = new Ellipse(Vector3D.ZERO, Vector3D.PLUS_I, Vector3D.PLUS_J,
138                                                a, b, FramesFactory.getGCRF());
139         final Vector2D close = ellipse.projectToEllipse(new Vector2D(2.0, 4.0));
140         Assertions.assertEquals(1.0,
141                             close.getX() * close.getX() / (a * a) + close.getY() * close.getY() / (b * b),
142                             1.0e-15);
143     }
144 
145     @BeforeEach
146     public void setUp() {
147         Utils.setDataRoot("regular-data");
148     }
149 
150 }
151