GPX Analysis: Add elevation graph (for now only in meters)
This commit is contained in:
parent
b9884e2abf
commit
2668df4f32
4 changed files with 148 additions and 9 deletions
|
@ -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>
|
||||
|
|
|
@ -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()) {
|
||||
|
|
98
OsmAnd/src/net/osmand/plus/myplaces/ElevationView.java
Normal file
98
OsmAnd/src/net/osmand/plus/myplaces/ElevationView.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue