1 /* Copyright 2002-2020 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.bodies;
18
19 import java.io.Serializable;
20 import java.text.NumberFormat;
21
22 import org.hipparchus.geometry.euclidean.threed.Vector3D;
23 import org.hipparchus.util.CompositeFormat;
24 import org.hipparchus.util.FastMath;
25 import org.hipparchus.util.MathUtils;
26
27 /** Point location relative to a 2D body surface.
28 * <p>Instance of this class are guaranteed to be immutable.</p>
29 * @see BodyShape
30 * @see FieldGeodeticPoint
31 * @author Luc Maisonobe
32 */
33 public class GeodeticPoint implements Serializable {
34
35 /** North pole.
36 * @since 10.0
37 */
38 public static final GeodeticPointticPoint">GeodeticPoint NORTH_POLE = new GeodeticPoint(+0.5 * FastMath.PI, 0.0, 0.0);
39
40 /** South pole.
41 * @since 10.0
42 */
43 public static final GeodeticPointticPoint">GeodeticPoint SOUTH_POLE = new GeodeticPoint(-0.5 * FastMath.PI, 0.0, 0.0);
44
45 /** Serializable UID. */
46 private static final long serialVersionUID = 7862466825590075399L;
47
48 /** Latitude of the point (rad). */
49 private final double latitude;
50
51 /** Longitude of the point (rad). */
52 private final double longitude;
53
54 /** Altitude of the point (m). */
55 private final double altitude;
56
57 /** Zenith direction. */
58 private transient Vector3D zenith;
59
60 /** Nadir direction. */
61 private transient Vector3D nadir;
62
63 /** North direction. */
64 private transient Vector3D north;
65
66 /** South direction. */
67 private transient Vector3D south;
68
69 /** East direction. */
70 private transient Vector3D east;
71
72 /** West direction. */
73 private transient Vector3D west;
74
75 /**
76 * Build a new instance. The angular coordinates will be normalized so that
77 * the latitude is between ±π/2 and the longitude is between ±π.
78 *
79 * @param latitude latitude of the point (rad)
80 * @param longitude longitude of the point (rad)
81 * @param altitude altitude of the point (m)
82 */
83 public GeodeticPoint(final double latitude, final double longitude,
84 final double altitude) {
85 double lat = MathUtils.normalizeAngle(latitude, FastMath.PI / 2);
86 double lon = MathUtils.normalizeAngle(longitude, 0);
87 if (lat > FastMath.PI / 2.0) {
88 // latitude is beyond the pole -> add 180 to longitude
89 lat = FastMath.PI - lat;
90 lon = MathUtils.normalizeAngle(longitude + FastMath.PI, 0);
91 }
92 this.latitude = lat;
93 this.longitude = lon;
94 this.altitude = altitude;
95 }
96
97 /** Get the latitude.
98 * @return latitude, an angular value in the range [-π/2, π/2]
99 */
100 public double getLatitude() {
101 return latitude;
102 }
103
104 /** Get the longitude.
105 * @return longitude, an angular value in the range [-π, π]
106 */
107 public double getLongitude() {
108 return longitude;
109 }
110
111 /** Get the altitude.
112 * @return altitude
113 */
114 public double getAltitude() {
115 return altitude;
116 }
117
118 /** Get the direction above the point, expressed in parent shape frame.
119 * <p>The zenith direction is defined as the normal to local horizontal plane.</p>
120 * @return unit vector in the zenith direction
121 * @see #getNadir()
122 */
123 public Vector3D getZenith() {
124 if (zenith == null) {
125 final double cosLat = FastMath.cos(latitude);
126 final double sinLat = FastMath.sin(latitude);
127 final double cosLon = FastMath.cos(longitude);
128 final double sinLon = FastMath.sin(longitude);
129 zenith = new Vector3D(cosLon * cosLat, sinLon * cosLat, sinLat);
130 }
131 return zenith;
132 }
133
134 /** Get the direction below the point, expressed in parent shape frame.
135 * <p>The nadir direction is the opposite of zenith direction.</p>
136 * @return unit vector in the nadir direction
137 * @see #getZenith()
138 */
139 public Vector3D getNadir() {
140 if (nadir == null) {
141 nadir = getZenith().negate();
142 }
143 return nadir;
144 }
145
146 /** Get the direction to the north of point, expressed in parent shape frame.
147 * <p>The north direction is defined in the horizontal plane
148 * (normal to zenith direction) and following the local meridian.</p>
149 * @return unit vector in the north direction
150 * @see #getSouth()
151 */
152 public Vector3D getNorth() {
153 if (north == null) {
154 final double cosLat = FastMath.cos(latitude);
155 final double sinLat = FastMath.sin(latitude);
156 final double cosLon = FastMath.cos(longitude);
157 final double sinLon = FastMath.sin(longitude);
158 north = new Vector3D(-cosLon * sinLat, -sinLon * sinLat, cosLat);
159 }
160 return north;
161 }
162
163 /** Get the direction to the south of point, expressed in parent shape frame.
164 * <p>The south direction is the opposite of north direction.</p>
165 * @return unit vector in the south direction
166 * @see #getNorth()
167 */
168 public Vector3D getSouth() {
169 if (south == null) {
170 south = getNorth().negate();
171 }
172 return south;
173 }
174
175 /** Get the direction to the east of point, expressed in parent shape frame.
176 * <p>The east direction is defined in the horizontal plane
177 * in order to complete direct triangle (east, north, zenith).</p>
178 * @return unit vector in the east direction
179 * @see #getWest()
180 */
181 public Vector3D getEast() {
182 if (east == null) {
183 east = new Vector3D(-FastMath.sin(longitude), FastMath.cos(longitude), 0);
184 }
185 return east;
186 }
187
188 /** Get the direction to the west of point, expressed in parent shape frame.
189 * <p>The west direction is the opposite of east direction.</p>
190 * @return unit vector in the west direction
191 * @see #getEast()
192 */
193 public Vector3D getWest() {
194 if (west == null) {
195 west = getEast().negate();
196 }
197 return west;
198 }
199
200 @Override
201 public boolean equals(final Object object) {
202 if (object instanceof GeodeticPoint) {
203 final GeodeticPoint../org/orekit/bodies/GeodeticPoint.html#GeodeticPoint">GeodeticPoint other = (GeodeticPoint) object;
204 return this.getLatitude() == other.getLatitude() &&
205 this.getLongitude() == other.getLongitude() &&
206 this.getAltitude() == other.getAltitude();
207 }
208 return false;
209 }
210
211 @Override
212 public int hashCode() {
213 return Double.valueOf(this.getLatitude()).hashCode() ^
214 Double.valueOf(this.getLongitude()).hashCode() ^
215 Double.valueOf(this.getAltitude()).hashCode();
216 }
217
218 @Override
219 public String toString() {
220 final NumberFormat format = CompositeFormat.getDefaultNumberFormat();
221 return "{lat: " +
222 format.format(FastMath.toDegrees(this.getLatitude())) +
223 " deg, lon: " +
224 format.format(FastMath.toDegrees(this.getLongitude())) +
225 " deg, alt: " +
226 format.format(this.getAltitude()) +
227 "}";
228 }
229 }