2 Copyright (C) 2001, 2006 United States Government
3 as represented by the Administrator of the
4 National Aeronautics and Space Administration.
7 package gov
.nasa
.worldwind
.geom
;
9 import gov
.nasa
.worldwind
.*;
12 * Represents a point on the two-dimensional surface of a globe. Latitude is the degrees North and ranges between [-90,
13 * 90], while longitude refers to degrees East, and ranges between (-180, 180].
15 * Instances of <code>LatLon</code> are immutable.
18 * @version $Id: LatLon.java 2152 2007-06-26 20:34:22Z tgaskins $
22 private final Angle latitude
;
23 private final Angle longitude
;
26 * Factor method for obtaining a new <code>LatLon</code> from two angles expressed in radians.
28 * @param latitude in radians
29 * @param longitude in radians
30 * @return a new <code>LatLon</code> from the given angles, which are expressed as radians
32 public static LatLon
fromRadians(double latitude
, double longitude
)
34 return new LatLon(Math
.toDegrees(latitude
), Math
.toDegrees(longitude
));
38 * Factory method for obtaining a new <code>LatLon</code> from two angles expressed in degrees.
40 * @param latitude in degrees
41 * @param longitude in degrees
42 * @return a new <code>LatLon</code> from the given angles, which are expressed as degrees
44 public static LatLon
fromDegrees(double latitude
, double longitude
)
46 return new LatLon(latitude
, longitude
);
49 private LatLon(double latitude
, double longitude
)
51 this.latitude
= Angle
.fromDegrees(latitude
);
52 this.longitude
= Angle
.fromDegrees(longitude
);
56 * Contructs a new <code>LatLon</code> from two angles. Neither angle may be null.
60 * @throws IllegalArgumentException if <code>latitude</code> or <code>longitude</code> is null
62 public LatLon(Angle latitude
, Angle longitude
)
64 if (latitude
== null || longitude
== null)
66 String message
= WorldWind
.retrieveErrMsg("nullValue.LatitudeOrLongitudeIsNull");
67 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
68 throw new IllegalArgumentException(message
);
71 this.latitude
= latitude
;
72 this.longitude
= longitude
;
76 * Obtains the latitude of this <code>LatLon</code>.
78 * @return this <code>LatLon</code>'s latitude
80 public final Angle
getLatitude()
86 * Obtains the longitude of this <code>LatLon</code>.
88 * @return this <code>LatLon</code>'s longitude
90 public final Angle
getLongitude()
92 return this.longitude
;
95 public static LatLon
interpolate(double t
, LatLon begin
, LatLon end
)
97 if (begin
== null || end
== null)
99 String message
= WorldWind
.retrieveErrMsg("nullValue.LatitudeOrLongitudeIsNull");
100 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
101 throw new IllegalArgumentException(message
);
108 Quaternion beginQuat
= Quaternion
.EulerToQuaternion(begin
.getLongitude().getRadians(),
109 begin
.getLatitude().getRadians(), 0);
110 Quaternion endQuat
= Quaternion
.EulerToQuaternion(end
.getLongitude().getRadians(),
111 end
.getLatitude().getRadians(), 0);
112 Quaternion q
= Quaternion
.Slerp(beginQuat
, endQuat
, t
);
113 Vec4 v
= Quaternion
.QuaternionToEuler(q
);
114 if (Double
.isNaN(v
.x
) || Double
.isNaN(v
.y
))
116 return LatLon
.fromRadians(v
.y
, v
.x
);
120 * Computes the great circle angular distance between two locations
122 * @param begin LatLon of the first location
123 * @param end LatLon of the second location
124 * @return the angular distance between the two locations
126 public static Angle
sphericalDistance(LatLon begin
, LatLon end
)
128 double radLatA
= begin
.getLatitude().radians
;
129 double radLatB
= end
.getLatitude().radians
;
130 double radLonA
= begin
.getLongitude().radians
;
131 double radLonB
= end
.getLongitude().radians
;
132 return Angle
.fromRadians(
133 Math
.acos(Math
.cos(radLatA
) * Math
.cos(radLatB
) * Math
.cos(radLonA
- radLonB
)
134 + Math
.sin(radLatA
) * Math
.sin(radLatB
)));
137 public LatLon
add(LatLon that
)
141 String msg
= WorldWind
.retrieveErrMsg("nullValue.AngleIsNull");
142 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, msg
);
143 throw new IllegalArgumentException(msg
);
146 Angle lat
= Angle
.normalizedLatitude(this.latitude
.add(that
.latitude
));
147 Angle lon
= Angle
.normalizedLongitude(this.longitude
.add(that
.longitude
));
149 return new LatLon(lat
, lon
);
152 public LatLon
subtract(LatLon that
)
156 String msg
= WorldWind
.retrieveErrMsg("nullValue.AngleIsNull");
157 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, msg
);
158 throw new IllegalArgumentException(msg
);
161 Angle lat
= Angle
.normalizedLatitude(this.latitude
.subtract(that
.latitude
));
162 Angle lon
= Angle
.normalizedLongitude(this.longitude
.subtract(that
.longitude
));
164 return new LatLon(lat
, lon
);
167 public LatLon
add(Position that
)
171 String msg
= WorldWind
.retrieveErrMsg("nullValue.AngleIsNull");
172 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, msg
);
173 throw new IllegalArgumentException(msg
);
176 Angle lat
= Angle
.normalizedLatitude(this.latitude
.add(that
.getLatitude()));
177 Angle lon
= Angle
.normalizedLongitude(this.longitude
.add(that
.getLongitude()));
179 return new LatLon(lat
, lon
);
182 public LatLon
subtract(Position that
)
186 String msg
= WorldWind
.retrieveErrMsg("nullValue.AngleIsNull");
187 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, msg
);
188 throw new IllegalArgumentException(msg
);
191 Angle lat
= Angle
.normalizedLatitude(this.latitude
.subtract(that
.getLatitude()));
192 Angle lon
= Angle
.normalizedLongitude(this.longitude
.subtract(that
.getLongitude()));
194 return new LatLon(lat
, lon
);
197 public static boolean positionsCrossLongitudeBoundary(Iterable
<LatLon
> positions
)
199 if (positions
== null)
201 String msg
= WorldWind
.retrieveErrMsg("nullValue.PositionsListIsNull");
202 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, msg
);
203 throw new IllegalArgumentException(msg
);
207 for (LatLon posNext
: positions
)
211 // A segment cross the line if end pos have different longitude signs
212 // and are more than 180 degress longitude apart
213 if (Math
.signum(pos
.getLongitude().degrees
) != Math
.signum(posNext
.getLongitude().degrees
))
215 if (Math
.abs(pos
.getLongitude().degrees
- posNext
.getLongitude().degrees
) > 180)
226 public String
toString()
228 return "(" + this.latitude
.toString() + ", " + this.longitude
.toString() + ")";
232 public boolean equals(Object o
)
236 if (o
== null || getClass() != o
.getClass())
239 final gov
.nasa
.worldwind
.geom
.LatLon latLon
= (gov
.nasa
.worldwind
.geom
.LatLon
) o
;
241 if (!latitude
.equals(latLon
.latitude
))
243 //noinspection RedundantIfStatement
244 if (!longitude
.equals(latLon
.longitude
))
251 public int hashCode()
254 result
= latitude
.hashCode();
255 result
= 29 * result
+ longitude
.hashCode();