diff options
| author | Torsten Keil <github@torsten-keil.net> | 2012-02-17 19:17:52 +0100 |
|---|---|---|
| committer | Bananeweizen <Bananeweizen@gmx.de> | 2012-02-17 19:17:52 +0100 |
| commit | 876bf8c1ae2f5de62fd37c65a896417e9db43f84 (patch) | |
| tree | 303d2769910ad3733c86ae4089b5e99d61ac4025 | |
| parent | 5241b730a8a3d3650b9b6f0352f74c090e258afe (diff) | |
| download | cgeo-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.java | 130 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/cgeowaypointadd.java | 18 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/geopoint/Geopoint.java | 219 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/geopoint/GeopointFormatter.java | 38 | ||||
| -rw-r--r-- | tests/src/cgeo/geocaching/geopoint/GeopointTest.java | 180 |
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); + } + } |
