GeodeticPoint.java

  1. /* Copyright 2002-2013 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (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. import java.io.Serializable;
  19. import java.text.NumberFormat;

  20. import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
  21. import org.apache.commons.math3.util.CompositeFormat;
  22. import org.apache.commons.math3.util.FastMath;
  23. import org.apache.commons.math3.util.MathUtils;

  24. /** Point location relative to a 2D body surface.
  25.  * <p>Instance of this class are guaranteed to be immutable.</p>
  26.  * @see BodyShape
  27.  * @author Luc Maisonobe
  28.  */
  29. public class GeodeticPoint implements Serializable {

  30.     /** Serializable UID. */
  31.     private static final long serialVersionUID = 7862466825590075399L;

  32.     /** Latitude of the point (rad). */
  33.     private final double latitude;

  34.     /** Longitude of the point (rad). */
  35.     private final double longitude;

  36.     /** Altitude of the point (m). */
  37.     private final double altitude;

  38.     /** Zenith direction. */
  39.     private transient Vector3D zenith;

  40.     /** Nadir direction. */
  41.     private transient Vector3D nadir;

  42.     /** North direction. */
  43.     private transient Vector3D north;

  44.     /** South direction. */
  45.     private transient Vector3D south;

  46.     /** East direction. */
  47.     private transient Vector3D east;

  48.     /** West direction. */
  49.     private transient Vector3D west;

  50.     /**
  51.      * Build a new instance. The angular coordinates will be normalized so that
  52.      * the latitude is between &pm;&pi;/2 and the longitude is between &pm;&pi;.
  53.      *
  54.      * @param latitude
  55.      *            of the point
  56.      * @param longitude
  57.      *            longitude of the point
  58.      * @param altitude
  59.      *            altitude of the point
  60.      */
  61.     public GeodeticPoint(final double latitude, final double longitude,
  62.                          final double altitude) {
  63.         double lat = MathUtils.normalizeAngle(latitude, FastMath.PI / 2);
  64.         double lon = MathUtils.normalizeAngle(longitude, 0);
  65.         if (lat > FastMath.PI / 2.0) {
  66.             // latitude is beyond the pole -> add 180 to longitude
  67.             lat = FastMath.PI - lat;
  68.             lon = MathUtils.normalizeAngle(longitude + FastMath.PI, 0);

  69.         }
  70.         this.latitude = lat;
  71.         this.longitude = lon;
  72.         this.altitude  = altitude;
  73.     }

  74.     /** Get the latitude.
  75.      * @return latitude, an angular value in the range [-&pi;/2, &pi;/2]
  76.      */
  77.     public double getLatitude() {
  78.         return latitude;
  79.     }

  80.     /** Get the longitude.
  81.      * @return longitude, an angular value in the range [-&pi;, &pi;]
  82.      */
  83.     public double getLongitude() {
  84.         return longitude;
  85.     }

  86.     /** Get the altitude.
  87.      * @return altitude
  88.      */
  89.     public double getAltitude() {
  90.         return altitude;
  91.     }

  92.     /** Get the direction above the point, expressed in parent shape frame.
  93.      * <p>The zenith direction is defined as the normal to local horizontal plane.</p>
  94.      * @return unit vector in the zenith direction
  95.      * @see #getNadir()
  96.      */
  97.     public Vector3D getZenith() {
  98.         if (zenith == null) {
  99.             final double cosLat = FastMath.cos(latitude);
  100.             final double sinLat = FastMath.sin(latitude);
  101.             final double cosLon = FastMath.cos(longitude);
  102.             final double sinLon = FastMath.sin(longitude);
  103.             zenith = new Vector3D(cosLon * cosLat, sinLon * cosLat, sinLat);
  104.         }
  105.         return zenith;
  106.     }

  107.     /** Get the direction below the point, expressed in parent shape frame.
  108.      * <p>The nadir direction is the opposite of zenith direction.</p>
  109.      * @return unit vector in the nadir direction
  110.      * @see #getZenith()
  111.      */
  112.     public Vector3D getNadir() {
  113.         if (nadir == null) {
  114.             nadir = getZenith().negate();
  115.         }
  116.         return nadir;
  117.     }

  118.     /** Get the direction to the north of point, expressed in parent shape frame.
  119.      * <p>The north direction is defined in the horizontal plane
  120.      * (normal to zenith direction) and following the local meridian.</p>
  121.      * @return unit vector in the north direction
  122.      * @see #getSouth()
  123.      */
  124.     public Vector3D getNorth() {
  125.         if (north == null) {
  126.             final double cosLat = FastMath.cos(latitude);
  127.             final double sinLat = FastMath.sin(latitude);
  128.             final double cosLon = FastMath.cos(longitude);
  129.             final double sinLon = FastMath.sin(longitude);
  130.             north = new Vector3D(-cosLon * sinLat, -sinLon * sinLat, cosLat);
  131.         }
  132.         return north;
  133.     }

  134.     /** Get the direction to the south of point, expressed in parent shape frame.
  135.      * <p>The south direction is the opposite of north direction.</p>
  136.      * @return unit vector in the south direction
  137.      * @see #getNorth()
  138.      */
  139.     public Vector3D getSouth() {
  140.         if (south == null) {
  141.             south = getNorth().negate();
  142.         }
  143.         return south;
  144.     }

  145.     /** Get the direction to the east of point, expressed in parent shape frame.
  146.      * <p>The east direction is defined in the horizontal plane
  147.      * in order to complete direct triangle (east, north, zenith).</p>
  148.      * @return unit vector in the east direction
  149.      * @see #getWest()
  150.      */
  151.     public Vector3D getEast() {
  152.         if (east == null) {
  153.             east = new Vector3D(-FastMath.sin(longitude), FastMath.cos(longitude), 0);
  154.         }
  155.         return east;
  156.     }

  157.     /** Get the direction to the west of point, expressed in parent shape frame.
  158.      * <p>The west direction is the opposite of east direction.</p>
  159.      * @return unit vector in the west direction
  160.      * @see #getEast()
  161.      */
  162.     public Vector3D getWest() {
  163.         if (west == null) {
  164.             west = getEast().negate();
  165.         }
  166.         return west;
  167.     }

  168.     @Override
  169.     public boolean equals(final Object object) {
  170.         if (object instanceof GeodeticPoint) {
  171.             final GeodeticPoint other = (GeodeticPoint) object;
  172.             return this.getLatitude() == other.getLatitude() &&
  173.                    this.getLongitude() == other.getLongitude() &&
  174.                    this.getAltitude() == other.getAltitude();
  175.         }
  176.         return false;
  177.     }

  178.     @Override
  179.     public int hashCode() {
  180.         return new Double(this.getLatitude()).hashCode() ^
  181.                new Double(this.getLongitude()).hashCode() ^
  182.                new Double(this.getAltitude()).hashCode();
  183.     }

  184.     @Override
  185.     public String toString() {
  186.         final NumberFormat format = CompositeFormat.getDefaultNumberFormat();
  187.         return "{lat: " +
  188.                format.format(FastMath.toDegrees(this.getLatitude())) +
  189.                " deg, lon: " +
  190.                format.format(FastMath.toDegrees(this.getLongitude())) +
  191.                " deg, alt: " +
  192.                format.format(this.getAltitude()) +
  193.                "}";
  194.     }
  195. }