diff --git a/res/values/strings.xml b/res/values/strings.xml
index 05b8dcf47..4a2bc0451 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -53,6 +53,12 @@
Track Details
Start time:
End time:
+ Distance:
+ Km
+ Elevation(min/max):
+ m
+ Speed(min/max):
+ Km/h
Starts at:
Ends at:
Exported:
diff --git a/src/me/guillaumin/android/osmtracker/activity/TrackDetail.java b/src/me/guillaumin/android/osmtracker/activity/TrackDetail.java
index 8d593294e..78070acbc 100644
--- a/src/me/guillaumin/android/osmtracker/activity/TrackDetail.java
+++ b/src/me/guillaumin/android/osmtracker/activity/TrackDetail.java
@@ -2,6 +2,7 @@
import java.sql.Date;
import java.text.DateFormat;
+import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -155,6 +156,25 @@ protected void onResume() {
map.put(ITEM_KEY, getResources().getString(R.string.trackdetail_enddate));
map.put(ITEM_VALUE, t.getEndDateAsString());
data.add(map);
+
+ DecimalFormat df = new DecimalFormat("#,##0.00");
+ // Distance
+ map = new HashMap();
+ map.put(ITEM_KEY, getResources().getString(R.string.trackdetail_distance));
+ map.put(ITEM_VALUE, df.format(t.getDistance()/1000) + " " +getResources().getString(R.string.trackdetail_distance_unit));
+ data.add(map);
+
+ // Elevation
+ map = new HashMap();
+ map.put(ITEM_KEY, getResources().getString(R.string.trackdetail_elevation));
+ map.put(ITEM_VALUE, df.format(t.getElevationMin()) + " / " + df.format(t.getElevationMax()) + " " +getResources().getString(R.string.trackdetail_elevation_unit));
+ data.add(map);
+
+ // Speed
+ map = new HashMap();
+ map.put(ITEM_KEY, getResources().getString(R.string.trackdetail_speed));
+ map.put(ITEM_VALUE, df.format(t.getSpeedMin() * 3.6) + " / " + df.format(t.getSpeedMax() * 3.6) + " " + getResources().getString(R.string.trackdetail_speed_unit));
+ data.add(map);
// Start point
map = new HashMap();
diff --git a/src/me/guillaumin/android/osmtracker/db/model/Track.java b/src/me/guillaumin/android/osmtracker/db/model/Track.java
index aeb992e9f..b4d2b1027 100644
--- a/src/me/guillaumin/android/osmtracker/db/model/Track.java
+++ b/src/me/guillaumin/android/osmtracker/db/model/Track.java
@@ -9,6 +9,7 @@
import me.guillaumin.android.osmtracker.R;
import me.guillaumin.android.osmtracker.db.TrackContentProvider;
import me.guillaumin.android.osmtracker.db.TrackContentProvider.Schema;
+import me.guillaumin.android.osmtracker.util.DistanceUtil;
import android.content.ContentResolver;
import android.database.Cursor;
@@ -57,8 +58,12 @@ public static OSMVisibility fromPosition(int position) {
private Long startDate=null, endDate=null;
private Float startLat=null, startLong=null, endLat=null, endLong=null;
+ private Float distance=0.0f;
+ private Float elevationMax=0.0f,elevationMin=0.0f;
+ private Float speedMax=0.0f, speedMin=0.0f;
private boolean extraInformationRead = false;
+ private boolean extraInformationRead_stats = false;
private ContentResolver cr;
@@ -121,6 +126,56 @@ private void readExtraInformation(){
}
}
+ /**
+ *
+ * @todo: allow to exclude zero speed values
+ */
+ private void readExtraInformation_stats() {
+ if(!extraInformationRead_stats){
+ Cursor cursor = cr.query(TrackContentProvider.trackPointsUri(trackId), null, null, null, null);
+ Float latitudeCurrent, longitudeCurrent, latitudePrev, longitudePrev;
+
+ Float elevationCurr, speedCurr;
+
+ boolean avoidZeroSpeed = true;
+
+ if(cursor != null && cursor.moveToFirst()) {
+ // Initialize the min/max values
+ elevationMin = elevationMax = cursor.getFloat(cursor.getColumnIndex(Schema.COL_ELEVATION));
+ speedMax = cursor.getFloat(cursor.getColumnIndex(Schema.COL_SPEED));
+ speedMin = (avoidZeroSpeed && speedMax == 0) ? Float.MAX_VALUE : speedMax;
+
+ latitudePrev = cursor.getFloat(cursor.getColumnIndex(Schema.COL_LATITUDE));
+ longitudePrev = cursor.getFloat(cursor.getColumnIndex(Schema.COL_LONGITUDE));
+
+ // Iterate over all points
+ while (cursor.moveToNext()) {
+ latitudeCurrent = cursor.getFloat(cursor.getColumnIndex(Schema.COL_LATITUDE));
+ longitudeCurrent = cursor.getFloat(cursor.getColumnIndex(Schema.COL_LONGITUDE));
+ distance += DistanceUtil.getDistance(latitudePrev, longitudePrev, latitudeCurrent, longitudeCurrent);
+
+ latitudePrev = latitudeCurrent;
+ longitudePrev = longitudeCurrent;
+
+ // Compute the Elevation
+ elevationCurr = cursor.getFloat(cursor.getColumnIndex(Schema.COL_ELEVATION));
+ elevationMin = Math.min(elevationMin, elevationCurr);
+ elevationMax = Math.max(elevationMax, elevationCurr);
+
+ // Compute the Speed
+ speedCurr = cursor.getFloat(cursor.getColumnIndex(Schema.COL_SPEED));
+ if (!avoidZeroSpeed || speedCurr > 0) {
+ speedMin = Math.min(speedMin, speedCurr);
+ speedMax = Math.max(speedMax, speedCurr);
+ }
+ }
+ cursor.close();
+ extraInformationRead_stats = true;
+ }
+ }
+ }
+
+
public void setName(String name) {
this.name = name;
}
@@ -177,6 +232,32 @@ public Integer getTpCount() {
return tpCount;
}
+ public Float getDistance() {
+ readExtraInformation_stats();
+ return distance;
+ }
+
+ public Float getElevationMin() {
+ readExtraInformation_stats();
+ return elevationMin;
+ }
+
+ public Float getElevationMax() {
+ readExtraInformation_stats();
+ return elevationMax;
+ }
+
+ public Float getSpeedMax() {
+ readExtraInformation_stats();
+ return speedMax;
+ }
+
+ public Float getSpeedMin() {
+ readExtraInformation_stats();
+ // Avoid returning inconsistent min-speed if "avoidZeroSpeed" is set to true
+ return (speedMin > speedMax) ? 0.0f : speedMin;
+ }
+
public String getName() {
if (name != null && name.length() > 0) {
return name;
diff --git a/src/me/guillaumin/android/osmtracker/util/DistanceUtil.java b/src/me/guillaumin/android/osmtracker/util/DistanceUtil.java
new file mode 100644
index 000000000..d4a456df5
--- /dev/null
+++ b/src/me/guillaumin/android/osmtracker/util/DistanceUtil.java
@@ -0,0 +1,46 @@
+package me.guillaumin.android.osmtracker.util;
+
+import org.osmdroid.api.IGeoPoint;
+
+public class DistanceUtil {
+
+ private static final double DEG2RAD = Math.PI / 180.0;
+ // private static final double RAD2DEG = 180.0 / Math.PI;
+ private static final int RADIUS_EARTH_METERS = 6378137;
+
+ /**
+ * Computes the distance with Spherical Law of Cosines
+ * http://www.movable-type.co.uk/scripts/latlong.html
+ * @param lat1
+ * @param lon1
+ * @param lat2
+ * @param lon2
+ * @return The distance (in meters) between point1 and point2
+ */
+ public static float getDistance(final float lat1, final float lon1, final float lat2, final float lon2) {
+ final double theta = lon1 - lon2;
+ System.out.println("theta = " + theta);
+ final double v = (Math.sin(DEG2RAD * lat1) * Math.sin(DEG2RAD * lat2))
+ + (Math.cos(DEG2RAD * lat1) * Math.cos(DEG2RAD * lat2) * Math.cos(DEG2RAD * theta));
+
+ // Due to Float/Double approximations sometimes the value v is greater than 1, thus out of Math.acos() domain
+ // @see: http://www.mathworks.it/it/help/matlab/ref/acos.html
+ return (v > 1) ? 0.0f : (float) (Math.acos(v) * RADIUS_EARTH_METERS);
+ }
+
+ /**
+ * Computes the distance with Spherical Law of Cosines
+ * http://www.movable-type.co.uk/scripts/latlong.html
+ * @param point1
+ * @param point2
+ * @return The distance (in meters) between point1 and point2
+ */
+ public static float getDistance(final IGeoPoint point1, final IGeoPoint point2) {
+ final float lat1 = (float) (point1.getLatitudeE6() / 1E6);
+ final float lon1 = (float) (point1.getLongitudeE6() / 1E6);
+ final float lat2 = (float) (point2.getLatitudeE6() / 1E6);
+ final float lon2 = (float) (point2.getLongitudeE6() / 1E6);
+
+ return getDistance(lat1, lon1, lat2, lon2);
+ }
+}