Optimize charts. Turn off splines.
This commit is contained in:
parent
69399b12c9
commit
0e920b7f91
3 changed files with 228 additions and 269 deletions
|
@ -225,16 +225,20 @@ public class ShowRouteInfoDialogFragment extends DialogFragment {
|
|||
});
|
||||
|
||||
GPXTrackAnalysis analysis = gpx.getAnalysis(0);
|
||||
List<ILineDataSet> dataSets = new ArrayList<>();
|
||||
GpxUiHelper.OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, mChart, analysis, false, true);
|
||||
dataSets.add(elevationDataSet);
|
||||
if (analysis.elevationData.size() > 1) {
|
||||
GpxUiHelper.OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, mChart, analysis, true, true);
|
||||
dataSets.add(slopeDataSet);
|
||||
if (analysis.totalDistance > 0) {
|
||||
List<ILineDataSet> dataSets = new ArrayList<>();
|
||||
GpxUiHelper.OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, mChart, analysis, false, true);
|
||||
dataSets.add(elevationDataSet);
|
||||
if (analysis.elevationData.size() > 1) {
|
||||
GpxUiHelper.OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, mChart, analysis, elevationDataSet.getValues(), true, true);
|
||||
dataSets.add(slopeDataSet);
|
||||
}
|
||||
LineData data = new LineData(dataSets);
|
||||
mChart.setData(data);
|
||||
mChart.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mChart.setVisibility(View.GONE);
|
||||
}
|
||||
LineData data = new LineData(dataSets);
|
||||
mChart.setData(data);
|
||||
|
||||
((TextView) headerView.findViewById(R.id.average_text))
|
||||
.setText(OsmAndFormatter.getFormattedAlt(analysis.avgElevation, app));
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ import android.content.Context;
|
|||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
|
@ -34,6 +36,7 @@ import android.widget.ImageView;
|
|||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.github.mikephil.charting.animation.ChartAnimator;
|
||||
import com.github.mikephil.charting.charts.LineChart;
|
||||
import com.github.mikephil.charting.components.AxisBase;
|
||||
import com.github.mikephil.charting.components.Legend;
|
||||
|
@ -46,10 +49,14 @@ import com.github.mikephil.charting.data.LineData;
|
|||
import com.github.mikephil.charting.data.LineDataSet;
|
||||
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
|
||||
import com.github.mikephil.charting.formatter.IFillFormatter;
|
||||
import com.github.mikephil.charting.formatter.IValueFormatter;
|
||||
import com.github.mikephil.charting.highlight.Highlight;
|
||||
import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider;
|
||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||
import com.github.mikephil.charting.renderer.LineChartRenderer;
|
||||
import com.github.mikephil.charting.utils.MPPointF;
|
||||
import com.github.mikephil.charting.utils.Transformer;
|
||||
import com.github.mikephil.charting.utils.ViewPortHandler;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.CallbackWithObject;
|
||||
|
@ -867,6 +874,8 @@ public class GpxUiHelper {
|
|||
mChart.setExtraTopOffset(24f);
|
||||
mChart.setExtraBottomOffset(16f);
|
||||
|
||||
mChart.setRenderer(new SplineRenderer(mChart, mChart.getAnimator(), mChart.getViewPortHandler()));
|
||||
|
||||
// create a custom MarkerView (extend MarkerView) and specify the layout
|
||||
// to use for it
|
||||
GPXMarkerView mv = new GPXMarkerView(mChart.getContext());
|
||||
|
@ -969,6 +978,54 @@ public class GpxUiHelper {
|
|||
return granularity;
|
||||
}
|
||||
|
||||
private static List<Entry> calculateElevationArray(GPXTrackAnalysis analysis, float divX, float convEle) {
|
||||
List<Entry> values = new ArrayList<>();
|
||||
List<Elevation> elevationData = analysis.elevationData;
|
||||
float nextX = 0;
|
||||
float nextY;
|
||||
float prevYM;
|
||||
float elev;
|
||||
float prevElevOrig = -80000;
|
||||
float prevElev = 0;
|
||||
int i = -1;
|
||||
int lastIndex = elevationData.size() - 1;
|
||||
float shift = 0f;
|
||||
Entry lastEntry = null;
|
||||
float lastXSameY = -1;
|
||||
boolean hasSameY = false;
|
||||
for (Elevation e : elevationData) {
|
||||
i++;
|
||||
if (e.distance > 0) {
|
||||
nextX += (float) e.distance / divX;
|
||||
elev = (float) e.elevation;
|
||||
if (prevElevOrig != -80000) {
|
||||
if (elev > prevElevOrig) {
|
||||
elev -= 1f;
|
||||
} else if (prevElevOrig == elev && i < lastIndex) {
|
||||
hasSameY = true;
|
||||
lastXSameY = nextX;
|
||||
continue;
|
||||
}
|
||||
if (prevElev == elev && i < lastIndex) {
|
||||
hasSameY = true;
|
||||
lastXSameY = nextX;
|
||||
continue;
|
||||
}
|
||||
if (hasSameY) {
|
||||
values.add(new Entry(lastXSameY, lastEntry.getY()));
|
||||
}
|
||||
hasSameY = false;
|
||||
}
|
||||
prevElevOrig = (float) e.elevation;
|
||||
prevElev = elev;
|
||||
nextY = elev * convEle;
|
||||
lastEntry = new Entry(nextX, nextY);
|
||||
values.add(lastEntry);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
public static OrderedLineDataSet createGPXElevationDataSet(OsmandApplication ctx, LineChart mChart, GPXTrackAnalysis analysis, boolean useRightAxis, boolean drawFilled) {
|
||||
OsmandSettings settings = ctx.getSettings();
|
||||
OsmandSettings.MetricsConstants mc = settings.METRIC_SYSTEM.get();
|
||||
|
@ -1020,76 +1077,7 @@ public class GpxUiHelper {
|
|||
}
|
||||
});
|
||||
|
||||
List<Entry> values = new ArrayList<>();
|
||||
List<Elevation> elevationData = analysis.elevationData;
|
||||
float nextX = 0;
|
||||
float nextY;
|
||||
float elev;
|
||||
float prevElev = -80000;
|
||||
int i = -1;
|
||||
int lastIndex = elevationData.size() - 1;
|
||||
float shift = 0f;
|
||||
Entry entry = null;
|
||||
for (Elevation e : elevationData) {
|
||||
i++;
|
||||
if (e.distance > 0) {
|
||||
nextX += (float) e.distance / divX;
|
||||
elev = (float) e.elevation;
|
||||
if (prevElev != -80000) {
|
||||
if (elev < prevElev) {
|
||||
shift = 0f;
|
||||
} else if (elev > prevElev) {
|
||||
shift = -1f;
|
||||
} else if (prevElev == elev && i < lastIndex) {
|
||||
values.add(new Entry(nextX, entry.getY()));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
prevElev = elev;
|
||||
nextY = (elev + shift) * convEle;
|
||||
entry = new Entry(nextX, nextY);
|
||||
values.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
List<Entry> newValues = new ArrayList<>();
|
||||
Entry lastEntry = null;
|
||||
i = -1;
|
||||
lastIndex = values.size() - 1;
|
||||
boolean hasSameY = false;
|
||||
for (Entry e : values) {
|
||||
i++;
|
||||
if (lastEntry != null) {
|
||||
if (lastEntry.getY() == e.getY() && i < lastIndex) {
|
||||
hasSameY = true;
|
||||
continue;
|
||||
} else if (hasSameY) {
|
||||
lastEntry.setX(lastEntry.getX() + (e.getX() - lastEntry.getX()) / 2f);
|
||||
hasSameY = false;
|
||||
}
|
||||
}
|
||||
newValues.add(e);
|
||||
lastEntry = e;
|
||||
}
|
||||
*/
|
||||
|
||||
List<Point2D> points = new ArrayList<>(values.size());
|
||||
for (Entry e : values) {
|
||||
points.add(new Point2D(e.getX(), e.getY()));
|
||||
}
|
||||
List<Segment> spline = calculateSpline(points);
|
||||
if (spline != null) {
|
||||
int count = 8;
|
||||
values = new ArrayList<>();
|
||||
for (Segment s : spline) {
|
||||
Point2D p = new Point2D();
|
||||
for (i = 0; i < count; ++i) {
|
||||
s.calc((double) i / (double) count, p);
|
||||
values.add(new Entry((float) p.x, (float) p.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
List<Entry> values = calculateElevationArray(analysis, divX, convEle);
|
||||
|
||||
OrderedLineDataSet dataSet = new OrderedLineDataSet(values, "", GPXDataSetType.ALTITUDE);
|
||||
dataSet.priority = (float) (analysis.avgElevation - analysis.minElevation) * convEle;
|
||||
|
@ -1118,7 +1106,7 @@ public class GpxUiHelper {
|
|||
dataSet.setDrawHorizontalHighlightIndicator(false);
|
||||
dataSet.setHighLightColor(light ? mChart.getResources().getColor(R.color.secondary_text_light) : mChart.getResources().getColor(R.color.secondary_text_dark));
|
||||
|
||||
//dataSet.setCubicIntensity(.2f);
|
||||
//dataSet.setMode(LineDataSet.Mode.HORIZONTAL_BEZIER);
|
||||
//dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
|
||||
|
||||
dataSet.setFillFormatter(new IFillFormatter() {
|
||||
|
@ -1271,16 +1259,19 @@ public class GpxUiHelper {
|
|||
mChart.setData(data);
|
||||
}
|
||||
|
||||
public static OrderedLineDataSet createGPXSlopeDataSet(OsmandApplication ctx, LineChart mChart, GPXTrackAnalysis analysis, boolean useRightAxis, boolean drawFilled) {
|
||||
public static OrderedLineDataSet createGPXSlopeDataSet(OsmandApplication ctx, LineChart mChart, GPXTrackAnalysis analysis, List<Entry> eleValues, boolean useRightAxis, boolean drawFilled) {
|
||||
OsmandSettings settings = ctx.getSettings();
|
||||
boolean light = settings.isLightContent();
|
||||
final float meters = analysis.totalDistance;
|
||||
OsmandSettings.MetricsConstants mc = settings.METRIC_SYSTEM.get();
|
||||
boolean useFeet = (mc == OsmandSettings.MetricsConstants.MILES_AND_FEET) || (mc == OsmandSettings.MetricsConstants.MILES_AND_YARDS);
|
||||
final float convEle = useFeet ? 3.28084f : 1.0f;
|
||||
final float totalDistance = analysis.totalDistance;
|
||||
|
||||
float[] koef = new float[] { 1f };
|
||||
StringBuilder fmt = new StringBuilder();
|
||||
StringBuilder unitX = new StringBuilder();
|
||||
|
||||
float granularity = getXAxisParams(ctx, meters, koef, fmt, unitX);
|
||||
float granularity = getXAxisParams(ctx, totalDistance, koef, fmt, unitX);
|
||||
float divX = koef[0];
|
||||
final String formatX = fmt.toString();
|
||||
final String mainUnitX = unitX.toString();
|
||||
|
@ -1319,174 +1310,21 @@ public class GpxUiHelper {
|
|||
}
|
||||
});
|
||||
|
||||
/*
|
||||
List<Entry> values = new ArrayList<>();
|
||||
List<Elevation> elevationData = analysis.elevationData;
|
||||
float nextX = 0;
|
||||
float nextY;
|
||||
float elev;
|
||||
float prevElev = -80000;
|
||||
int i = -1;
|
||||
int lastIndex = elevationData.size() - 1;
|
||||
float shift = 0f;
|
||||
Entry entry = null;
|
||||
for (Elevation e : elevationData) {
|
||||
i++;
|
||||
if (e.distance > 0) {
|
||||
nextX += (float) e.distance / divX;
|
||||
elev = (float) e.elevation;
|
||||
nextY = elev + shift;
|
||||
entry = new Entry(nextX, nextY);
|
||||
values.add(entry);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
List<Entry> values = new ArrayList<>();
|
||||
List<Elevation> elevationData = analysis.elevationData;
|
||||
float nextX = 0;
|
||||
float nextY;
|
||||
float elev;
|
||||
float prevElev = -80000;
|
||||
int i = -1;
|
||||
int lastIndex = elevationData.size() - 1;
|
||||
float shift = 0f;
|
||||
Entry entry = null;
|
||||
for (Elevation e : elevationData) {
|
||||
i++;
|
||||
if (e.distance > 0) {
|
||||
nextX += (float) e.distance;
|
||||
elev = (float) e.elevation;
|
||||
if (prevElev != -80000) {
|
||||
if (elev < prevElev) {
|
||||
shift = 0f;
|
||||
} else if (elev > prevElev) {
|
||||
shift = -1f;
|
||||
} else if (prevElev == elev && i < lastIndex) {
|
||||
values.add(new Entry(nextX, entry.getY()));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
prevElev = elev;
|
||||
nextY = (elev + shift);
|
||||
entry = new Entry(nextX, nextY);
|
||||
values.add(entry);
|
||||
List<Entry> values;
|
||||
if (eleValues == null) {
|
||||
values = calculateElevationArray(analysis, 1f, 1f);
|
||||
} else {
|
||||
values = new ArrayList<>(eleValues.size());
|
||||
for (Entry e : eleValues) {
|
||||
values.add(new Entry(e.getX() * divX, e.getY() / convEle));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
List<Entry> eleValues = new ArrayList<>();
|
||||
Entry lastEntry = null;
|
||||
i = -1;
|
||||
lastIndex = values.size() - 1;
|
||||
boolean hasSameY = false;
|
||||
for (Entry e : values) {
|
||||
i++;
|
||||
if (lastEntry != null) {
|
||||
if (lastEntry.getY() == e.getY() && i < lastIndex) {
|
||||
hasSameY = true;
|
||||
continue;
|
||||
} else if (hasSameY) {
|
||||
lastEntry.setX(lastEntry.getX() + (e.getX() - lastEntry.getX()) / 2f);
|
||||
hasSameY = false;
|
||||
}
|
||||
}
|
||||
eleValues.add(e);
|
||||
lastEntry = e;
|
||||
if (values == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Point2D> points = new ArrayList<>(eleValues.size());
|
||||
for (Entry e : eleValues) {
|
||||
points.add(new Point2D(e.getX(), e.getY()));
|
||||
}
|
||||
List<Segment> spline = calculateSpline(points);
|
||||
if (spline != null) {
|
||||
int count = 8;
|
||||
eleValues = new ArrayList<>();
|
||||
for (Segment s : spline) {
|
||||
Point2D p = new Point2D();
|
||||
for (i = 0; i < count; ++i) {
|
||||
s.calc((double) i / (double) count, p);
|
||||
eleValues.add(new Entry((float) p.x, (float) p.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
values.clear();
|
||||
//List<Elevation> elevationData = analysis.elevationData;
|
||||
//float nextX;
|
||||
//float nextY;
|
||||
float nextXM;
|
||||
float nextYM;
|
||||
float prevXM;
|
||||
float prevYM;
|
||||
float delta = 150;
|
||||
float prevDistM = -1;
|
||||
float nextDistM;
|
||||
float d;
|
||||
if (eleValues.size() > 1) {
|
||||
nextXM = eleValues.get(0).getX();
|
||||
nextYM = eleValues.get(0).getY();
|
||||
prevXM = nextXM;
|
||||
prevYM = 0;
|
||||
nextX = 0;
|
||||
nextY = 0;
|
||||
for (i = 1; i < eleValues.size(); i++) {
|
||||
Entry e = eleValues.get(i);
|
||||
d = e.getX() - prevXM;
|
||||
if (d < delta && i < eleValues.size() - 1) {
|
||||
continue;
|
||||
}
|
||||
if (prevDistM < 0) {
|
||||
nextDistM = d / 2f;
|
||||
} else {
|
||||
nextDistM = prevDistM / 2f + d / 2f;
|
||||
}
|
||||
prevDistM = d;
|
||||
if (nextX == 0) {
|
||||
values.add(new Entry(prevXM / divX, 0));
|
||||
prevXM = nextXM;
|
||||
prevYM = nextYM;
|
||||
}
|
||||
nextXM = e.getX();
|
||||
nextYM = e.getY();
|
||||
nextX = (prevXM + nextDistM) / divX;
|
||||
nextY = (nextYM - prevYM) / (nextXM - prevXM) * 100f;
|
||||
if (Math.abs(nextY) < 120) {
|
||||
values.add(new Entry(nextX, nextY));
|
||||
prevXM = nextXM;
|
||||
prevYM = nextYM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
points = new ArrayList<>(values.size());
|
||||
for (Entry e : values) {
|
||||
points.add(new Point2D(e.getX(), e.getY()));
|
||||
}
|
||||
spline = calculateSpline(points);
|
||||
if (spline != null) {
|
||||
int count = 8;
|
||||
values = new ArrayList<>();
|
||||
for (Segment s : spline) {
|
||||
Point2D p = new Point2D();
|
||||
for (i = 0; i < count; ++i) {
|
||||
s.calc((double) i / (double) count, p);
|
||||
values.add(new Entry((float) p.x, (float) p.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
double totalDistance = meters;
|
||||
double[] dist = new double[values.size()];
|
||||
double[] h = new double[values.size()];
|
||||
i = 0;
|
||||
for (Entry e : values) {
|
||||
dist[i] = e.getX();
|
||||
h[i] = e.getY();
|
||||
i++;
|
||||
}
|
||||
int lastIndex = values.size() - 1;
|
||||
|
||||
double STEP = 5;
|
||||
|
||||
|
@ -1497,34 +1335,56 @@ public class GpxUiHelper {
|
|||
if (k > 0) {
|
||||
calculatedDist[k] = calculatedDist[k - 1] + STEP;
|
||||
}
|
||||
while(nextW < lastIndex && calculatedDist[k] > dist[nextW]) {
|
||||
while(nextW < lastIndex && calculatedDist[k] > values.get(nextW).getX()) {
|
||||
nextW ++;
|
||||
}
|
||||
double pd = nextW == 0 ? 0 : dist[nextW - 1];
|
||||
double ph = nextW == 0 ? h[0] : h[nextW - 1];
|
||||
calculatedH[k] = ph + (h[nextW] - ph) / (dist[nextW] - pd) * (calculatedDist[k] - pd);
|
||||
double pd = nextW == 0 ? 0 : values.get(nextW - 1).getX();
|
||||
double ph = nextW == 0 ? values.get(0).getY() : values.get(nextW - 1).getY();
|
||||
calculatedH[k] = ph + (values.get(nextW).getY() - ph) / (values.get(nextW).getX() - pd) * (calculatedDist[k] - pd);
|
||||
}
|
||||
|
||||
double GREEN_PROXIMITY = 150;
|
||||
double SLOPE_PROXIMITY = 150;
|
||||
|
||||
double[] calculatedGreenDist = new double[(int) ((totalDistance - GREEN_PROXIMITY) / STEP) + 1];
|
||||
double[] calculatedGreenH = new double[(int) ((totalDistance - GREEN_PROXIMITY) / STEP) + 1];
|
||||
double[] calculatedSlopeDist = new double[(int) ((totalDistance - SLOPE_PROXIMITY) / STEP) + 1];
|
||||
double[] calculatedSlope = new double[(int) ((totalDistance - SLOPE_PROXIMITY) / STEP) + 1];
|
||||
|
||||
int index = (int) ((GREEN_PROXIMITY / STEP) / 2);
|
||||
for (int k = 0; k < calculatedGreenDist.length; k++) {
|
||||
calculatedGreenDist[k] = calculatedDist[index + k];
|
||||
calculatedGreenH[k] = (calculatedH[ 2 * index + k] - calculatedH[k]) * 100 / GREEN_PROXIMITY;
|
||||
if (Double.isNaN(calculatedGreenH[k])) {
|
||||
calculatedGreenH[k] = 0;
|
||||
int index = (int) ((SLOPE_PROXIMITY / STEP) / 2);
|
||||
for (int k = 0; k < calculatedSlopeDist.length; k++) {
|
||||
calculatedSlopeDist[k] = calculatedDist[index + k];
|
||||
calculatedSlope[k] = (calculatedH[ 2 * index + k] - calculatedH[k]) * 100 / SLOPE_PROXIMITY;
|
||||
if (Double.isNaN(calculatedSlope[k])) {
|
||||
calculatedSlope[k] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
values.clear();
|
||||
for (i = 0; i < calculatedGreenDist.length; i++) {
|
||||
values.add(new Entry((float) calculatedGreenDist[i] / divX, (float) calculatedGreenH[i]));
|
||||
List<Entry> slopeValues = new ArrayList<>(calculatedSlopeDist.length);
|
||||
float prevSlope = -80000;
|
||||
float slope;
|
||||
float x;
|
||||
float lastXSameY = 0;
|
||||
boolean hasSameY = false;
|
||||
Entry lastEntry = null;
|
||||
lastIndex = calculatedSlopeDist.length - 1;
|
||||
for (int i = 0; i < calculatedSlopeDist.length; i++) {
|
||||
x = (float) calculatedSlopeDist[i] / divX;
|
||||
slope = (float) calculatedSlope[i];
|
||||
if (prevSlope != -80000) {
|
||||
if (prevSlope == slope && i < lastIndex) {
|
||||
hasSameY = true;
|
||||
lastXSameY = x;
|
||||
continue;
|
||||
}
|
||||
if (hasSameY) {
|
||||
slopeValues.add(new Entry(lastXSameY, lastEntry.getY()));
|
||||
}
|
||||
hasSameY = false;
|
||||
}
|
||||
prevSlope = slope;
|
||||
lastEntry = new Entry(x, slope);
|
||||
slopeValues.add(lastEntry);
|
||||
}
|
||||
|
||||
OrderedLineDataSet dataSet = new OrderedLineDataSet(values, "", GPXDataSetType.SLOPE);
|
||||
OrderedLineDataSet dataSet = new OrderedLineDataSet(slopeValues, "", GPXDataSetType.SLOPE);
|
||||
dataSet.units = mainUnitY;
|
||||
|
||||
dataSet.setColor(ContextCompat.getColor(mChart.getContext(), R.color.gpx_chart_green));
|
||||
|
@ -1551,6 +1411,7 @@ public class GpxUiHelper {
|
|||
dataSet.setHighLightColor(light ? mChart.getResources().getColor(R.color.secondary_text_light) : mChart.getResources().getColor(R.color.secondary_text_dark));
|
||||
|
||||
//dataSet.setMode(LineDataSet.Mode.HORIZONTAL_BEZIER);
|
||||
//dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
|
||||
|
||||
/*
|
||||
dataSet.setFillFormatter(new IFillFormatter() {
|
||||
|
@ -1567,7 +1428,7 @@ public class GpxUiHelper {
|
|||
}
|
||||
|
||||
public static void setGPXSlopeChartData(OsmandApplication ctx, LineChart mChart, GPXTrackAnalysis analysis, boolean useRightAxis, boolean drawFilled) {
|
||||
LineDataSet dataSet = createGPXSlopeDataSet(ctx, mChart, analysis, useRightAxis, drawFilled);
|
||||
LineDataSet dataSet = createGPXSlopeDataSet(ctx, mChart, analysis, null, useRightAxis, drawFilled);
|
||||
ArrayList<ILineDataSet> dataSets = new ArrayList<>();
|
||||
dataSets.add(dataSet);
|
||||
LineData data = new LineData(dataSets);
|
||||
|
@ -1586,15 +1447,32 @@ public class GpxUiHelper {
|
|||
|
||||
public float priority;
|
||||
public String units;
|
||||
public List<Segment> spline;
|
||||
|
||||
public OrderedLineDataSet(List<Entry> yVals, String label, GPXDataSetType dataSetType) {
|
||||
super(yVals, label);
|
||||
this.dataSetType = dataSetType;
|
||||
|
||||
/*
|
||||
List<Point2D> points = new ArrayList<>(yVals.size());
|
||||
for (Entry e : yVals) {
|
||||
points.add(new Point2D(e.getX(), e.getY()));
|
||||
}
|
||||
spline = calculateSpline(points);
|
||||
*/
|
||||
}
|
||||
|
||||
public GPXDataSetType getDataSetType() {
|
||||
return dataSetType;
|
||||
}
|
||||
|
||||
public Segment getSegmentForEntryIndex(int index) {
|
||||
if (index < spline.size()) {
|
||||
return spline.get(index);
|
||||
} else {
|
||||
return spline.get(spline.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
|
@ -1919,4 +1797,70 @@ public class GpxUiHelper {
|
|||
|
||||
return bezier;
|
||||
}
|
||||
|
||||
public static class SplineRenderer extends LineChartRenderer {
|
||||
|
||||
public SplineRenderer(LineDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
|
||||
super(chart, animator, viewPortHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawCubicBezier(ILineDataSet dataSet) {
|
||||
if (!(dataSet instanceof OrderedLineDataSet)) {
|
||||
super.drawCubicBezier(dataSet);
|
||||
} else {
|
||||
|
||||
OrderedLineDataSet ds = (OrderedLineDataSet) dataSet;
|
||||
|
||||
float phaseY = mAnimator.getPhaseY();
|
||||
|
||||
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
|
||||
|
||||
mXBounds.set(mChart, dataSet);
|
||||
|
||||
cubicPath.reset();
|
||||
|
||||
if (mXBounds.range >= 1) {
|
||||
|
||||
final int firstIndex = mXBounds.min + 1;
|
||||
final int lastIndex = mXBounds.min + mXBounds.range;
|
||||
|
||||
Segment seg = ds.getSegmentForEntryIndex(Math.max(firstIndex - 1, 0));
|
||||
|
||||
if (seg == null) return;
|
||||
|
||||
// let the spline start
|
||||
cubicPath.moveTo((float) seg.points[0].x, (float) seg.points[0].y * phaseY);
|
||||
|
||||
for (int j = firstIndex; j <= lastIndex; j++) {
|
||||
|
||||
seg = ds.getSegmentForEntryIndex(j);
|
||||
|
||||
cubicPath.cubicTo((float) seg.points[1].x, (float) seg.points[1].y * phaseY,
|
||||
(float) seg.points[2].x, (float) seg.points[2].y * phaseY,
|
||||
(float) seg.points[3].x, (float) seg.points[3].y * phaseY);
|
||||
}
|
||||
}
|
||||
|
||||
// if filled is enabled, close the path
|
||||
if (ds.isDrawFilledEnabled()) {
|
||||
|
||||
cubicFillPath.reset();
|
||||
cubicFillPath.addPath(cubicPath);
|
||||
|
||||
drawCubicFill(mBitmapCanvas, ds, cubicFillPath, trans, mXBounds);
|
||||
}
|
||||
|
||||
mRenderPaint.setColor(ds.getColor());
|
||||
|
||||
mRenderPaint.setStyle(Paint.Style.STROKE);
|
||||
|
||||
trans.pathValueToPixel(cubicPath);
|
||||
|
||||
mBitmapCanvas.drawPath(cubicPath, mRenderPaint);
|
||||
|
||||
mRenderPaint.setPathEffect(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -542,6 +542,11 @@ public class TrackSegmentFragment extends OsmAndListFragment {
|
|||
super(getActivity(), R.layout.gpx_list_item_tab_content, items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
|
@ -740,7 +745,8 @@ public class TrackSegmentFragment extends OsmAndListFragment {
|
|||
case GPX_TAB_ITEM_GENERAL:
|
||||
if (analysis != null) {
|
||||
List<ILineDataSet> dataSets = new LinkedList<>();
|
||||
if (analysis.elevationData != null || analysis.isSpeedSpecified()) {
|
||||
if ((analysis.elevationData != null && analysis.totalDistance > 0)
|
||||
|| analysis.isSpeedSpecified()) {
|
||||
GpxUiHelper.setupGPXChart(app, chart, 4);
|
||||
OrderedLineDataSet speedDataSet = null;
|
||||
OrderedLineDataSet elevationDataSet = null;
|
||||
|
@ -810,13 +816,13 @@ public class TrackSegmentFragment extends OsmAndListFragment {
|
|||
break;
|
||||
case GPX_TAB_ITEM_ALTITUDE:
|
||||
if (analysis != null) {
|
||||
if (analysis.elevationData != null) {
|
||||
if (analysis.elevationData != null && analysis.totalDistance > 0) {
|
||||
GpxUiHelper.setupGPXChart(app, chart, 4);
|
||||
List<ILineDataSet> dataSets = new ArrayList<>();
|
||||
OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, analysis, false, true);
|
||||
dataSets.add(elevationDataSet);
|
||||
if (analysis.elevationData.size() > 1) {
|
||||
OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, analysis, true, true);
|
||||
OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, analysis, elevationDataSet.getValues(), true, true);
|
||||
dataSets.add(slopeDataSet);
|
||||
}
|
||||
LineData data = new LineData(dataSets);
|
||||
|
@ -861,8 +867,13 @@ public class TrackSegmentFragment extends OsmAndListFragment {
|
|||
break;
|
||||
case GPX_TAB_ITEM_SPEED:
|
||||
if (analysis != null && analysis.isSpeedSpecified()) {
|
||||
GpxUiHelper.setupGPXChart(app, chart, 4);
|
||||
GpxUiHelper.setGPXSpeedChartData(app, chart, analysis, false, true);
|
||||
if (analysis.totalDistance > 0) {
|
||||
GpxUiHelper.setupGPXChart(app, chart, 4);
|
||||
GpxUiHelper.setGPXSpeedChartData(app, chart, analysis, false, true);
|
||||
chart.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
chart.setVisibility(View.GONE);
|
||||
}
|
||||
((ImageView) view.findViewById(R.id.average_icon))
|
||||
.setImageDrawable(ic.getThemedIcon(R.drawable.ic_action_speed));
|
||||
((ImageView) view.findViewById(R.id.max_icon))
|
||||
|
|
Loading…
Reference in a new issue