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.geometry.fov;
18  
19  import org.hipparchus.exception.LocalizedCoreFormats;
20  import org.hipparchus.geometry.euclidean.threed.Vector3D;
21  import org.hipparchus.random.UnitSphereRandomVectorGenerator;
22  import org.hipparchus.random.Well1024a;
23  import org.hipparchus.util.FastMath;
24  import org.hipparchus.util.MathUtils;
25  import org.junit.jupiter.api.Assertions;
26  import org.junit.jupiter.api.Test;
27  import org.orekit.errors.OrekitException;
28  import org.orekit.geometry.fov.PolygonalFieldOfView.DefiningConeType;
29  import org.orekit.propagation.events.VisibilityTrigger;
30  
31  public class DoubleDihedraFieldOfViewTest {
32  
33      @Test
34      public void testDihedralFielOfView() {
35          double maxError = 0;
36          for (double alpha1 = 0; alpha1 < 0.5 * FastMath.PI; alpha1 += 0.1) {
37              for (double alpha2 = 0; alpha2 < 0.5 * FastMath.PI; alpha2 += 0.1) {
38                  DoubleDihedraFieldOfView fov = new DoubleDihedraFieldOfView(Vector3D.PLUS_I,
39                                                                              Vector3D.PLUS_K, alpha1,
40                                                                              Vector3D.PLUS_J, alpha2,
41                                                                              0.125);
42                  double eta = FastMath.acos(FastMath.sin(alpha1) * FastMath.sin(alpha2));
43                  double theoreticalArea = MathUtils.TWO_PI - 4 * eta;
44                  double error = theoreticalArea - fov.getZone().getSize();
45                  maxError = FastMath.max(FastMath.abs(error), maxError);
46                  Assertions.assertEquals(0.125, fov.getMargin(), 1.0e-15);
47              }
48          }
49          Assertions.assertEquals(0, maxError, 4.0e-15);
50      }
51  
52      @Test
53      public void testTooWideDihedralFielOfView() {
54          double tooLarge = 1.6;
55          try {
56              new DoubleDihedraFieldOfView(Vector3D.PLUS_I,
57                                           Vector3D.PLUS_K, 0.1,
58                                           Vector3D.PLUS_J, tooLarge,
59                                           0.125);
60              Assertions.fail("an exception should have been thrown");
61          } catch(OrekitException oe) {
62              Assertions.assertEquals(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE, oe.getSpecifier());
63              Assertions.assertEquals(tooLarge,          (Double) oe.getParts()[0], 1.0e-15);
64              Assertions.assertEquals(0,                 (Double) oe.getParts()[1], 1.0e-15);
65              Assertions.assertEquals(0.5 * FastMath.PI, (Double) oe.getParts()[2], 1.0e-15);
66          }
67      }
68  
69      @Test
70      public void testSquare() {
71          DoubleDihedraFieldOfView square1 = new DoubleDihedraFieldOfView(Vector3D.PLUS_K,
72                                                                          Vector3D.PLUS_I, 0.25,
73                                                                          Vector3D.MINUS_J, 0.25,
74                                                                          0.0);
75          PolygonalFieldOfView square2 = new PolygonalFieldOfView(Vector3D.PLUS_K, DefiningConeType.INSIDE_CONE_TOUCHING_POLYGON_AT_EDGES_MIDDLE,
76                                                                  Vector3D.PLUS_I, 0.25, 4, 0.0);
77          Assertions.assertEquals(square1.getZone().getSize(),         square2.getZone().getSize(),         1.0e-15);
78          Assertions.assertEquals(square1.getZone().getBoundarySize(), square2.getZone().getBoundarySize(), 1.0e-15);
79          UnitSphereRandomVectorGenerator random =
80                          new UnitSphereRandomVectorGenerator(3, new Well1024a(0x17df21c7598b114bl));
81          for (int i = 0; i < 1000; ++i) {
82              Vector3D v = new Vector3D(random.nextVector()).scalarMultiply(1.0e6);
83              Assertions.assertEquals(square1.offsetFromBoundary(v, 0.125, VisibilityTrigger.VISIBLE_ONLY_WHEN_FULLY_IN_FOV),
84                                  square2.offsetFromBoundary(v, 0.125, VisibilityTrigger.VISIBLE_ONLY_WHEN_FULLY_IN_FOV),
85                                  2.6e-15);
86          }
87      }
88  
89  }