Skip to content

Added distance and elevation (min/max) computation #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
6 changes: 6 additions & 0 deletions res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@
<string name="trackdetail">Track Details</string>
<string name="trackdetail_startdate">Start time:</string>
<string name="trackdetail_enddate">End time:</string>
<string name="trackdetail_distance">Distance:</string>
<string name="trackdetail_distance_unit">Km</string>
<string name="trackdetail_elevation">Elevation(min/max):</string>
<string name="trackdetail_elevation_unit">m</string>
<string name="trackdetail_speed">Speed(min/max):</string>
<string name="trackdetail_speed_unit">Km/h</string>
<string name="trackdetail_startloc">Starts at:</string>
<string name="trackdetail_endloc">Ends at:</string>
<string name="trackdetail_exportdate">Exported:</string>
Expand Down
20 changes: 20 additions & 0 deletions src/me/guillaumin/android/osmtracker/activity/TrackDetail.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<String, String>();
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<String, String>();
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<String, String>();
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<String, String>();
Expand Down
81 changes: 81 additions & 0 deletions src/me/guillaumin/android/osmtracker/db/model/Track.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
46 changes: 46 additions & 0 deletions src/me/guillaumin/android/osmtracker/util/DistanceUtil.java
Original file line number Diff line number Diff line change
@@ -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);
}
}