GPX Analysis: Add elevation graph (for now only in meters)

This commit is contained in:
sonora 2016-11-26 20:31:26 +01:00
parent b9884e2abf
commit 2668df4f32
4 changed files with 148 additions and 9 deletions

View file

@ -48,14 +48,23 @@
tools:text="@string/lorem_ipsum" />
</LinearLayout>
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginTop="5dp"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_desc_text_size"
tools:text="Hellow world"/>
android:orientation="vertical">
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginTop="5dp"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size" />
</LinearLayout>
<net.osmand.plus.myplaces.ElevationView
android:id="@+id/elevation"
android:layout_width="fill_parent"
android:layout_height="150dp"
android:layout_gravity="center_vertical" />
</LinearLayout>
</LinearLayout>

View file

@ -91,6 +91,10 @@ public class GPXUtilities {
}
public static class Elevation {
public double distance, elevation;
}
public static class WptPt extends GPXExtensions implements LocationPoint {
public double lat;
public double lon;
@ -286,6 +290,8 @@ public class GPXUtilities {
return maxElevation != -100;
}
public List<Elevation> elevationData;
public boolean isSpeedSpecified() {
return avgSpeed > 0;
}
@ -311,6 +317,8 @@ public class GPXUtilities {
double channelBottom;
boolean climb = false;
elevationData = new ArrayList<>();
for (SplitSegment s : splitSegments) {
final int numberOfPoints = s.getNumberOfPoints();
@ -337,11 +345,16 @@ public class GPXUtilities {
}
double elevation = point.ele;
Elevation elevation1 = new Elevation();
if (!Double.isNaN(elevation)) {
totalElevation += elevation;
elevationPoints++;
minElevation = Math.min(elevation, minElevation);
maxElevation = Math.max(elevation, maxElevation);
elevation1.elevation = elevation;
} else {
elevation1.elevation = 0;
}
float speed = (float) point.speed;
@ -433,7 +446,12 @@ public class GPXUtilities {
// timeMoving0 = timeMoving0 + (point.time - prev.time);
// totalDistanceMoving0 += calculations[0];
// }
}
elevation1.distance = (j > 0) ? calculations[0] : 0;
elevationData.add(elevation1);
}
}
if (!isTimeSpecified()) {

View file

@ -0,0 +1,98 @@
package net.osmand.plus.myplaces;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.R;
import java.util.List;
/**
* Created by maw on 02.09.15., original credit goes to gibbsnich
* Developed further by Hardy 2016-11
*/
public class ElevationView extends ImageView {
double maxElevation, minElevation;
float xDistance;
List<GPXUtilities.Elevation> elevationList;
public ElevationView(Context ctx, AttributeSet as) {
super(ctx, as);
}
public void onDraw(Canvas canvas) {
final float screenScale = getResources().getDisplayMetrics().density;
//TODO: Hardy: Perhaps support the other units of length in graph
int maxBase = (int)maxElevation / 100, minBase = (int)minElevation / 100;
maxBase += 1;
float yDistance = (maxBase-minBase) * 100;
float xPer = (float)canvas.getWidth() / xDistance;
float yPer = (float)canvas.getHeight() / yDistance;
Paint barPaint = new Paint();
barPaint.setColor(getResources().getColor(R.color.dialog_inactive_text_color_dark));
barPaint.setTextSize((int)(16f * screenScale + 0.5f));
barPaint.setTypeface(Typeface.create(Typeface.DEFAULT_BOLD, Typeface.BOLD));
float yTextLast = 9999f;
for (int i = minBase; i <= maxBase ; i++) {
float y = (float)canvas.getHeight() - yPer * (float)(i*100-(minBase*100));
canvas.drawLine(0, y, canvas.getWidth(), y, barPaint);
if (yTextLast - y >= (int)(32f * screenScale + 0.5f)) { // Overlap prevention
canvas.drawText(String.valueOf(i*100) + " m", (int)(8f * screenScale + 0.5f), y-(int)(2f * screenScale + 0.5f), barPaint);
yTextLast = (float)(y);
}
}
canvas.drawLine(0, getResources().getDisplayMetrics().density, canvas.getWidth(), getResources().getDisplayMetrics().density, barPaint);
float lastX = 0, lastY = 0;
float xDistSum = 0;
Paint paint = new Paint();
paint.setColor(getResources().getColor(R.color.gpx_altitude_asc));
paint.setStrokeWidth((int)(2f * screenScale + 0.5f));
boolean first = true;
if (elevationList != null) {
for (GPXUtilities.Elevation elevation : elevationList) {
xDistSum += elevation.distance;
float nextX = xPer * xDistSum;
float nextY = (float)canvas.getHeight() - yPer * (float)(elevation.elevation - (minBase*100f));
if (first) {
first = false;
} else {
//Log.d("ElevationView", "curElevation: "+elevation.elevation+", drawLine: ("+lastX+", "+lastY+") -> ("+nextX+", "+nextY+")");
canvas.drawLine(lastX, lastY, nextX, nextY, paint);
}
lastX = nextX;
lastY = nextY;
}
//Log.d("ElevationView", "yMin: "+yMin+", yMax = "+yMax+", smallestY = "+smallestYFound+", biggestY = "+biggestYFound);
}
}
public void setElevationData(List<GPXUtilities.Elevation> elevationData) {
elevationList = elevationData;
}
public void setMaxElevation(double max) {
maxElevation = max;
}
public void setMinElevation(double min) {
minElevation = min;
}
public void setTotalDistance(float dist) {
xDistance = dist;
}
}

View file

@ -2,8 +2,11 @@ package net.osmand.plus.myplaces;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@ -31,6 +34,7 @@ import net.osmand.data.FavouritePoint;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.GpxSelectionHelper;
@ -491,6 +495,16 @@ public class SelectedGPXFragment extends OsmAndListFragment {
description.setVisibility(View.GONE);
}
ElevationView elevationImg = (ElevationView) row.findViewById(R.id.elevation);
if (child.analysis != null && child.analysis.elevationData != null && child.analysis.isElevationSpecified() && (child.analysis.points > 1)) {
elevationImg.setElevationData(child.analysis.elevationData);
elevationImg.setMaxElevation(child.analysis.maxElevation);
elevationImg.setMinElevation(child.analysis.minElevation);
elevationImg.setTotalDistance(child.analysis.totalDistance); //Use raw data for graph, not channel detection noise filter (facilitates visual double check)
} else {
elevationImg.setVisibility(View.GONE);
}
return row;
}