aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTorsten Keil <github@torsten-keil.net>2012-02-17 19:17:52 +0100
committerBananeweizen <Bananeweizen@gmx.de>2012-02-17 19:17:52 +0100
commit876bf8c1ae2f5de62fd37c65a896417e9db43f84 (patch)
tree303d2769910ad3733c86ae4089b5e99d61ac4025
parent5241b730a8a3d3650b9b6f0352f74c090e258afe (diff)
downloadcgeo-876bf8c1ae2f5de62fd37c65a896417e9db43f84.zip
cgeo-876bf8c1ae2f5de62fd37c65a896417e9db43f84.tar.gz
cgeo-876bf8c1ae2f5de62fd37c65a896417e9db43f84.tar.bz2
Implementation for issue #1120
- see ticket for more details Conflicts: main/src/cgeo/geocaching/cgeowaypointadd.java
-rw-r--r--main/src/cgeo/geocaching/cgeocoords.java130
-rw-r--r--main/src/cgeo/geocaching/cgeowaypointadd.java18
-rw-r--r--main/src/cgeo/geocaching/geopoint/Geopoint.java219
-rw-r--r--main/src/cgeo/geocaching/geopoint/GeopointFormatter.java38
-rw-r--r--tests/src/cgeo/geocaching/geopoint/GeopointTest.java180
5 files changed, 466 insertions, 119 deletions
diff --git a/main/src/cgeo/geocaching/cgeocoords.java b/main/src/cgeo/geocaching/cgeocoords.java
index 3aadf05..b4868ce 100644
--- a/main/src/cgeo/geocaching/cgeocoords.java
+++ b/main/src/cgeo/geocaching/cgeocoords.java
@@ -5,6 +5,10 @@ import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.geopoint.Geopoint.DDD;
+import cgeo.geocaching.geopoint.Geopoint.DMM;
+import cgeo.geocaching.geopoint.Geopoint.DMS;
+import cgeo.geocaching.geopoint.Geopoint.Direction;
import cgeo.geocaching.geopoint.GeopointFormatter;
import cgeo.geocaching.geopoint.GeopointParser.ParseException;
@@ -147,41 +151,10 @@ public class cgeocoords extends Dialog {
if (gp == null) {
return;
}
- double lat = 0.0;
- if (gp.getLatitude() < 0) {
- bLat.setText("S");
- } else {
- bLat.setText("N");
- }
-
- lat = Math.abs(gp.getLatitude());
-
- double lon = 0.0;
- if (gp.getLongitude() < 0) {
- bLon.setText("W");
- } else {
- bLon.setText("E");
- }
-
- lon = Math.abs(gp.getLongitude());
-
- final int latDeg = (int) Math.floor(lat);
- final int latDegFrac = (int) Math.round((lat - latDeg) * 100000);
- final int latMin = (int) Math.floor((lat - latDeg) * 60);
- final int latMinFrac = (int) Math.round(((lat - latDeg) * 60 - latMin) * 1000);
-
- final int latSec = (int) Math.floor(((lat - latDeg) * 60 - latMin) * 60);
- final int latSecFrac = (int) Math.round((((lat - latDeg) * 60 - latMin) * 60 - latSec) * 1000);
-
- final int lonDeg = (int) Math.floor(lon);
- final int lonDegFrac = (int) Math.round((lon - lonDeg) * 100000);
-
- final int lonMin = (int) Math.floor((lon - lonDeg) * 60);
- final int lonMinFrac = (int) Math.round(((lon - lonDeg) * 60 - lonMin) * 1000);
-
- final int lonSec = (int) Math.floor(((lon - lonDeg) * 60 - lonMin) * 60);
- final int lonSecFrac = (int) Math.round((((lon - lonDeg) * 60 - lonMin) * 60 - lonSec) * 1000);
+ Direction dir = gp.asDirection();
+ bLat.setText(String.valueOf(dir.latDir));
+ bLon.setText(String.valueOf(dir.lonDir));
switch (currentFormat) {
case Plain:
@@ -207,10 +180,11 @@ public class cgeocoords extends Dialog {
tLatSep2.setText("°");
tLonSep2.setText("°");
- eLatDeg.setText(addZeros(latDeg, 2));
- eLatMin.setText(addZeros(latDegFrac, 5));
- eLonDeg.setText(addZeros(lonDeg, 3));
- eLonMin.setText(addZeros(lonDegFrac, 5));
+ DDD ddd = gp.asDDD();
+ eLatDeg.setText(addZeros(ddd.latDeg, 2));
+ eLatMin.setText(addZeros(ddd.latDegFrac, 5));
+ eLonDeg.setText(addZeros(ddd.lonDeg, 3));
+ eLonMin.setText(addZeros(ddd.lonDegFrac, 5));
break;
case Min: // DDD° MM.MMM
findViewById(R.id.coordTable).setVisibility(View.VISIBLE);
@@ -230,12 +204,13 @@ public class cgeocoords extends Dialog {
tLatSep3.setText("'");
tLonSep3.setText("'");
- eLatDeg.setText(addZeros(latDeg, 2));
- eLatMin.setText(addZeros(latMin, 2));
- eLatSec.setText(addZeros(latMinFrac, 3));
- eLonDeg.setText(addZeros(lonDeg, 3));
- eLonMin.setText(addZeros(lonMin, 2));
- eLonSec.setText(addZeros(lonMinFrac, 3));
+ DMM dmm = gp.asDMM();
+ eLatDeg.setText(addZeros(dmm.latDeg, 2));
+ eLatMin.setText(addZeros(dmm.latMin, 2));
+ eLatSec.setText(addZeros(dmm.latMinFrac, 3));
+ eLonDeg.setText(addZeros(dmm.lonDeg, 3));
+ eLonMin.setText(addZeros(dmm.lonMin, 2));
+ eLonSec.setText(addZeros(dmm.lonMinFrac, 3));
break;
case Sec: // DDD° MM SS.SSS
findViewById(R.id.coordTable).setVisibility(View.VISIBLE);
@@ -255,14 +230,15 @@ public class cgeocoords extends Dialog {
tLatSep3.setText(".");
tLonSep3.setText(".");
- eLatDeg.setText(addZeros(latDeg, 2));
- eLatMin.setText(addZeros(latMin, 2));
- eLatSec.setText(addZeros(latSec, 2));
- eLatSub.setText(addZeros(latSecFrac, 3));
- eLonDeg.setText(addZeros(lonDeg, 3));
- eLonMin.setText(addZeros(lonMin, 2));
- eLonSec.setText(addZeros(lonSec, 2));
- eLonSub.setText(addZeros(lonSecFrac, 3));
+ DMS dms = gp.asDMS();
+ eLatDeg.setText(addZeros(dms.latDeg, 2));
+ eLatMin.setText(addZeros(dms.latMin, 2));
+ eLatSec.setText(addZeros(dms.latSec, 2));
+ eLatSub.setText(addZeros(dms.latSecFrac, 3));
+ eLonDeg.setText(addZeros(dms.lonDeg, 3));
+ eLonMin.setText(addZeros(dms.lonMin, 2));
+ eLonSec.setText(addZeros(dms.lonSec, 2));
+ eLonSub.setText(addZeros(dms.lonSecFrac, 3));
break;
}
}
@@ -385,51 +361,35 @@ public class cgeocoords extends Dialog {
return true;
}
- int latDeg = 0, latMin = 0, latSec = 0;
- int lonDeg = 0, lonMin = 0, lonSec = 0;
- double latDegFrac = 0.0, latMinFrac = 0.0, latSecFrac = 0.0;
- double lonDegFrac = 0.0, lonMinFrac = 0.0, lonSecFrac = 0.0;
-
- try {
- latDeg = Integer.parseInt(eLatDeg.getText().toString());
- lonDeg = Integer.parseInt(eLonDeg.getText().toString());
- latDegFrac = Double.parseDouble("0." + eLatMin.getText().toString());
- lonDegFrac = Double.parseDouble("0." + eLonMin.getText().toString());
- latMin = Integer.parseInt(eLatMin.getText().toString());
- lonMin = Integer.parseInt(eLonMin.getText().toString());
- latMinFrac = Double.parseDouble("0." + eLatSec.getText().toString());
- lonMinFrac = Double.parseDouble("0." + eLonSec.getText().toString());
- latSec = Integer.parseInt(eLatSec.getText().toString());
- lonSec = Integer.parseInt(eLonSec.getText().toString());
- latSecFrac = Double.parseDouble("0." + eLatSub.getText().toString());
- lonSecFrac = Double.parseDouble("0." + eLonSub.getText().toString());
-
- } catch (NumberFormatException e) {
- }
-
- double latitude = 0.0;
- double longitude = 0.0;
+ String latDir = bLat.getText().toString();
+ String lonDir = bLon.getText().toString();
+ String latDeg = eLatDeg.getText().toString();
+ String lonDeg = eLonDeg.getText().toString();
+ String latDegFrac = eLatMin.getText().toString();
+ String lonDegFrac = eLonMin.getText().toString();
+ String latMin = eLatMin.getText().toString();
+ String lonMin = eLonMin.getText().toString();
+ String latMinFrac = eLatSec.getText().toString();
+ String lonMinFrac = eLonSec.getText().toString();
+ String latSec = eLatSec.getText().toString();
+ String lonSec = eLonSec.getText().toString();
+ String latSecFrac = eLatSub.getText().toString();
+ String lonSecFrac = eLonSub.getText().toString();
switch (currentFormat) {
case Deg:
- latitude = latDeg + latDegFrac;
- longitude = lonDeg + lonDegFrac;
+ gp = DDD.createGeopoint(latDir, latDeg, latDegFrac, lonDir, lonDeg, lonDegFrac);
break;
case Min:
- latitude = latDeg + latMin / 60.0 + latMinFrac / 60.0;
- longitude = lonDeg + lonMin / 60.0 + lonMinFrac / 60.0;
+ gp = DMM.createGeopoint(latDir, latDeg, latMin, latMinFrac, lonDir, lonDeg, lonMin, lonMinFrac);
break;
case Sec:
- latitude = latDeg + latMin / 60.0 + latSec / 60.0 / 60.0 + latSecFrac / 60.0 / 60.0;
- longitude = lonDeg + lonMin / 60.0 + lonSec / 60.0 / 60.0 + lonSecFrac / 60.0 / 60.0;
+ gp = DMS.createGeopoint(latDir, latDeg, latMin, latSec, latSecFrac, lonDir, lonDeg, lonMin, lonSec, lonSecFrac);
break;
case Plain:
// This case has been handled above
}
- latitude *= (bLat.getText().toString().equalsIgnoreCase("S") ? -1 : 1);
- longitude *= (bLon.getText().toString().equalsIgnoreCase("W") ? -1 : 1);
- gp = new Geopoint(latitude, longitude);
return true;
}
diff --git a/main/src/cgeo/geocaching/cgeowaypointadd.java b/main/src/cgeo/geocaching/cgeowaypointadd.java
index f4ebbe6..2508750 100644
--- a/main/src/cgeo/geocaching/cgeowaypointadd.java
+++ b/main/src/cgeo/geocaching/cgeowaypointadd.java
@@ -37,6 +37,7 @@ public class cgeowaypointadd extends AbstractActivity {
private UpdateLocationCallback geoUpdate = new update();
private ProgressDialog waitDialog = null;
private cgWaypoint waypoint = null;
+ private Geopoint gpTemp = null;
private WaypointType type = WaypointType.OWN;
private String prefix = "OWN";
private String lookup = "---";
@@ -53,11 +54,6 @@ public class cgeowaypointadd extends AbstractActivity {
public void handleMessage(Message msg) {
try {
if (waypoint == null) {
- if (waitDialog != null) {
- waitDialog.dismiss();
- waitDialog = null;
- }
-
id = -1;
} else {
geocode = waypoint.getGeocode();
@@ -74,22 +70,18 @@ public class cgeowaypointadd extends AbstractActivity {
}
((EditText) findViewById(R.id.name)).setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getName())).toString());
((EditText) findViewById(R.id.note)).setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getNote())).toString());
-
- if (waitDialog != null) {
- waitDialog.dismiss();
- waitDialog = null;
- }
}
if (own) {
initializeWaypointTypeSelector();
}
} catch (Exception e) {
+ Log.e(Settings.tag, "cgeowaypointadd.loadWaypointHandler: " + e.toString());
+ } finally {
if (waitDialog != null) {
waitDialog.dismiss();
waitDialog = null;
}
- Log.e(Settings.tag, "cgeowaypointadd.loadWaypointHandler: " + e.toString());
}
}
};
@@ -265,6 +257,8 @@ public class cgeowaypointadd extends AbstractActivity {
Geopoint gp = null;
if (waypoint != null && waypoint.getCoords() != null) {
gp = waypoint.getCoords();
+ } else if (gpTemp != null) {
+ gp = gpTemp;
}
cgCache cache = app.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
cgeocoords coordsDialog = new cgeocoords(cgeowaypointadd.this, cache, gp, geo);
@@ -276,6 +270,8 @@ public class cgeowaypointadd extends AbstractActivity {
((Button) findViewById(R.id.buttonLongitude)).setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE));
if (waypoint != null) {
waypoint.setCoords(gp);
+ } else {
+ gpTemp = gp;
}
}
});
diff --git a/main/src/cgeo/geocaching/geopoint/Geopoint.java b/main/src/cgeo/geocaching/geopoint/Geopoint.java
index 43aef68..65b9ad5 100644
--- a/main/src/cgeo/geocaching/geopoint/Geopoint.java
+++ b/main/src/cgeo/geocaching/geopoint/Geopoint.java
@@ -1,7 +1,12 @@
package cgeo.geocaching.geopoint;
+import org.apache.commons.lang3.StringUtils;
+
import android.location.Location;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
/**
* Abstraction of geographic point.
*/
@@ -14,6 +19,11 @@ public final class Geopoint
private final double latitude;
private final double longitude;
+ private Direction direction;
+ private DDD ddd;
+ private DMM dmm;
+ private DMS dms;
+
/**
* Creates new Geopoint with given latitude and longitude (both degree).
*
@@ -224,7 +234,7 @@ public final class Geopoint
/**
* Returns formatted coordinates with default format.
* Default format is decimalminutes, e.g. N 52° 36.123 E 010° 03.456
- *
+ *
* @return formatted coordinates
*/
@Override
@@ -233,6 +243,213 @@ public final class Geopoint
return format(GeopointFormatter.Format.LAT_LON_DECMINUTE);
}
+ /**
+ * Converts this geopoint to value type Direction.
+ *
+ * @return Direction
+ */
+ public Direction asDirection() {
+ if (direction == null) { // because geopoint is immutable we can "cache" the result
+ direction = new Direction(getLatitude(), getLongitude());
+ }
+ return direction;
+ }
+
+ /**
+ * Converts this geopoint to value type DDD.
+ *
+ * @return
+ */
+ public DDD asDDD() {
+ if (ddd == null) {
+ ddd = new DDD(getLatitude(), getLongitude());
+ }
+ return ddd;
+ }
+
+ /**
+ * Converts this geopoint to value type DMM.
+ *
+ * @return
+ */
+ public DMM asDMM() {
+ if (dmm == null) {
+ dmm = new DMM(getLatitude(), getLongitude());
+ }
+ return dmm;
+ }
+
+ /**
+ * Converts this geopoint to value type DMS.
+ *
+ * @return
+ */
+ public DMS asDMS() {
+ if (dms == null) {
+ dms = new DMS(getLatitude(), getLongitude());
+ }
+ return dms;
+ }
+
+ /* Constant values needed for calculation */
+ private static final double D60 = 60.0d;
+ private static final double D1000 = 1000.0d;
+ private static final double D3600 = 3600.0d;
+ private static final BigDecimal BD_SIXTY = BigDecimal.valueOf(D60);
+ private static final BigDecimal BD_THOUSAND = BigDecimal.valueOf(D1000);
+ private static final BigDecimal BD_ONEHOUNDREDTHOUSAND = BigDecimal.valueOf(100000.0d);
+
+ /**
+ * Value type for the direction.
+ */
+ public static class Direction {
+ /** latitude direction, 'N' or 'S' */
+ public final char latDir;
+ /** longitude direction, 'E' or 'W' */
+ public final char lonDir;
+
+ private Direction(final double latSigned, final double lonSigned) {
+ latDir = latSigned < 0 ? 'S' : 'N';
+ lonDir = lonSigned < 0 ? 'W' : 'E';
+ }
+
+ protected static String addZeros(final int value, final int len) {
+ return StringUtils.leftPad(Integer.toString(value), len, '0');
+ }
+ }
+
+ /**
+ * Value type for the DDD.DDDDD format.
+ */
+ public static final class DDD extends Direction {
+
+ /** latitude degree value */
+ public final int latDeg;
+ /** fractional part of the latitude degree value */
+ public final int latDegFrac;
+
+ public final int lonDeg;
+ public final int lonDegFrac;
+
+ private DDD(final double latSigned, final double lonSigned) {
+ super(latSigned, lonSigned);
+ BigDecimal bdLat = BigDecimal.valueOf(latSigned).abs();
+ latDeg = bdLat.intValue();
+ BigDecimal bdLatFrac = bdLat.subtract(BigDecimal.valueOf(latDeg)).multiply(BD_ONEHOUNDREDTHOUSAND);
+ latDegFrac = bdLatFrac.setScale(0, RoundingMode.HALF_UP).intValue();
+
+ BigDecimal bdlon = BigDecimal.valueOf(lonSigned).abs();
+ lonDeg = bdlon.intValue();
+ BigDecimal bdLonFrac = bdlon.subtract(BigDecimal.valueOf(lonDeg)).multiply(BD_ONEHOUNDREDTHOUSAND);
+ lonDegFrac = bdLonFrac.setScale(0, RoundingMode.HALF_UP).intValue();
+ }
+
+ public static Geopoint createGeopoint(final String latDir, final String latDeg, final String latDegFrac,
+ final String lonDir, final String lonDeg, final String lonDegFrac) {
+ double lat = Double.parseDouble(latDeg + "." + addZeros(Integer.parseInt(latDegFrac), 5));
+ double lon = Double.parseDouble(lonDeg + "." + addZeros(Integer.parseInt(lonDegFrac), 5));
+ lat *= "S".equalsIgnoreCase(latDir) ? -1 : 1;
+ lon *= "W".equalsIgnoreCase(lonDir) ? -1 : 1;
+ return new Geopoint(lat, lon);
+ }
+ }
+
+ public static final class DMM extends Direction {
+
+ public final int latDeg;
+ public final double latMinRaw;
+ public final int latMin;
+ public final int latMinFrac;
+
+ public final int lonDeg;
+ public final double lonMinRaw;
+ public final int lonMin;
+ public final int lonMinFrac;
+
+ private DMM(final double latSigned, final double lonSigned) {
+ super(latSigned, lonSigned);
+ BigDecimal bdLat = BigDecimal.valueOf(latSigned).abs();
+ latDeg = bdLat.intValue();
+ BigDecimal bdLatMin = bdLat.subtract(BigDecimal.valueOf(latDeg)).multiply(BD_SIXTY);
+ // Rounding here ...
+ bdLatMin = bdLatMin.setScale(3, RoundingMode.HALF_UP);
+ latMinRaw = bdLatMin.doubleValue();
+ latMin = bdLatMin.intValue();
+ BigDecimal bdLatMinFrac = bdLatMin.subtract(BigDecimal.valueOf(latMin)).multiply(BD_THOUSAND);
+ latMinFrac = bdLatMinFrac.setScale(0, RoundingMode.HALF_UP).intValue();
+
+ BigDecimal bdlon = BigDecimal.valueOf(lonSigned).abs();
+ lonDeg = bdlon.intValue();
+ BigDecimal bdLonMin = bdlon.subtract(BigDecimal.valueOf(lonDeg)).multiply(BD_SIXTY);
+ // Rounding here ...
+ bdLonMin = bdLonMin.setScale(3, RoundingMode.HALF_UP);
+ lonMinRaw = bdLonMin.doubleValue();
+ lonMin = bdLonMin.intValue();
+ BigDecimal bdLonMinFrac = bdLonMin.subtract(BigDecimal.valueOf(lonMin)).multiply(BD_THOUSAND);
+ lonMinFrac = bdLonMinFrac.setScale(0, RoundingMode.HALF_UP).intValue();
+ }
+
+ public static Geopoint createGeopoint(final String latDir, final String latDeg, final String latMin, final String latMinFrac,
+ final String lonDir, final String lonDeg, final String lonMin, final String lonMinFrac) {
+ double lat = Double.parseDouble(latDeg) + Double.parseDouble(latMin + "." + addZeros(Integer.parseInt(latMinFrac), 3)) / D60;
+ double lon = Double.parseDouble(lonDeg) + Double.parseDouble(lonMin + "." + addZeros(Integer.parseInt(lonMinFrac), 3)) / D60;
+ lat *= "S".equalsIgnoreCase(latDir) ? -1 : 1;
+ lon *= "W".equalsIgnoreCase(lonDir) ? -1 : 1;
+ return new Geopoint(lat, lon);
+ }
+ }
+
+ public static final class DMS extends Direction {
+
+ public final int latDeg;
+ public final int latMin;
+ public final double latSecRaw;
+ public final int latSec;
+ public final int latSecFrac;
+
+ public final int lonDeg;
+ public final int lonMin;
+ public final double lonSecRaw;
+ public final int lonSec;
+ public final int lonSecFrac;
+
+ private DMS(final double latSigned, final double lonSigned) {
+ super(latSigned, lonSigned);
+ BigDecimal bdLat = BigDecimal.valueOf(latSigned).abs();
+ latDeg = bdLat.intValue();
+ BigDecimal bdLatMin = bdLat.subtract(BigDecimal.valueOf(latDeg)).multiply(BD_SIXTY);
+ latMin = bdLatMin.intValue();
+ BigDecimal bdLatSec = bdLatMin.subtract(BigDecimal.valueOf(latMin)).multiply(BD_SIXTY);
+ // Rounding here ...
+ bdLatSec = bdLatSec.setScale(3, RoundingMode.HALF_UP);
+ latSecRaw = bdLatSec.doubleValue();
+ latSec = bdLatSec.intValue();
+ BigDecimal bdLatSecFrac = bdLatSec.subtract(BigDecimal.valueOf(latSec)).multiply(BD_THOUSAND);
+ latSecFrac = bdLatSecFrac.setScale(0, RoundingMode.HALF_UP).intValue();
+
+ BigDecimal bdlon = BigDecimal.valueOf(lonSigned).abs();
+ lonDeg = bdlon.intValue();
+ BigDecimal bdLonMin = bdlon.subtract(BigDecimal.valueOf(lonDeg)).multiply(BD_SIXTY);
+ lonMin = bdLonMin.intValue();
+ BigDecimal bdLonSec = bdLonMin.subtract(BigDecimal.valueOf(lonMin)).multiply(BD_SIXTY);
+ // Rounding here ...
+ bdLonSec = bdLonSec.setScale(3, RoundingMode.HALF_UP);
+ lonSecRaw = bdLonSec.doubleValue();
+ lonSec = bdLonSec.intValue();
+ BigDecimal bdLonSecFrac = bdLonSec.subtract(BigDecimal.valueOf(lonSec)).multiply(BD_THOUSAND);
+ lonSecFrac = bdLonSecFrac.setScale(0, RoundingMode.HALF_UP).intValue();
+ }
+
+ public static Geopoint createGeopoint(final String latDir, final String latDeg, final String latMin, final String latSec, final String latSecFrac,
+ final String lonDir, final String lonDeg, final String lonMin, final String lonSec, final String lonSecFrac) {
+ double lat = Double.parseDouble(latDeg) + Double.parseDouble(latMin) / D60 + Double.parseDouble(latSec + "." + addZeros(Integer.parseInt(latSecFrac), 3)) / D3600;
+ double lon = Double.parseDouble(lonDeg) + Double.parseDouble(lonMin) / D60 + Double.parseDouble(lonSec + "." + addZeros(Integer.parseInt(lonSecFrac), 3)) / D3600;
+ lat *= "S".equalsIgnoreCase(latDir) ? -1 : 1;
+ lon *= "W".equalsIgnoreCase(lonDir) ? -1 : 1;
+ return new Geopoint(lat, lon);
+ }
+ }
+
abstract public static class GeopointException
extends RuntimeException
{
diff --git a/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java b/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java
index c4cfb8c..d0baee9 100644
--- a/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java
+++ b/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java
@@ -1,5 +1,8 @@
package cgeo.geocaching.geopoint;
+import cgeo.geocaching.geopoint.Geopoint.DMM;
+import cgeo.geocaching.geopoint.Geopoint.DMS;
+
import java.util.Locale;
/**
@@ -58,18 +61,9 @@ public class GeopointFormatter
{
final double latSigned = gp.getLatitude();
final double lonSigned = gp.getLongitude();
- final double lat = Math.abs(latSigned);
- final double lon = Math.abs(lonSigned);
- final double latFloor = Math.floor(lat);
- final double lonFloor = Math.floor(lon);
- final double latMin = (lat - latFloor) * 60;
- final double lonMin = (lon - lonFloor) * 60;
- final double latMinFloor = Math.floor(latMin);
- final double lonMinFloor = Math.floor(lonMin);
- final double latSec = (latMin - latMinFloor) * 60;
- final double lonSec = (lonMin - lonMinFloor) * 60;
- final char latDir = latSigned < 0 ? 'S' : 'N';
- final char lonDir = lonSigned < 0 ? 'W' : 'E';
+
+ DMM dmm = gp.asDMM();
+ DMS dms = gp.asDMS();
switch (format) {
case LAT_LON_DECDEGREE:
@@ -79,34 +73,34 @@ public class GeopointFormatter
return String.format((Locale) null, "%.6f,%.6f", latSigned, lonSigned);
case LAT_LON_DECMINUTE:
- return String.format("%c %02.0f° %06.3f · %c %03.0f° %06.3f",
- latDir, latFloor, latMin, lonDir, lonFloor, lonMin);
+ return String.format("%c %02d° %06.3f · %c %03d° %06.3f",
+ dmm.latDir, dmm.latDeg, dmm.latMinRaw, dmm.lonDir, dmm.lonDeg, dmm.lonMinRaw);
case LAT_LON_DECMINUTE_RAW:
- return String.format((Locale) null, "%c %02.0f° %06.3f %c %03.0f° %06.3f",
- latDir, latFloor, latMin, lonDir, lonFloor, lonMin);
+ return String.format((Locale) null, "%c %02d° %06.3f %c %03d° %06.3f",
+ dmm.latDir, dmm.latDeg, dmm.latMinRaw, dmm.lonDir, dmm.lonDeg, dmm.lonMinRaw);
case LAT_LON_DECSECOND:
- return String.format("%c %02.0f° %02.0f' %06.3f\" · %c %03.0f° %02.0f' %06.3f\"",
- latDir, latFloor, latMinFloor, latSec, lonDir, lonFloor, lonMinFloor, lonSec);
+ return String.format("%c %02d° %02d' %06.3f\" · %c %03d° %02d' %06.3f\"",
+ dms.latDir, dms.latDeg, dms.latMin, dms.latSecRaw, dms.lonDir, dms.lonDeg, dms.lonMin, dms.lonSecRaw);
case LAT_DECDEGREE_RAW:
return String.format((Locale) null, "%.6f", latSigned);
case LAT_DECMINUTE:
- return String.format("%c %02.0f° %06.3f", latDir, latFloor, latMin);
+ return String.format("%c %02d° %06.3f", dmm.latDir, dmm.latDeg, dmm.latMinRaw);
case LAT_DECMINUTE_RAW:
- return String.format("%c %02.0f %06.3f", latDir, latFloor, latMin);
+ return String.format("%c %02d %06.3f", dmm.latDir, dmm.latDeg, dmm.latMinRaw);
case LON_DECDEGREE_RAW:
return String.format((Locale) null, "%.6f", lonSigned);
case LON_DECMINUTE:
- return String.format("%c %03.0f° %06.3f", lonDir, lonFloor, lonMin);
+ return String.format("%c %03d° %06.3f", dmm.lonDir, dmm.lonDeg, dmm.lonMinRaw);
case LON_DECMINUTE_RAW:
- return String.format("%c %03.0f %06.3f", lonDir, lonFloor, lonMin);
+ return String.format("%c %03d %06.3f", dmm.lonDir, dmm.lonDeg, dmm.lonMinRaw);
}
// Keep the compiler happy even though it cannot happen
diff --git a/tests/src/cgeo/geocaching/geopoint/GeopointTest.java b/tests/src/cgeo/geocaching/geopoint/GeopointTest.java
index 63cc0b5..894b046 100644
--- a/tests/src/cgeo/geocaching/geopoint/GeopointTest.java
+++ b/tests/src/cgeo/geocaching/geopoint/GeopointTest.java
@@ -1,5 +1,9 @@
package cgeo.geocaching.geopoint;
+import cgeo.geocaching.geopoint.Geopoint.DDD;
+import cgeo.geocaching.geopoint.Geopoint.DMM;
+import cgeo.geocaching.geopoint.Geopoint.DMS;
+
import android.test.AndroidTestCase;
import junit.framework.Assert;
@@ -63,4 +67,180 @@ public class GeopointTest extends AndroidTestCase {
Assert.assertEquals(107.715, gp2.bearingTo(gp1), 1e-3);
}
+ public static void testDDD() {
+ // case 1
+ final Geopoint gp1 = new Geopoint(51.3d, 13.8d);
+ DDD ddd1 = gp1.asDDD();
+
+ checkDDD(ddd1, 'N', 51, 30000, 'E', 13, 80000);
+
+ Geopoint gp1a = DDD.createGeopoint(String.valueOf(ddd1.latDir), String.valueOf(ddd1.latDeg), String.valueOf(ddd1.latDegFrac),
+ String.valueOf(ddd1.lonDir), String.valueOf(ddd1.lonDeg), String.valueOf(ddd1.lonDegFrac));
+
+ Assert.assertTrue(gp1a.isEqualTo(gp1));
+
+ // case 2
+ final Geopoint gp2 = new Geopoint(51.34567d, 13.87654d);
+ DDD ddd2 = gp2.asDDD();
+
+ checkDDD(ddd2, 'N', 51, 34567, 'E', 13, 87654);
+
+ Geopoint gp2a = DDD.createGeopoint(String.valueOf(ddd2.latDir), String.valueOf(ddd2.latDeg), String.valueOf(ddd2.latDegFrac),
+ String.valueOf(ddd2.lonDir), String.valueOf(ddd2.lonDeg), String.valueOf(ddd2.lonDegFrac));
+
+ Assert.assertTrue(gp2a.isEqualTo(gp2));
+
+ // case 3
+ final Geopoint gp3 = new Geopoint(51.29999833333333d, 13.8d);
+ DDD ddd3 = gp3.asDDD();
+
+ checkDDD(ddd3, 'N', 51, 30000, 'E', 13, 80000);
+
+ Geopoint gp3a = DDD.createGeopoint(String.valueOf(ddd3.latDir), String.valueOf(ddd3.latDeg), String.valueOf(ddd3.latDegFrac),
+ String.valueOf(ddd3.lonDir), String.valueOf(ddd3.lonDeg), String.valueOf(ddd3.lonDegFrac));
+
+ checkTolerance(gp3, gp3a, 5e-5);
+
+ // case 4
+ final Geopoint gp4 = new Geopoint(51.00012d, 13.00089d);
+ DDD ddd4 = gp4.asDDD();
+
+ checkDDD(ddd4, 'N', 51, 12, 'E', 13, 89);
+
+ Geopoint gp4a = DDD.createGeopoint(String.valueOf(ddd4.latDir), String.valueOf(ddd4.latDeg), String.valueOf(ddd4.latDegFrac),
+ String.valueOf(ddd4.lonDir), String.valueOf(ddd4.lonDeg), String.valueOf(ddd4.lonDegFrac));
+
+ checkTolerance(gp4, gp4a, 5e-5);
+ }
+
+ private static void checkDDD(DDD ddd, char latDir, int latDeg, int latDegFrac, char lonDir, int lonDeg, int lonDegFrac) {
+ Assert.assertEquals(latDir, ddd.latDir);
+ Assert.assertEquals(latDeg, ddd.latDeg);
+ Assert.assertEquals(latDegFrac, ddd.latDegFrac);
+ Assert.assertEquals(lonDir, ddd.lonDir);
+ Assert.assertEquals(lonDeg, ddd.lonDeg);
+ Assert.assertEquals(lonDegFrac, ddd.lonDegFrac);
+ }
+
+ private static void checkTolerance(Geopoint gp1, Geopoint gp2, double tolerance) {
+ Assert.assertTrue(Math.abs(gp1.getLatitude() - gp2.getLatitude()) <= tolerance);
+ Assert.assertTrue(Math.abs(gp1.getLongitude() - gp2.getLongitude()) <= tolerance);
+ }
+
+ public static void testDMM() {
+ // case 1
+ final Geopoint gp1 = new Geopoint(51.3d, 13.8d);
+ DMM dmm1 = gp1.asDMM();
+
+ checkDMM(dmm1, 'N', 51, 18, 0, 'E', 13, 48, 0);
+
+ Geopoint gp1a = DMM.createGeopoint(String.valueOf(dmm1.latDir), String.valueOf(dmm1.latDeg), String.valueOf(dmm1.latMin), String.valueOf(dmm1.latMinFrac),
+ String.valueOf(dmm1.lonDir), String.valueOf(dmm1.lonDeg), String.valueOf(dmm1.lonMin), String.valueOf(dmm1.lonMinFrac));
+
+ Assert.assertTrue(gp1a.isEqualTo(gp1));
+
+ // case 2
+ final Geopoint gp2 = new Geopoint(51.34567d, 13.87654d);
+ DMM dmm2 = gp2.asDMM();
+
+ checkDMM(dmm2, 'N', 51, 20, 740, 'E', 13, 52, 592);
+
+ Geopoint gp2a = DMM.createGeopoint(String.valueOf(dmm2.latDir), String.valueOf(dmm2.latDeg), String.valueOf(dmm2.latMin), String.valueOf(dmm2.latMinFrac),
+ String.valueOf(dmm2.lonDir), String.valueOf(dmm2.lonDeg), String.valueOf(dmm2.lonMin), String.valueOf(dmm2.lonMinFrac));
+
+ checkTolerance(gp2, gp2a, 5e-5);
+
+ // case 3
+ final Geopoint gp3 = new Geopoint(51.29999833333333d, 13.8d);
+ DMM dmm3 = gp3.asDMM();
+
+ checkDMM(dmm3, 'N', 51, 18, 0, 'E', 13, 48, 0);
+
+ Geopoint gp3a = DMM.createGeopoint(String.valueOf(dmm3.latDir), String.valueOf(dmm3.latDeg), String.valueOf(dmm3.latMin), String.valueOf(dmm3.latMinFrac),
+ String.valueOf(dmm3.lonDir), String.valueOf(dmm3.lonDeg), String.valueOf(dmm3.lonMin), String.valueOf(dmm3.lonMinFrac));
+
+ checkTolerance(gp3, gp3a, 5e-5);
+
+ // case 4
+ final Geopoint gp4 = new Geopoint(51.00012d, 13.00089d);
+ DMM dmm4 = gp4.asDMM();
+
+ checkDMM(dmm4, 'N', 51, 0, 7, 'E', 13, 0, 53);
+
+ Geopoint gp4a = DMM.createGeopoint(String.valueOf(dmm4.latDir), String.valueOf(dmm4.latDeg), String.valueOf(dmm4.latMin), String.valueOf(dmm4.latMinFrac),
+ String.valueOf(dmm4.lonDir), String.valueOf(dmm4.lonDeg), String.valueOf(dmm4.lonMin), String.valueOf(dmm4.lonMinFrac));
+
+ checkTolerance(gp4, gp4a, 5e-5);
+ }
+
+ private static void checkDMM(DMM dmm, char latDir, int latDeg, int latMin, int latMinFrac, char lonDir, int lonDeg, int lonMin, int lonMinFrac) {
+ Assert.assertEquals(latDir, dmm.latDir);
+ Assert.assertEquals(latDeg, dmm.latDeg);
+ Assert.assertEquals(latMin, dmm.latMin);
+ Assert.assertEquals(latMinFrac, dmm.latMinFrac);
+ Assert.assertEquals(lonDir, dmm.lonDir);
+ Assert.assertEquals(lonDeg, dmm.lonDeg);
+ Assert.assertEquals(lonMin, dmm.lonMin);
+ Assert.assertEquals(lonMinFrac, dmm.lonMinFrac);
+ }
+
+ public static void testDMS() {
+ // case 1
+ final Geopoint gp1 = new Geopoint(51.3d, 13.8d);
+ DMS dms1 = gp1.asDMS();
+
+ checkDMS(dms1, 'N', 51, 18, 0, 0, 'E', 13, 48, 0, 0);
+
+ Geopoint gp1a = DMS.createGeopoint(String.valueOf(dms1.latDir), String.valueOf(dms1.latDeg), String.valueOf(dms1.latMin), String.valueOf(dms1.latSec), String.valueOf(dms1.latSecFrac),
+ String.valueOf(dms1.lonDir), String.valueOf(dms1.lonDeg), String.valueOf(dms1.lonMin), String.valueOf(dms1.lonSec), String.valueOf(dms1.lonSecFrac));
+
+ Assert.assertTrue(gp1a.isEqualTo(gp1));
+
+ // case 2
+ final Geopoint gp2 = new Geopoint(51.34567d, 13.87654d);
+ DMS dms2 = gp2.asDMS();
+
+ checkDMS(dms2, 'N', 51, 20, 44, 412, 'E', 13, 52, 35, 544);
+
+ Geopoint gp2a = DMS.createGeopoint(String.valueOf(dms2.latDir), String.valueOf(dms2.latDeg), String.valueOf(dms2.latMin), String.valueOf(dms2.latSec), String.valueOf(dms2.latSecFrac),
+ String.valueOf(dms2.lonDir), String.valueOf(dms2.lonDeg), String.valueOf(dms2.lonMin), String.valueOf(dms2.lonSec), String.valueOf(dms2.lonSecFrac));
+
+ checkTolerance(gp2, gp2a, 5e-6);
+
+ // case 3
+ final Geopoint gp3 = new Geopoint(51.29999833333333d, 13.8d);
+ DMS dms3 = gp3.asDMS();
+
+ checkDMS(dms3, 'N', 51, 17, 59, 994, 'E', 13, 48, 0, 0);
+
+ Geopoint gp3a = DMS.createGeopoint(String.valueOf(dms3.latDir), String.valueOf(dms3.latDeg), String.valueOf(dms3.latMin), String.valueOf(dms3.latSec), String.valueOf(dms3.latSecFrac),
+ String.valueOf(dms3.lonDir), String.valueOf(dms3.lonDeg), String.valueOf(dms3.lonMin), String.valueOf(dms3.lonSec), String.valueOf(dms3.lonSecFrac));
+
+ checkTolerance(gp3, gp3a, 5e-6);
+
+ // case 4
+ final Geopoint gp4 = new Geopoint(51.00012d, 13.00089d);
+ DMS dms4 = gp4.asDMS();
+
+ checkDMS(dms4, 'N', 51, 0, 0, 432, 'E', 13, 0, 3, 204);
+
+ Geopoint gp4a = DMS.createGeopoint(String.valueOf(dms4.latDir), String.valueOf(dms4.latDeg), String.valueOf(dms4.latMin), String.valueOf(dms4.latSec), String.valueOf(dms4.latSecFrac),
+ String.valueOf(dms4.lonDir), String.valueOf(dms4.lonDeg), String.valueOf(dms4.lonMin), String.valueOf(dms4.lonSec), String.valueOf(dms4.lonSecFrac));
+
+ checkTolerance(gp4, gp4a, 5e-6);
+ }
+
+ private static void checkDMS(DMS dms, char latDir, int latDeg, int latMin, int latSec, int latSecFrac, char lonDir, int lonDeg, int lonMin, int lonSec, int lonSecFrac) {
+ Assert.assertEquals(latDir, dms.latDir);
+ Assert.assertEquals(latDeg, dms.latDeg);
+ Assert.assertEquals(latMin, dms.latMin);
+ Assert.assertEquals(latSec, dms.latSec);
+ Assert.assertEquals(latSecFrac, dms.latSecFrac);
+ Assert.assertEquals(lonDir, dms.lonDir);
+ Assert.assertEquals(lonDeg, dms.lonDeg);
+ Assert.assertEquals(lonMin, dms.lonMin);
+ Assert.assertEquals(lonSec, dms.lonSec);
+ Assert.assertEquals(lonSecFrac, dms.lonSecFrac);
+ }
+
}