Tile.java

  1. /* Copyright 2002-2024 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. import java.io.Serializable;

  19. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  20. import org.hipparchus.util.FastMath;
  21. import org.orekit.bodies.GeodeticPoint;

  22. /** Simple data structure for a quadrilateral tile shape on a body surface.
  23.  * <p>
  24.  * This class is devoted to simple usage only. It assumes the edges
  25.  * are strictly between 0 and π radians and that the angles between
  26.  * edges are also strictly between 0 and π radians.
  27.  * </p>
  28.  * @see AlongTrackAiming
  29.  * @see ConstantAzimuthAiming
  30.  * @author Luc Maisonobe
  31.  */
  32. public class Tile implements Serializable {

  33.     /** Serializable UID. */
  34.     private static final long serialVersionUID = 20150313L;

  35.     /** First vertex. */
  36.     private final GeodeticPoint v0;

  37.     /** Second vertex. */
  38.     private final GeodeticPoint v1;

  39.     /** Third vertex. */
  40.     private final GeodeticPoint v2;

  41.     /** Fourth vertex. */
  42.     private final GeodeticPoint v3;

  43.     /** Create a tile.
  44.      * <p>
  45.      * It is caller responsibility o ensure the vertices define a
  46.      * simple non-degenerated tile (i.e. edges are strictly between
  47.      * 0 than π radians and angles between edges are also strictly
  48.      * between 0 and π radians). No checks are performed here.
  49.      * </p>
  50.      * @param v0 first vertex
  51.      * @param v1 second vertex
  52.      * @param v2 third vertex
  53.      * @param v3 fourth vertex
  54.      */
  55.     public Tile(final GeodeticPoint v0, final GeodeticPoint v1,
  56.                 final GeodeticPoint v2, final GeodeticPoint v3) {
  57.         this.v0   = v0;
  58.         this.v1   = v1;
  59.         this.v2   = v2;
  60.         this.v3   = v3;
  61.     }

  62.     /** Get the four vertices.
  63.      * @return four vertices
  64.      */
  65.     public GeodeticPoint[] getVertices() {
  66.         return new GeodeticPoint[] {
  67.             v0, v1, v2, v3
  68.         };
  69.     }

  70.     /** Get an interpolated point inside the tile.
  71.      * <p>
  72.      * The interpolated point is based on bilinear interpolations
  73.      * along the body surface assumed to be <em>spherical</em>,
  74.      * and along the vertical axis.
  75.      * </p>
  76.      * <p>
  77.      * The interpolation parameters are chosen such that
  78.      * (u = 0, v = 0) maps to vertex v0, (u = 1, v = 0) maps
  79.      * to vertex v1, (u = 1, v = 1) maps to vertex v2 and
  80.      * (u = 0, v = 1) maps to vertex v3.
  81.      * </p>
  82.      * @param u first interpolation parameter (should be between
  83.      * 0 and 1 to remain inside the tile)
  84.      * @param v second interpolation parameter (should be between
  85.      * 0 and 1 to remain inside the tile)
  86.      * @return interpolated point
  87.      */
  88.     public GeodeticPoint getInterpolatedPoint(final double u, final double v) {

  89.         // bilinear interpolation along a spherical shape
  90.         final Vector3D pu0 = interpolate(v0.getZenith(), v1.getZenith(), u);
  91.         final Vector3D pu1 = interpolate(v3.getZenith(), v2.getZenith(), u);
  92.         final Vector3D puv = interpolate(pu0, pu1, v);

  93.         // bilinear interpolation of altitude
  94.         final double hu0 = v1.getAltitude() * u + v0.getAltitude() * (1 - u);
  95.         final double hu1 = v2.getAltitude() * u + v3.getAltitude() * (1 - u);
  96.         final double huv = hu1 * v + hu0 * (1 - v);

  97.         // create interpolated point
  98.         return new GeodeticPoint(puv.getDelta(), puv.getAlpha(), huv);

  99.     }

  100.     /** Interpolate a vector along a unit sphere.
  101.      * @param p0 first base unit vector
  102.      * @param p1 second base unit vector
  103.      * @param r interpolation parameter (0 for p0, 1 for p1)
  104.      * @return interpolated unit vector
  105.      */
  106.     private Vector3D interpolate(final Vector3D p0, final Vector3D p1, final double r) {

  107.         // find all interpolation angles
  108.         final double theta       = Vector3D.angle(p0, p1);
  109.         final double alpha       = r * theta;
  110.         final double thetaMAlpha = (1 - r) * theta;

  111.         final double sinTheta       = FastMath.sin(theta);
  112.         final double sinAlpha       = FastMath.sin(alpha);
  113.         final double sinThetaMAlpha = FastMath.sin(thetaMAlpha);

  114.         // interpolate
  115.         return new Vector3D(sinThetaMAlpha / sinTheta, p0, sinAlpha / sinTheta, p1);

  116.     }

  117.     /** Get the center point.
  118.      * <p>
  119.      * The center points corresponds to {@link
  120.      * #getInterpolatedPoint(double, double) getInterpolatedPoint(0.5, 0.5)}
  121.      * </p>
  122.      * @return center point
  123.      */
  124.     public GeodeticPoint getCenter() {
  125.         return getInterpolatedPoint(0.5, 0.5);
  126.     }

  127. }