FieldSegment.java

  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.ionosphere.nequick;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.util.FastMath;
  20. import org.orekit.bodies.FieldGeodeticPoint;

  21. /** Performs the computation of the coordinates along the integration path.
  22.  * @author Bryan Cazabonne
  23.  * @since 13.0
  24.  */
  25. class FieldSegment<T extends CalculusFieldElement<T>> {

  26.     /** Threshold for zenith segment. */
  27.     private static final double THRESHOLD = 1.0e-3;

  28.     /** Supporting ray. */
  29.     private final FieldRay<T> ray;

  30.     /** Integration start. */
  31.     private final T y;

  32.     /** Odd points offset. */
  33.     private final T g;

  34.     /** Integration step [m]. */
  35.     private final T deltaN;

  36.     /** Number of points. */
  37.     private final int nbPoints;

  38.     /**
  39.      * Constructor.
  40.      *
  41.      * @param n   number of intervals for integration (2 points per interval, hence 2n points will be generated)
  42.      * @param ray ray-perigee parameters
  43.      * @param s1  lower boundary of integration
  44.      * @param s2  upper boundary for integration
  45.      */
  46.     FieldSegment(final int n, final FieldRay<T> ray, final T s1, final T s2) {

  47.         this.ray = ray;

  48.         // Integration step (Eq. 195)
  49.         deltaN = s2.subtract(s1).divide(n);

  50.         // Eq. 196
  51.         g = deltaN.multiply(0.5773502691896);

  52.         // Eq. 197
  53.         y = s1.add(deltaN.subtract(g).multiply(0.5));

  54.         nbPoints = 2 * n;

  55.     }

  56.     /** Get point along the ray.
  57.      * @param index point index (between O included and {@link #getNbPoints()} excluded)
  58.      * @return point on ray
  59.      * @since 13.0
  60.      */
  61.     public FieldGeodeticPoint<T> getPoint(final int index) {

  62.         final int p = index / 2;
  63.         final T   s = y.add(deltaN.multiply(p)).add(g.multiply(index % 2));

  64.         // Heights (Eq. 178)
  65.         final T height = FastMath.sqrt(s.multiply(s).add(ray.getRadius().multiply(ray.getRadius()))).
  66.                          subtract(NeQuickModel.RE);

  67.         if (ray.getRadius().getReal() < THRESHOLD) {
  68.             // zenith segment
  69.             return new FieldGeodeticPoint<>(ray.getLatitude(),  ray.getLongitude(), height);
  70.         } else {
  71.             // Great circle parameters (Eq. 179 to 181)
  72.             final T tanDs = s.divide(ray.getRadius());
  73.             final T cosDs = FastMath.sqrt(tanDs.multiply(tanDs).add(1.0)).reciprocal();
  74.             final T sinDs = tanDs.multiply(cosDs);

  75.             // Latitude (Eq. 182 to 183)
  76.             final T sinLatS =
  77.                 ray.getScLat().sin().multiply(cosDs).add(ray.getScLat().cos().multiply(sinDs).multiply(ray.getCosineAz()));
  78.             final T cosLatS = FastMath.sqrt(sinLatS.multiply(sinLatS).negate().add(1.0));

  79.             // Longitude (Eq. 184 to 187)
  80.             final T sinLonS = sinDs.multiply(ray.getSineAz()).multiply(ray.getScLat().cos());
  81.             final T cosLonS = cosDs.subtract(ray.getScLat().sin().multiply(sinLatS));

  82.             return new FieldGeodeticPoint<>(FastMath.atan2(sinLatS, cosLatS),
  83.                                             FastMath.atan2(sinLonS, cosLonS).add(ray.getLongitude()),
  84.                                             height);

  85.         }
  86.     }

  87.     /** Get number of points.
  88.      * <p>
  89.      * Note there are 2 points per interval, so {@code index} must be between 0 (included)
  90.      * and 2n (excluded) for a segment built with {@code n} intervals
  91.      * </p>
  92.      * @return number of points
  93.      */
  94.     public int getNbPoints() {
  95.         return nbPoints;
  96.     }

  97.     /**
  98.      * Get the integration step.
  99.      *
  100.      * @return the integration step in meters
  101.      */
  102.     public T getInterval() {
  103.         return deltaN;
  104.     }

  105. }