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.geometry.euclidean.threed.Vector3D;
20  import org.hipparchus.util.FastMath;
21  import org.hipparchus.util.SinCos;
22  import org.orekit.propagation.events.VisibilityTrigger;
23  
24  /** Class representing a spacecraft sensor Field Of View with circular shape.
25   * <p>The field of view is defined by an axis and an half-aperture angle.</p>
26   * @author Luc Maisonobe
27   * @since 10.1
28   */
29  public class CircularFieldOfView extends SmoothFieldOfView {
30  
31      /** FOV half aperture angle. */
32      private final double halfAperture;
33  
34      /** Scaled X axis defining FoV boundary. */
35      private final Vector3D scaledX;
36  
37      /** Scaled Y axis defining FoV boundary. */
38      private final Vector3D scaledY;
39  
40      /** Scaled Z axis defining FoV boundary. */
41      private final Vector3D scaledZ;
42  
43      /** Build a new instance.
44       * @param center direction of the FOV center, in spacecraft frame
45       * @param halfAperture FOV half aperture angle
46       * @param margin angular margin to apply to the zone (if positive,
47       * the Field Of View will consider points slightly outside of the
48       * zone are still visible)
49       */
50      public CircularFieldOfView(final Vector3D center, final double halfAperture,
51                                 final double margin) {
52  
53          super(center, center.orthogonal(), margin);
54          this.halfAperture = halfAperture;
55  
56          // precompute utility vectors for walking around the FoV
57          final SinCos sc = FastMath.sinCos(halfAperture);
58          scaledX   = new Vector3D(sc.sin(), getX());
59          scaledY   = new Vector3D(sc.sin(), getY());
60          scaledZ   = new Vector3D(sc.cos(), getZ());
61  
62      }
63  
64      /** get the FOV half aperture angle.
65       * @return FOV half aperture angle
66       */
67      public double getHalfAperture() {
68          return halfAperture;
69      }
70  
71      /** {@inheritDoc} */
72      @Override
73      public double offsetFromBoundary(final Vector3D lineOfSight, final double angularRadius,
74                                       final VisibilityTrigger trigger) {
75          return Vector3D.angle(getCenter(), lineOfSight) - halfAperture +
76                 trigger.radiusCorrection(angularRadius) - getMargin();
77      }
78  
79      /** {@inheritDoc} */
80      @Override
81      public Vector3D projectToBoundary(final Vector3D lineOfSight) {
82          return directionAt(FastMath.atan2(Vector3D.dotProduct(lineOfSight, getY()),
83                                            Vector3D.dotProduct(lineOfSight, getX())));
84      }
85  
86      /** {@inheritDoc} */
87      @Override
88      protected Vector3D directionAt(final double angle) {
89          final SinCos sc = FastMath.sinCos(angle);
90          return new Vector3D(sc.cos(), scaledX, sc.sin(), scaledY, 1.0, scaledZ);
91      }
92  
93  }