@@ -71,7 +71,7 @@ public static Point fromDeg(final double latDeg, final double lonDeg) {
7171 */
7272 public double getLatDeg () {
7373 assert defined ;
74- return latDeg ;
74+ return ( lat32 / MICRODEG_TO_DEG_FACTOR ) + ( fraclat / MICROLAT_MAX_PRECISION_FACTOR ) ;
7575 }
7676
7777 /**
@@ -81,7 +81,7 @@ public double getLatDeg() {
8181 */
8282 public double getLonDeg () {
8383 assert defined ;
84- return lonDeg ;
84+ return ( lon32 / MICRODEG_TO_DEG_FACTOR ) + ( fraclon / MICROLON_MAX_PRECISION_FACTOR ) ;
8585 }
8686
8787
@@ -90,14 +90,14 @@ public double getLonDeg() {
9090 */
9191 public double LonFractions () {
9292 assert defined ;
93- return 0 ;
93+ return fraclon ;
9494 }
9595 /**
9696 * Returns "fractions", which is a whole number of 1/MICROLAT_MAX_PRECISION_FACTORth degrees versus the millionths of degrees
9797 */
9898 public double LatFractions () {
9999 assert defined ;
100- return 0 ;
100+ return fraclat ;
101101 }
102102
103103
@@ -146,22 +146,19 @@ public static double distanceInMeters(@Nonnull final Point p1, @Nonnull final Po
146146 checkNonnull ("p1" , p1 );
147147 checkNonnull ("p2" , p2 );
148148
149- final Point from ;
150- final Point to ;
151- if (p1 .lonDeg <= p2 .lonDeg ) {
152- from = p1 ;
153- to = p2 ;
154- } else {
155- from = p2 ;
156- to = p1 ;
157- }
149+ final double latDeg1 = p1 .getLatDeg ();
150+ final double latDeg2 = p2 .getLatDeg ();
151+ double lonDeg1 = p1 .getLonDeg ();
152+ double lonDeg2 = p2 .getLonDeg ();
153+
154+ if (lonDeg1 < 0 && lonDeg2 > 1 ) { lonDeg1 += 360 ; }
155+ if (lonDeg2 < 0 && lonDeg1 > 1 ) { lonDeg2 += 360 ; }
158156
159157 // Calculate mid point of 2 latitudes.
160- final double avgLat = from . latDeg + (( to . latDeg - from . latDeg ) / 2.0 ) ;
158+ final double avgLat = ( p1 . getLatDeg () + p2 . getLatDeg ()) / 2.0 ;
161159
162- final double deltaLonDeg360 = Math .abs (to .lonDeg - from .lonDeg );
163- final double deltaLonDeg = ((deltaLonDeg360 <= 180.0 ) ? deltaLonDeg360 : (360.0 - deltaLonDeg360 ));
164- final double deltaLatDeg = Math .abs (to .latDeg - from .latDeg );
160+ final double deltaLatDeg = latDeg1 - latDeg2 ;
161+ final double deltaLonDeg = lonDeg1 - lonDeg2 ;
165162
166163 // Meters per longitude is fixed; per latitude requires * cos(avg(lat)).
167164 final double deltaXMeters = degreesLonToMetersAtLat (deltaLonDeg , avgLat );
@@ -186,13 +183,13 @@ public static double metersToDegreesLonAtLat(final double eastMeters, final doub
186183 @ Nonnull
187184 @ Override
188185 public String toString () {
189- return defined ? ("(" + latDeg + ", " + lonDeg + ')' ) : "undefined" ;
186+ return defined ? ("(" + getLatDeg () + ", " + getLonDeg () + ')' ) : "undefined" ;
190187 }
191188
192189 @ SuppressWarnings ("NonFinalFieldReferencedInHashCode" )
193190 @ Override
194191 public int hashCode () {
195- return Arrays .hashCode (new Object []{latDeg , lonDeg , defined });
192+ return Arrays .hashCode (new Object []{getLatDeg (), getLonDeg () , defined });
196193 }
197194
198195 @ SuppressWarnings ("NonFinalFieldReferenceInEquals" )
@@ -205,16 +202,20 @@ public boolean equals(final Object obj) {
205202 return false ;
206203 }
207204 final Point that = (Point ) obj ;
208- return (Double .compare (this .latDeg , that .latDeg ) == 0 ) &&
209- (Double .compare (this .lonDeg , that .lonDeg ) == 0 ) &&
210- (this .defined == that .defined );
205+ return (this .lat32 == that .lat32 ) &&
206+ (this .lon32 == that .lon32 ) &&
207+ (Double .compare (this .fraclat , that .fraclat ) == 0 ) &&
208+ (Double .compare (this .fraclon , that .fraclon ) == 0 ) &&
209+ (this .defined == that .defined );
211210 }
212211
213212 /**
214213 * Private data.
215214 */
216- private double latDeg ; // Latitude, normal range -90..90, but not enforced.
217- private double lonDeg ; // Longitude, normal range -180..180, but not enforced.
215+ private int lat32 ; // whole nr of MICRODEG_TO_DEG_FACTOR
216+ private int lon32 ; // whole nr of MICRODEG_TO_DEG_FACTOR
217+ private double fraclat ; // whole nr of MICROLAT_MAX_PRECISION_FACTOR, relative to lat32
218+ private double fraclon ; // whole nr of MICROLON_MAX_PRECISION_FACTOR, relative to lon32
218219
219220 /**
220221 * Points can be "undefined" within the mapcode implementation, but never outside of that.
@@ -227,22 +228,30 @@ public boolean equals(final Object obj) {
227228 * Private constructors.
228229 */
229230 private Point () {
230- latDeg = Double .NaN ;
231- lonDeg = Double .NaN ;
232231 defined = false ;
233232 }
234233
235234 private Point (final double latDeg , final double lonDeg , final boolean wrap ) {
236- if (wrap ) {
237- this .latDeg = mapToLat (latDeg );
238- this .lonDeg = mapToLon (lonDeg );
239- assert (LON_DEG_MIN <= this .lonDeg ) && (this .lonDeg <= LON_DEG_MAX ) : "lon [-180..180]: " + this .lonDeg ;
240- assert (LAT_DEG_MIN <= this .latDeg ) && (this .latDeg <= LAT_DEG_MAX ) : "lat [-90..90]: " + this .latDeg ;
241- } else {
242- this .latDeg = latDeg ;
243- this .lonDeg = lonDeg ;
244- }
245- this .defined = true ;
235+
236+ double lat = latDeg + 90 ;
237+ if (lat < 0 ) { lat = 0 ; } else if (lat > 180 ) { lat = 180 ; }
238+ // lat now [0..180]
239+ lat *= MICROLAT_MAX_PRECISION_FACTOR ;
240+ fraclat = Math .floor (lat + 0.1 );
241+ double f = fraclat / MAX_PRECISION_FACTOR ;
242+ lat32 = (int ) f ;
243+ fraclat -= ((double ) lat32 * MAX_PRECISION_FACTOR );
244+ lat32 -= 90000000 ;
245+
246+ double lon = lonDeg - (360.0 * Math .floor (lonDeg / 360 )); // lon now in [0..360>
247+ lon *= MICROLON_MAX_PRECISION_FACTOR ;
248+ fraclon = Math .floor (lon + 0.1 );
249+ f = fraclon / FRACLON_PRECISION_FACTOR ;
250+ lon32 = (int )f ;
251+ fraclon -= ((double ) lon32 * FRACLON_PRECISION_FACTOR );
252+ if (lon32 >= 180000000 ) { lon32 -= 360000000 ; }
253+
254+ defined = true ;
246255 }
247256
248257 /**
@@ -255,7 +264,13 @@ private Point(final double latDeg, final double lonDeg, final boolean wrap) {
255264
256265 @ Nonnull
257266 static Point fromMicroDeg (final int latMicroDeg , final int lonMicroDeg ) {
258- return new Point (microDegToDeg (latMicroDeg ), microDegToDeg (lonMicroDeg ), false );
267+ Point p = new Point ();
268+ p .lat32 = latMicroDeg ;
269+ p .lon32 = lonMicroDeg ;
270+ p .fraclat = 0 ;
271+ p .fraclon = 0 ;
272+ p .defined = true ;
273+ return p ;
259274 }
260275
261276 /**
@@ -265,7 +280,7 @@ static Point fromMicroDeg(final int latMicroDeg, final int lonMicroDeg) {
265280 */
266281 int getLatMicroDeg () {
267282 assert defined ;
268- return degToMicroDeg ( latDeg ) ;
283+ return lat32 ;
269284 }
270285
271286 /**
@@ -275,12 +290,12 @@ int getLatMicroDeg() {
275290 */
276291 int getLonMicroDeg () {
277292 assert defined ;
278- return degToMicroDeg ( lonDeg ) ;
293+ return lon32 ;
279294 }
280295
281296 static int degToMicroDeg (final double deg ) {
282297 //noinspection NumericCastThatLosesPrecision
283- return (int ) Math .round (deg * MICRODEG_TO_DEG_FACTOR );
298+ return (int ) Math .floor (deg * MICRODEG_TO_DEG_FACTOR );
284299 }
285300
286301 static double microDegToDeg (final int microDeg ) {
@@ -290,38 +305,18 @@ static double microDegToDeg(final int microDeg) {
290305 @ Nonnull
291306 Point wrap () {
292307 if (defined ) {
293- this .latDeg = mapToLat (latDeg );
294- this .lonDeg = mapToLon (lonDeg );
308+ // Cut latitude to [-90, 90].
309+ if (lat32 < -90000000 ) { lat32 = -90000000 ; fraclat =0 ; }
310+ if (lat32 > 90000000 ) { lat32 = 90000000 ; fraclat =0 ; }
311+ // Map longitude to [-180, 180). Values outside this range are wrapped to this range.
312+ if (lon32 < -180000000 || lon32 >= 180000000 ) {
313+ lon32 -= 360 * (lon32 / 360 ); // [0..360)
314+ if (lon32 >= 180000000 ) { lon32 -= 360000000 ; } // [-180,180)
315+ }
295316 }
296317 return this ;
297318 }
298319
299- /**
300- * Map a longitude to [-90, 90]. Values outside this range are limited to this range.
301- *
302- * @param value Latitude, any range.
303- * @return Limited to [-90, 90].
304- */
305- static double mapToLat (final double value ) {
306- return (value < -90.0 ) ? -90.0 : ((value > 90.0 ) ? 90.0 : value );
307- }
308-
309- /**
310- * Map a longitude to [-180, 180). Values outside this range are wrapped to this range.
311- *
312- * @param value Longitude, any range.
313- * @return Mapped to [-180, 180).
314- */
315- static double mapToLon (final double value ) {
316- if ( value > -180 && value < 180 )
317- return value ; // already in range
318- double lon = (((((value >= 0 ) ? value : -value ) + 180 ) % 360 ) - 180 ) * ((value >= 0 ) ? 1.0 : -1.0 );
319- if (Double .compare (lon , 180.0 ) == 0 ) {
320- return -180 ;
321- }
322- return lon ;
323- }
324-
325320 /**
326321 * Create an undefined points. No latitude or longitude can be obtained from it.
327322 * Only within the mapcode implementation points can be undefined, so this methods is package private.
@@ -338,8 +333,6 @@ static Point undefined() {
338333 * Only within the mapcode implementation points can be undefined, so this methods is package private.
339334 */
340335 void setUndefined () {
341- latDeg = Double .NaN ;
342- lonDeg = Double .NaN ;
343336 defined = false ;
344337 }
345338
0 commit comments