forked from upstream-mirrors/OpenTracks
Refactor ChartView/ChartFragment to use ChartPoint.
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package de.dennisguse.opentracks.chart;
|
package de.dennisguse.opentracks.chart;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
@@ -44,7 +45,17 @@ public class ChartValueSeriesTest {
|
|||||||
R.string.description_elevation_metric,
|
R.string.description_elevation_metric,
|
||||||
R.string.description_elevation_imperial,
|
R.string.description_elevation_imperial,
|
||||||
R.color.chart_elevation_fill,
|
R.color.chart_elevation_fill,
|
||||||
R.color.chart_elevation_border);
|
R.color.chart_elevation_border) {
|
||||||
|
@Override
|
||||||
|
double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||||
|
return chartPoint.getElevation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean drawIfChartPointHasNoData() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -63,8 +74,8 @@ public class ChartValueSeriesTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSmallUpdates() {
|
public void testSmallUpdates() {
|
||||||
series.update(0);
|
series.update(new ChartPoint(0));
|
||||||
series.update(10);
|
series.update(new ChartPoint(10));
|
||||||
series.updateDimension();
|
series.updateDimension();
|
||||||
Assert.assertEquals(100, series.getInterval());
|
Assert.assertEquals(100, series.getInterval());
|
||||||
Assert.assertEquals(0, series.getMinMarkerValue());
|
Assert.assertEquals(0, series.getMinMarkerValue());
|
||||||
@@ -73,8 +84,8 @@ public class ChartValueSeriesTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBigUpdates() {
|
public void testBigUpdates() {
|
||||||
series.update(0);
|
series.update(new ChartPoint(0));
|
||||||
series.update(901);
|
series.update(new ChartPoint(901));
|
||||||
series.updateDimension();
|
series.updateDimension();
|
||||||
Assert.assertEquals(1000, series.getInterval());
|
Assert.assertEquals(1000, series.getInterval());
|
||||||
Assert.assertEquals(0, series.getMinMarkerValue());
|
Assert.assertEquals(0, series.getMinMarkerValue());
|
||||||
@@ -83,8 +94,8 @@ public class ChartValueSeriesTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNotZeroBasedUpdates() {
|
public void testNotZeroBasedUpdates() {
|
||||||
series.update(220);
|
series.update(new ChartPoint(220));
|
||||||
series.update(250);
|
series.update(new ChartPoint(250));
|
||||||
series.updateDimension();
|
series.updateDimension();
|
||||||
Assert.assertEquals(100, series.getInterval());
|
Assert.assertEquals(100, series.getInterval());
|
||||||
Assert.assertEquals(200, series.getMinMarkerValue());
|
Assert.assertEquals(200, series.getMinMarkerValue());
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.TrackStubUtils;
|
import de.dennisguse.opentracks.TrackStubUtils;
|
||||||
|
import de.dennisguse.opentracks.chart.ChartPoint;
|
||||||
import de.dennisguse.opentracks.chart.ChartView;
|
import de.dennisguse.opentracks.chart.ChartView;
|
||||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||||
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
|
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
|
||||||
@@ -74,10 +75,10 @@ public class ChartFragmentTest {
|
|||||||
TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint();
|
||||||
|
|
||||||
// No input.
|
// No input.
|
||||||
double[] point = chartFragment.createPendingPoint(trackPoint);
|
ChartPoint point = chartFragment.createPendingPoint(trackPoint);
|
||||||
Assert.assertEquals(Float.NaN, point[ChartView.HEART_RATE_SERIES + 1], 0.01);
|
Assert.assertEquals(Float.NaN, point.getHeartRate(), 0.01);
|
||||||
Assert.assertEquals(Float.NaN, point[ChartView.CADENCE_SERIES + 1], 0.01);
|
Assert.assertEquals(Float.NaN, point.getCadence(), 0.01);
|
||||||
Assert.assertEquals(Float.NaN, point[ChartView.POWER_SERIES + 1], 0.01);
|
Assert.assertEquals(Float.NaN, point.getPower(), 0.01);
|
||||||
|
|
||||||
// Input incorrect state.
|
// Input incorrect state.
|
||||||
// Creates SensorData.
|
// Creates SensorData.
|
||||||
@@ -85,9 +86,9 @@ public class ChartFragmentTest {
|
|||||||
trackPoint.setSensorDataSet(sensorDataSet);
|
trackPoint.setSensorDataSet(sensorDataSet);
|
||||||
// Test.
|
// Test.
|
||||||
point = chartFragment.createPendingPoint(trackPoint);
|
point = chartFragment.createPendingPoint(trackPoint);
|
||||||
Assert.assertEquals(Float.NaN, point[ChartView.HEART_RATE_SERIES + 1], 0.01);
|
Assert.assertEquals(Float.NaN, point.getHeartRate(), 0.01);
|
||||||
Assert.assertEquals(Float.NaN, point[ChartView.CADENCE_SERIES + 1], 0.01);
|
Assert.assertEquals(Float.NaN, point.getCadence(), 0.01);
|
||||||
Assert.assertEquals(Float.NaN, point[ChartView.POWER_SERIES + 1], 0.01);
|
Assert.assertEquals(Float.NaN, point.getPower(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,10 +98,10 @@ public class ChartFragmentTest {
|
|||||||
public void testCreatePendingPoint_sensorCorrect() {
|
public void testCreatePendingPoint_sensorCorrect() {
|
||||||
TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint();
|
||||||
// No input.
|
// No input.
|
||||||
double[] point = chartFragment.createPendingPoint(trackPoint);
|
ChartPoint point = chartFragment.createPendingPoint(trackPoint);
|
||||||
Assert.assertEquals(Float.NaN, point[ChartView.HEART_RATE_SERIES + 1], 0.01);
|
Assert.assertEquals(Float.NaN, point.getHeartRate(), 0.01);
|
||||||
Assert.assertEquals(Float.NaN, point[ChartView.CADENCE_SERIES + 1], 0.01);
|
Assert.assertEquals(Float.NaN, point.getCadence(), 0.01);
|
||||||
Assert.assertEquals(Float.NaN, point[ChartView.POWER_SERIES + 1], 0.01);
|
Assert.assertEquals(Float.NaN, point.getPower(), 0.01);
|
||||||
|
|
||||||
// Creates SensorData.
|
// Creates SensorData.
|
||||||
SensorDataSet sensorDataSet = new SensorDataSet(100, 101, 102);
|
SensorDataSet sensorDataSet = new SensorDataSet(100, 101, 102);
|
||||||
@@ -109,9 +110,9 @@ public class ChartFragmentTest {
|
|||||||
trackPoint.setSensorDataSet(sensorDataSet);
|
trackPoint.setSensorDataSet(sensorDataSet);
|
||||||
// Test.
|
// Test.
|
||||||
point = chartFragment.createPendingPoint(trackPoint);
|
point = chartFragment.createPendingPoint(trackPoint);
|
||||||
Assert.assertEquals(100.0, point[ChartView.HEART_RATE_SERIES + 1], 0.01);
|
Assert.assertEquals(100.0, point.getHeartRate(), 0.01);
|
||||||
Assert.assertEquals(101.0, point[ChartView.CADENCE_SERIES + 1], 0.01);
|
Assert.assertEquals(101.0, point.getCadence(), 0.01);
|
||||||
Assert.assertEquals(102.0, point[ChartView.POWER_SERIES + 1], 0.01);
|
Assert.assertEquals(102.0, point.getPower(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,13 +123,13 @@ public class ChartFragmentTest {
|
|||||||
chartFragment.setChartByDistance(true);
|
chartFragment.setChartByDistance(true);
|
||||||
// Resets last location and writes first location.
|
// Resets last location and writes first location.
|
||||||
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
double[] point = chartFragment.createPendingPoint(trackPoint1);
|
ChartPoint point = chartFragment.createPendingPoint(trackPoint1);
|
||||||
Assert.assertEquals(0.0, point[0], 0.01);
|
Assert.assertEquals(0.0, point.getTimeOrDistance(), 0.01);
|
||||||
|
|
||||||
// The second is a same location, just different time.
|
// The second is a same location, just different time.
|
||||||
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
point = chartFragment.createPendingPoint(trackPoint2);
|
point = chartFragment.createPendingPoint(trackPoint2);
|
||||||
Assert.assertEquals(0.0, point[0], 0.01);
|
Assert.assertEquals(0.0, point.getTimeOrDistance(), 0.01);
|
||||||
|
|
||||||
// The third location is a new location, and use metric.
|
// The third location is a new location, and use metric.
|
||||||
TrackPoint trackPoint3 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint3 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
@@ -140,7 +141,7 @@ public class ChartFragmentTest {
|
|||||||
Location.distanceBetween(trackPoint2.getLatitude(), trackPoint2.getLongitude(),
|
Location.distanceBetween(trackPoint2.getLatitude(), trackPoint2.getLongitude(),
|
||||||
trackPoint3.getLatitude(), trackPoint3.getLongitude(), results);
|
trackPoint3.getLatitude(), trackPoint3.getLongitude(), results);
|
||||||
double distance1 = results[0] * UnitConversions.M_TO_KM;
|
double distance1 = results[0] * UnitConversions.M_TO_KM;
|
||||||
Assert.assertEquals(distance1, point[0], 0.01);
|
Assert.assertEquals(distance1, point.getTimeOrDistance(), 0.01);
|
||||||
|
|
||||||
// The fourth location is a new location, and use metric.
|
// The fourth location is a new location, and use metric.
|
||||||
TrackPoint trackPoint4 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint4 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
@@ -151,7 +152,7 @@ public class ChartFragmentTest {
|
|||||||
Location.distanceBetween(trackPoint3.getLatitude(), trackPoint3.getLongitude(),
|
Location.distanceBetween(trackPoint3.getLatitude(), trackPoint3.getLongitude(),
|
||||||
trackPoint4.getLatitude(), trackPoint4.getLongitude(), results);
|
trackPoint4.getLatitude(), trackPoint4.getLongitude(), results);
|
||||||
double distance2 = results[0] * UnitConversions.M_TO_KM;
|
double distance2 = results[0] * UnitConversions.M_TO_KM;
|
||||||
Assert.assertEquals((distance1 + distance2), point[0], 0.01);
|
Assert.assertEquals((distance1 + distance2), point.getTimeOrDistance(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -166,8 +167,8 @@ public class ChartFragmentTest {
|
|||||||
|
|
||||||
// The first is a same location, just different time.
|
// The first is a same location, just different time.
|
||||||
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
double[] point = chartFragment.createPendingPoint(trackPoint1);
|
ChartPoint point = chartFragment.createPendingPoint(trackPoint1);
|
||||||
Assert.assertEquals(0.0, point[0], 0.01);
|
Assert.assertEquals(0.0, point.getTimeOrDistance(), 0.01);
|
||||||
|
|
||||||
// The second location is a new location, and use imperial.
|
// The second location is a new location, and use imperial.
|
||||||
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
@@ -181,7 +182,7 @@ public class ChartFragmentTest {
|
|||||||
float[] results = new float[4];
|
float[] results = new float[4];
|
||||||
Location.distanceBetween(trackPoint1.getLatitude(), trackPoint1.getLongitude(), trackPoint2.getLatitude(), trackPoint2.getLongitude(), results);
|
Location.distanceBetween(trackPoint1.getLatitude(), trackPoint1.getLongitude(), trackPoint2.getLatitude(), trackPoint2.getLongitude(), results);
|
||||||
double distance1 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI;
|
double distance1 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI;
|
||||||
Assert.assertEquals(distance1, point[0], 0.01);
|
Assert.assertEquals(distance1, point.getTimeOrDistance(), 0.01);
|
||||||
|
|
||||||
// The third location is a new location, and use imperial.
|
// The third location is a new location, and use imperial.
|
||||||
TrackPoint trackPoint3 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint3 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
@@ -194,7 +195,7 @@ public class ChartFragmentTest {
|
|||||||
*/
|
*/
|
||||||
Location.distanceBetween(trackPoint2.getLatitude(), trackPoint2.getLongitude(), trackPoint3.getLatitude(), trackPoint3.getLongitude(), results);
|
Location.distanceBetween(trackPoint2.getLatitude(), trackPoint2.getLongitude(), trackPoint3.getLatitude(), trackPoint3.getLongitude(), results);
|
||||||
double distance2 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI;
|
double distance2 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI;
|
||||||
Assert.assertEquals(distance1 + distance2, point[0], 0.01);
|
Assert.assertEquals(distance1 + distance2, point.getTimeOrDistance(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -204,13 +205,13 @@ public class ChartFragmentTest {
|
|||||||
public void testCreatePendingPoint_time() {
|
public void testCreatePendingPoint_time() {
|
||||||
chartFragment.setChartByDistance(false);
|
chartFragment.setChartByDistance(false);
|
||||||
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
double[] point = chartFragment.createPendingPoint(trackPoint1);
|
ChartPoint point = chartFragment.createPendingPoint(trackPoint1);
|
||||||
Assert.assertEquals(0.0, point[0], 0.01);
|
Assert.assertEquals(0.0, point.getTimeOrDistance(), 0.01);
|
||||||
long timeSpan = 222;
|
long timeSpan = 222;
|
||||||
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
trackPoint2.setTime(trackPoint1.getTime() + timeSpan);
|
trackPoint2.setTime(trackPoint1.getTime() + timeSpan);
|
||||||
point = chartFragment.createPendingPoint(trackPoint2);
|
point = chartFragment.createPendingPoint(trackPoint2);
|
||||||
Assert.assertEquals((double) timeSpan, point[0], 0.01);
|
Assert.assertEquals((double) timeSpan, point.getTimeOrDistance(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -224,8 +225,8 @@ public class ChartFragmentTest {
|
|||||||
* At first, clear old points of elevation, so give true to the second parameter.
|
* At first, clear old points of elevation, so give true to the second parameter.
|
||||||
* Then only one value INITIAL_ALTITUDE in buffer.
|
* Then only one value INITIAL_ALTITUDE in buffer.
|
||||||
*/
|
*/
|
||||||
double[] point = chartFragment.createPendingPoint(trackPoint1);
|
ChartPoint point = chartFragment.createPendingPoint(trackPoint1);
|
||||||
Assert.assertEquals(TrackStubUtils.INITIAL_ALTITUDE, point[ChartView.ELEVATION_SERIES + 1], 0.01);
|
Assert.assertEquals(TrackStubUtils.INITIAL_ALTITUDE, point.getElevation(), 0.01);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send another value to buffer, now there are two values, INITIAL_ALTITUDE and INITIAL_ALTITUDE * 2.
|
* Send another value to buffer, now there are two values, INITIAL_ALTITUDE and INITIAL_ALTITUDE * 2.
|
||||||
@@ -233,7 +234,7 @@ public class ChartFragmentTest {
|
|||||||
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
trackPoint2.setAltitude(TrackStubUtils.INITIAL_ALTITUDE * 2);
|
trackPoint2.setAltitude(TrackStubUtils.INITIAL_ALTITUDE * 2);
|
||||||
point = chartFragment.createPendingPoint(trackPoint2);
|
point = chartFragment.createPendingPoint(trackPoint2);
|
||||||
Assert.assertEquals((TrackStubUtils.INITIAL_ALTITUDE + TrackStubUtils.INITIAL_ALTITUDE * 2) / 2.0, point[ChartView.ELEVATION_SERIES + 1], 0.01);
|
Assert.assertEquals((TrackStubUtils.INITIAL_ALTITUDE + TrackStubUtils.INITIAL_ALTITUDE * 2) / 2.0, point.getElevation(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -249,8 +250,8 @@ public class ChartFragmentTest {
|
|||||||
*/
|
*/
|
||||||
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
trackPoint1.setSpeed(128.5f);
|
trackPoint1.setSpeed(128.5f);
|
||||||
double[] point = chartFragment.createPendingPoint(trackPoint1);
|
ChartPoint point = chartFragment.createPendingPoint(trackPoint1);
|
||||||
Assert.assertEquals(0.0, point[ChartView.SPEED_SERIES + 1], 0.01);
|
Assert.assertEquals(0.0, point.getSpeed(), 0.01);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tests the logic when both metricUnits and reportSpeed are true.
|
* Tests the logic when both metricUnits and reportSpeed are true.
|
||||||
@@ -264,7 +265,7 @@ public class ChartFragmentTest {
|
|||||||
trackPoint2.setTime(trackPoint1.getTime() + 222);
|
trackPoint2.setTime(trackPoint1.getTime() + 222);
|
||||||
trackPoint2.setSpeed(130);
|
trackPoint2.setSpeed(130);
|
||||||
point = chartFragment.createPendingPoint(trackPoint2);
|
point = chartFragment.createPendingPoint(trackPoint2);
|
||||||
Assert.assertEquals(130.0 * UnitConversions.MS_TO_KMH, point[ChartView.SPEED_SERIES + 1], 0.01);
|
Assert.assertEquals(130.0 * UnitConversions.MS_TO_KMH, point.getSpeed(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -277,8 +278,8 @@ public class ChartFragmentTest {
|
|||||||
// First data point is not added to the speed buffer
|
// First data point is not added to the speed buffer
|
||||||
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
trackPoint1.setSpeed(100.0f);
|
trackPoint1.setSpeed(100.0f);
|
||||||
double[] point = chartFragment.createPendingPoint(trackPoint1);
|
ChartPoint point = chartFragment.createPendingPoint(trackPoint1);
|
||||||
Assert.assertEquals(0.0, point[ChartView.SPEED_SERIES + 1], 0.01);
|
Assert.assertEquals(0.0, point.getSpeed(), 0.01);
|
||||||
|
|
||||||
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
|
|
||||||
@@ -289,7 +290,7 @@ public class ChartFragmentTest {
|
|||||||
trackPoint2.setTime(trackPoint2.getTime() + 222);
|
trackPoint2.setTime(trackPoint2.getTime() + 222);
|
||||||
trackPoint2.setSpeed(102);
|
trackPoint2.setSpeed(102);
|
||||||
point = chartFragment.createPendingPoint(trackPoint2);
|
point = chartFragment.createPendingPoint(trackPoint2);
|
||||||
Assert.assertEquals(102.0 * UnitConversions.MS_TO_KMH * UnitConversions.KM_TO_MI, point[ChartView.SPEED_SERIES + 1], 0.01);
|
Assert.assertEquals(102.0 * UnitConversions.MS_TO_KMH * UnitConversions.KM_TO_MI, point.getSpeed(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -302,8 +303,8 @@ public class ChartFragmentTest {
|
|||||||
// First data point is not added to the speed buffer
|
// First data point is not added to the speed buffer
|
||||||
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
trackPoint1.setSpeed(100.0f);
|
trackPoint1.setSpeed(100.0f);
|
||||||
double[] point = chartFragment.createPendingPoint(trackPoint1);
|
ChartPoint point = chartFragment.createPendingPoint(trackPoint1);
|
||||||
Assert.assertEquals(0.0, point[ChartView.SPEED_SERIES + 1], 0.01);
|
Assert.assertEquals(0.0, point.getSpeed(), 0.01);
|
||||||
|
|
||||||
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
||||||
|
|
||||||
@@ -314,7 +315,7 @@ public class ChartFragmentTest {
|
|||||||
trackPoint2.setTime(trackPoint2.getTime() + 222);
|
trackPoint2.setTime(trackPoint2.getTime() + 222);
|
||||||
trackPoint2.setSpeed(102);
|
trackPoint2.setSpeed(102);
|
||||||
point = chartFragment.createPendingPoint(trackPoint2);
|
point = chartFragment.createPendingPoint(trackPoint2);
|
||||||
Assert.assertEquals(HOURS_PER_UNIT / (102.0 * UnitConversions.MS_TO_KMH), point[ChartView.PACE_SERIES + 1], 0.01);
|
Assert.assertEquals(HOURS_PER_UNIT / (102.0 * UnitConversions.MS_TO_KMH), point.getPace(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -325,7 +326,7 @@ public class ChartFragmentTest {
|
|||||||
chartFragment.setReportSpeed(false);
|
chartFragment.setReportSpeed(false);
|
||||||
TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint();
|
TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint();
|
||||||
trackPoint.setSpeed(0);
|
trackPoint.setSpeed(0);
|
||||||
double[] point = chartFragment.createPendingPoint(trackPoint);
|
ChartPoint point = chartFragment.createPendingPoint(trackPoint);
|
||||||
Assert.assertEquals(0.0, point[ChartView.PACE_SERIES + 1], 0.01);
|
Assert.assertEquals(0.0, point.getPace(), 0.01);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
if (recordingTrackId == -1L) {
|
if (recordingTrackId == -1L) {
|
||||||
TrackRecordingServiceInterface service = trackRecordingServiceConnection.getServiceIfBound();
|
TrackRecordingServiceInterface service = trackRecordingServiceConnection.getServiceIfBound();
|
||||||
if (service == null) {
|
if (service == null) {
|
||||||
Log.d(TAG, "it could not get service");
|
Log.d(TAG, "could not get TrackRecordingService");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
package de.dennisguse.opentracks.chart;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
|
||||||
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
|
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
||||||
|
import de.dennisguse.opentracks.util.UnitConversions;
|
||||||
|
|
||||||
|
public class ChartPoint {
|
||||||
|
//X-axis
|
||||||
|
private double timeOrDistance;
|
||||||
|
|
||||||
|
//Y-axis
|
||||||
|
private double elevation;
|
||||||
|
private double speed;
|
||||||
|
private double pace;
|
||||||
|
private double heartRate = Double.NaN;
|
||||||
|
private double cadence = Double.NaN;
|
||||||
|
private double power = Double.NaN;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
ChartPoint(double elevation) {
|
||||||
|
this.elevation = elevation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChartPoint(@NonNull TrackStatisticsUpdater trackStatisticsUpdater, SensorDataSet sensorDataSet, boolean chartByDistance, boolean metricUnits) {
|
||||||
|
TrackStatistics trackStatistics = trackStatisticsUpdater.getTrackStatistics();
|
||||||
|
|
||||||
|
if (chartByDistance) {
|
||||||
|
double distance = trackStatistics.getTotalDistance() * UnitConversions.M_TO_KM;
|
||||||
|
if (!metricUnits) {
|
||||||
|
distance *= UnitConversions.KM_TO_MI;
|
||||||
|
}
|
||||||
|
timeOrDistance = distance;
|
||||||
|
} else {
|
||||||
|
timeOrDistance = trackStatistics.getTotalTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
elevation = trackStatisticsUpdater.getSmoothedElevation();
|
||||||
|
if (!metricUnits) {
|
||||||
|
elevation *= UnitConversions.M_TO_FT;
|
||||||
|
}
|
||||||
|
|
||||||
|
speed = trackStatisticsUpdater.getSmoothedSpeed() * UnitConversions.MS_TO_KMH;
|
||||||
|
if (!metricUnits) {
|
||||||
|
speed *= UnitConversions.KM_TO_MI;
|
||||||
|
}
|
||||||
|
pace = speed == 0 ? 0.0 : 60.0 / speed;
|
||||||
|
if (sensorDataSet != null) {
|
||||||
|
if (sensorDataSet.hasHeartRate()) {
|
||||||
|
heartRate = sensorDataSet.getHeartRate();
|
||||||
|
}
|
||||||
|
if (sensorDataSet.hasCadence()) {
|
||||||
|
cadence = sensorDataSet.getCadence();
|
||||||
|
}
|
||||||
|
if (sensorDataSet.hasPower()) {
|
||||||
|
power = sensorDataSet.getPower();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getTimeOrDistance() {
|
||||||
|
return timeOrDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getElevation() {
|
||||||
|
return elevation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getSpeed() {
|
||||||
|
return speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPace() {
|
||||||
|
return pace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasHeartRate() {
|
||||||
|
return Double.isNaN(heartRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHeartRate() {
|
||||||
|
return heartRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasCadence() {
|
||||||
|
return Double.isNaN(cadence);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getCadence() {
|
||||||
|
return cadence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPower() {
|
||||||
|
return Double.isNaN(power);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPower() {
|
||||||
|
return power;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,8 @@ import android.graphics.Paint.Align;
|
|||||||
import android.graphics.Paint.Style;
|
import android.graphics.Paint.Style;
|
||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.stats.ExtremityMonitor;
|
import de.dennisguse.opentracks.stats.ExtremityMonitor;
|
||||||
@@ -32,7 +34,7 @@ import de.dennisguse.opentracks.stats.ExtremityMonitor;
|
|||||||
*
|
*
|
||||||
* @author Sandor Dornbush
|
* @author Sandor Dornbush
|
||||||
*/
|
*/
|
||||||
class ChartValueSeries {
|
abstract class ChartValueSeries {
|
||||||
|
|
||||||
private static final float STROKE_WIDTH = 2f;
|
private static final float STROKE_WIDTH = 2f;
|
||||||
|
|
||||||
@@ -126,26 +128,26 @@ class ChartValueSeries {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the series with a new value.
|
* Updates the series with a new {@link ChartPoint}.
|
||||||
*
|
|
||||||
* @param value the new value
|
|
||||||
*/
|
*/
|
||||||
void update(double value) {
|
void update(ChartPoint chartPoint) {
|
||||||
extremityMonitor.update(value);
|
if (isChartPointValid(chartPoint)) {
|
||||||
|
extremityMonitor.update(extractDataFromChartPoint(chartPoint));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
abstract double extractDataFromChartPoint(@NonNull ChartPoint chartPoint);
|
||||||
* Gets the path.
|
|
||||||
*/
|
boolean isChartPointValid(@NonNull ChartPoint chartPoint) {
|
||||||
|
return !Double.isNaN(extractDataFromChartPoint(chartPoint));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract boolean drawIfChartPointHasNoData();
|
||||||
|
|
||||||
Path getPath() {
|
Path getPath() {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Draws the path on canvas.
|
|
||||||
*
|
|
||||||
* @param canvas the canvas
|
|
||||||
*/
|
|
||||||
void drawPath(Canvas canvas) {
|
void drawPath(Canvas canvas) {
|
||||||
canvas.drawPath(path, fillPaint);
|
canvas.drawPath(path, fillPaint);
|
||||||
canvas.drawPath(path, strokePaint);
|
canvas.drawPath(path, strokePaint);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import android.view.ScaleGestureDetector;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Scroller;
|
import android.widget.Scroller;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.view.GestureDetectorCompat;
|
import androidx.core.view.GestureDetectorCompat;
|
||||||
|
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
@@ -62,14 +63,6 @@ public class ChartView extends View {
|
|||||||
|
|
||||||
static final int Y_AXIS_INTERVALS = 5;
|
static final int Y_AXIS_INTERVALS = 5;
|
||||||
|
|
||||||
public static final int NUM_SERIES = 6;
|
|
||||||
public static final int ELEVATION_SERIES = 0;
|
|
||||||
public static final int SPEED_SERIES = 1;
|
|
||||||
public static final int PACE_SERIES = 2;
|
|
||||||
public static final int HEART_RATE_SERIES = 3;
|
|
||||||
public static final int CADENCE_SERIES = 4;
|
|
||||||
public static final int POWER_SERIES = 5;
|
|
||||||
|
|
||||||
private static final int TARGET_X_AXIS_INTERVALS = 4;
|
private static final int TARGET_X_AXIS_INTERVALS = 4;
|
||||||
|
|
||||||
private static final int MIN_ZOOM_LEVEL = 1;
|
private static final int MIN_ZOOM_LEVEL = 1;
|
||||||
@@ -89,8 +82,11 @@ public class ChartView extends View {
|
|||||||
X_FRACTION_FORMAT.setMinimumFractionDigits(1);
|
X_FRACTION_FORMAT.setMinimumFractionDigits(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ChartValueSeries[] series = new ChartValueSeries[NUM_SERIES];
|
private final List<ChartValueSeries> seriesList = new ArrayList<>();
|
||||||
private final List<double[]> chartData = new ArrayList<>();
|
private final ChartValueSeries speedSeries;
|
||||||
|
private final ChartValueSeries paceSeries;
|
||||||
|
|
||||||
|
private final List<ChartPoint> chartData = new ArrayList<>();
|
||||||
private final List<Waypoint> waypoints = new ArrayList<>();
|
private final List<Waypoint> waypoints = new ArrayList<>();
|
||||||
private final ExtremityMonitor xExtremityMonitor = new ExtremityMonitor();
|
private final ExtremityMonitor xExtremityMonitor = new ExtremityMonitor();
|
||||||
private final Paint axisPaint;
|
private final Paint axisPaint;
|
||||||
@@ -192,58 +188,124 @@ public class ChartView extends View {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
public ChartView(Context context, boolean chartByDistance) {
|
public ChartView(Context context, final boolean chartByDistance) {
|
||||||
super(context);
|
super(context);
|
||||||
this.chartByDistance = chartByDistance;
|
this.chartByDistance = chartByDistance;
|
||||||
|
|
||||||
series[ELEVATION_SERIES] = new ChartValueSeries(context,
|
seriesList.add(new ChartValueSeries(context,
|
||||||
Integer.MIN_VALUE,
|
Integer.MIN_VALUE,
|
||||||
Integer.MAX_VALUE,
|
Integer.MAX_VALUE,
|
||||||
new int[]{5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000},
|
new int[]{5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000},
|
||||||
R.string.description_elevation_metric,
|
R.string.description_elevation_metric,
|
||||||
R.string.description_elevation_imperial,
|
R.string.description_elevation_imperial,
|
||||||
R.color.chart_elevation_fill,
|
R.color.chart_elevation_fill,
|
||||||
R.color.chart_elevation_border);
|
R.color.chart_elevation_border) {
|
||||||
series[SPEED_SERIES] = new ChartValueSeries(context,
|
@Override
|
||||||
|
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||||
|
return chartPoint.getElevation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean drawIfChartPointHasNoData() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
speedSeries = new ChartValueSeries(context,
|
||||||
0,
|
0,
|
||||||
Integer.MAX_VALUE,
|
Integer.MAX_VALUE,
|
||||||
new int[]{1, 5, 10, 20, 50, 100},
|
new int[]{1, 5, 10, 20, 50, 100},
|
||||||
R.string.description_speed_metric,
|
R.string.description_speed_metric,
|
||||||
R.string.description_speed_imperial,
|
R.string.description_speed_imperial,
|
||||||
R.color.chart_speed_fill,
|
R.color.chart_speed_fill,
|
||||||
R.color.chart_speed_border);
|
R.color.chart_speed_border) {
|
||||||
series[PACE_SERIES] = new ChartValueSeries(context,
|
@Override
|
||||||
|
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||||
|
return chartPoint.getSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean drawIfChartPointHasNoData() {
|
||||||
|
return reportSpeed;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
seriesList.add(speedSeries);
|
||||||
|
|
||||||
|
paceSeries = new ChartValueSeries(context,
|
||||||
0,
|
0,
|
||||||
Integer.MAX_VALUE,
|
Integer.MAX_VALUE,
|
||||||
new int[]{1, 2, 5, 10, 15, 20, 30, 60, 120},
|
new int[]{1, 2, 5, 10, 15, 20, 30, 60, 120},
|
||||||
R.string.description_pace_metric,
|
R.string.description_pace_metric,
|
||||||
R.string.description_pace_imperial,
|
R.string.description_pace_imperial,
|
||||||
R.color.chart_pace_fill,
|
R.color.chart_pace_fill,
|
||||||
R.color.chart_pace_border);
|
R.color.chart_pace_border) {
|
||||||
series[HEART_RATE_SERIES] = new ChartValueSeries(context,
|
@Override
|
||||||
|
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||||
|
return chartPoint.getPace();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean drawIfChartPointHasNoData() {
|
||||||
|
return !reportSpeed;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
seriesList.add(paceSeries);
|
||||||
|
|
||||||
|
seriesList.add(new ChartValueSeries(context,
|
||||||
0,
|
0,
|
||||||
Integer.MAX_VALUE,
|
Integer.MAX_VALUE,
|
||||||
new int[]{25, 50},
|
new int[]{25, 50},
|
||||||
R.string.description_sensor_heart_rate,
|
R.string.description_sensor_heart_rate,
|
||||||
R.string.description_sensor_heart_rate,
|
R.string.description_sensor_heart_rate,
|
||||||
R.color.chart_heart_rate_fill,
|
R.color.chart_heart_rate_fill,
|
||||||
R.color.chart_heart_rate_border);
|
R.color.chart_heart_rate_border) {
|
||||||
series[CADENCE_SERIES] = new ChartValueSeries(context,
|
@Override
|
||||||
|
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||||
|
return chartPoint.getHeartRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean drawIfChartPointHasNoData() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
seriesList.add(new ChartValueSeries(context,
|
||||||
0,
|
0,
|
||||||
Integer.MAX_VALUE,
|
Integer.MAX_VALUE,
|
||||||
new int[]{5, 10, 25, 50},
|
new int[]{5, 10, 25, 50},
|
||||||
R.string.description_sensor_cadence,
|
R.string.description_sensor_cadence,
|
||||||
R.string.description_sensor_cadence,
|
R.string.description_sensor_cadence,
|
||||||
R.color.chart_cadence_fill,
|
R.color.chart_cadence_fill,
|
||||||
R.color.chart_cadence_border);
|
R.color.chart_cadence_border) {
|
||||||
series[POWER_SERIES] = new ChartValueSeries(context,
|
@Override
|
||||||
|
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||||
|
return chartPoint.getCadence();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean drawIfChartPointHasNoData() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
seriesList.add(new ChartValueSeries(context,
|
||||||
0,
|
0,
|
||||||
1000,
|
1000,
|
||||||
new int[]{5, 50, 100, 200},
|
new int[]{5, 50, 100, 200},
|
||||||
R.string.description_sensor_power,
|
R.string.description_sensor_power,
|
||||||
R.string.description_sensor_power,
|
R.string.description_sensor_power,
|
||||||
R.color.chart_power_fill,
|
R.color.chart_power_fill,
|
||||||
R.color.chart_power_border);
|
R.color.chart_power_border) {
|
||||||
|
@Override
|
||||||
|
protected double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) {
|
||||||
|
return chartPoint.getPower();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean drawIfChartPointHasNoData() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
float scale = context.getResources().getDisplayMetrics().density;
|
float scale = context.getResources().getDisplayMetrics().density;
|
||||||
|
|
||||||
@@ -279,6 +341,10 @@ public class ChartView extends View {
|
|||||||
setFocusable(true);
|
setFocusable(true);
|
||||||
setClickable(true);
|
setClickable(true);
|
||||||
updateDimensions();
|
updateDimensions();
|
||||||
|
|
||||||
|
// either speedSeries or paceSeries should be enabled.
|
||||||
|
speedSeries.setEnabled(reportSpeed);
|
||||||
|
paceSeries.setEnabled(!reportSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -286,15 +352,6 @@ public class ChartView extends View {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the enabled value for a chart value series.
|
|
||||||
*
|
|
||||||
* @param index the chart value series index
|
|
||||||
*/
|
|
||||||
public void setChartValueSeriesEnabled(int index, boolean enabled) {
|
|
||||||
series[index].setEnabled(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getMetricUnits() {
|
public boolean getMetricUnits() {
|
||||||
return metricUnits;
|
return metricUnits;
|
||||||
}
|
}
|
||||||
@@ -315,12 +372,30 @@ public class ChartView extends View {
|
|||||||
/**
|
/**
|
||||||
* Sets report speed.
|
* Sets report speed.
|
||||||
*
|
*
|
||||||
* @param value true to report speed
|
* @param value report speed (true) or pace (false)
|
||||||
*/
|
*/
|
||||||
public void setReportSpeed(boolean value) {
|
public void setReportSpeed(boolean value) {
|
||||||
reportSpeed = value;
|
reportSpeed = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean applyReportSpeed() {
|
||||||
|
if (reportSpeed) {
|
||||||
|
if (!speedSeries.isEnabled()) {
|
||||||
|
speedSeries.setEnabled(true);
|
||||||
|
paceSeries.setEnabled(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!paceSeries.isEnabled()) {
|
||||||
|
speedSeries.setEnabled(false);
|
||||||
|
paceSeries.setEnabled(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets show pointer.
|
* Sets show pointer.
|
||||||
*
|
*
|
||||||
@@ -335,15 +410,13 @@ public class ChartView extends View {
|
|||||||
*
|
*
|
||||||
* @param dataPoints an array of data points to be added
|
* @param dataPoints an array of data points to be added
|
||||||
*/
|
*/
|
||||||
public void addPendingPoints(List<double[]> dataPoints) {
|
public void addChartPoints(List<ChartPoint> dataPoints) {
|
||||||
synchronized (chartData) {
|
synchronized (chartData) {
|
||||||
chartData.addAll(dataPoints);
|
chartData.addAll(dataPoints);
|
||||||
for (double[] dataPoint : dataPoints) {
|
for (ChartPoint dataPoint : dataPoints) {
|
||||||
xExtremityMonitor.update(dataPoint[0]);
|
xExtremityMonitor.update(dataPoint.getTimeOrDistance());
|
||||||
for (int j = 0; j < series.length; j++) {
|
for (ChartValueSeries i : seriesList) {
|
||||||
if (!Double.isNaN(dataPoint[j + 1])) {
|
i.update(dataPoint);
|
||||||
series[j].update(dataPoint[j + 1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateDimensions();
|
updateDimensions();
|
||||||
@@ -536,7 +609,7 @@ public class ChartView extends View {
|
|||||||
* @param canvas the canvas
|
* @param canvas the canvas
|
||||||
*/
|
*/
|
||||||
private void drawDataSeries(Canvas canvas) {
|
private void drawDataSeries(Canvas canvas) {
|
||||||
for (ChartValueSeries chartValueSeries : series) {
|
for (ChartValueSeries chartValueSeries : seriesList) {
|
||||||
if (chartValueSeries.isEnabled() && chartValueSeries.hasData()) {
|
if (chartValueSeries.isEnabled() && chartValueSeries.hasData()) {
|
||||||
chartValueSeries.drawPath(canvas);
|
chartValueSeries.drawPath(canvas);
|
||||||
}
|
}
|
||||||
@@ -602,9 +675,8 @@ public class ChartView extends View {
|
|||||||
int lines = titleDimensions[0];
|
int lines = titleDimensions[0];
|
||||||
int lineHeight = titleDimensions[1];
|
int lineHeight = titleDimensions[1];
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int i = 0; i < series.length; i++) {
|
for (ChartValueSeries chartValueSeries : seriesList) {
|
||||||
ChartValueSeries chartValueSeries = series[i];
|
if (chartValueSeries.isEnabled() && chartValueSeries.hasData() || allowIfEmpty(chartValueSeries)) {
|
||||||
if (chartValueSeries.isEnabled() && chartValueSeries.hasData() || allowIfEmpty(i)) {
|
|
||||||
count++;
|
count++;
|
||||||
String title = getContext().getString(chartValueSeries.getTitleId(metricUnits));
|
String title = getContext().getString(chartValueSeries.getTitleId(metricUnits));
|
||||||
Paint paint = chartValueSeries.getTitlePaint();
|
Paint paint = chartValueSeries.getTitlePaint();
|
||||||
@@ -622,9 +694,8 @@ public class ChartView extends View {
|
|||||||
private int[] getTitleDimensions() {
|
private int[] getTitleDimensions() {
|
||||||
int lines = 0;
|
int lines = 0;
|
||||||
int lineHeight = 0;
|
int lineHeight = 0;
|
||||||
for (int i = 0; i < series.length; i++) {
|
for (ChartValueSeries chartValueSeries : seriesList) {
|
||||||
ChartValueSeries chartValueSeries = series[i];
|
if (chartValueSeries.isEnabled() && chartValueSeries.hasData() || allowIfEmpty(chartValueSeries)) {
|
||||||
if (chartValueSeries.isEnabled() && chartValueSeries.hasData() || allowIfEmpty(i)) {
|
|
||||||
lines++;
|
lines++;
|
||||||
String title = getContext().getString(chartValueSeries.getTitleId(metricUnits));
|
String title = getContext().getString(chartValueSeries.getTitleId(metricUnits));
|
||||||
Rect rect = getRect(chartValueSeries.getTitlePaint(), title);
|
Rect rect = getRect(chartValueSeries.getTitlePaint(), title);
|
||||||
@@ -728,10 +799,10 @@ public class ChartView extends View {
|
|||||||
canvas.drawLine(x, y, x, y + effectiveHeight, axisPaint);
|
canvas.drawLine(x, y, x, y + effectiveHeight, axisPaint);
|
||||||
|
|
||||||
int markerXPosition = x - spacer;
|
int markerXPosition = x - spacer;
|
||||||
for (int i = 0; i < series.length; i++) {
|
for (int i = 0; i < seriesList.size(); i++) {
|
||||||
int index = series.length - 1 - i;
|
int index = seriesList.size() - 1 - i;
|
||||||
ChartValueSeries chartValueSeries = series[index];
|
ChartValueSeries chartValueSeries = seriesList.get(index);
|
||||||
if (chartValueSeries.isEnabled() && chartValueSeries.hasData() || allowIfEmpty(index)) {
|
if (chartValueSeries.isEnabled() && chartValueSeries.hasData() || allowIfEmpty(chartValueSeries)) {
|
||||||
markerXPosition -= drawYAxisMarkers(chartValueSeries, canvas, markerXPosition) + spacer;
|
markerXPosition -= drawYAxisMarkers(chartValueSeries, canvas, markerXPosition) + spacer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -779,18 +850,34 @@ public class ChartView extends View {
|
|||||||
* @param canvas the canvas
|
* @param canvas the canvas
|
||||||
*/
|
*/
|
||||||
private void drawPointer(Canvas canvas) {
|
private void drawPointer(Canvas canvas) {
|
||||||
int index = -1;
|
//TODO pass chartValueSeries to 2nd if
|
||||||
for (int i = 0; i < series.length; i++) {
|
// int index = -1;
|
||||||
ChartValueSeries chartValueSeries = series[i];
|
// for (int i = 0; i < seriesList.size(); i++) {
|
||||||
|
// ChartValueSeries chartValueSeries = seriesList.get(i);
|
||||||
|
// if (chartValueSeries.isEnabled() && chartValueSeries.hasData()) {
|
||||||
|
// index = i;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (index != -1 && chartData.size() > 0) {
|
||||||
|
// int dx = getX(maxX) - pointer.getIntrinsicWidth() / 2;
|
||||||
|
// int dy = getY(seriesList.get(index), chartData.get(chartData.size() - 1)[index + 1])
|
||||||
|
// - pointer.getIntrinsicHeight();
|
||||||
|
// canvas.translate(dx, dy);
|
||||||
|
// pointer.draw(canvas);
|
||||||
|
// }
|
||||||
|
|
||||||
|
ChartValueSeries firstChartValueSeries = null;
|
||||||
|
for (ChartValueSeries chartValueSeries : seriesList) {
|
||||||
if (chartValueSeries.isEnabled() && chartValueSeries.hasData()) {
|
if (chartValueSeries.isEnabled() && chartValueSeries.hasData()) {
|
||||||
index = i;
|
firstChartValueSeries = chartValueSeries;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (index != -1 && chartData.size() > 0) {
|
if (firstChartValueSeries != null && chartData.size() > 0) {
|
||||||
int dx = getX(maxX) - pointer.getIntrinsicWidth() / 2;
|
int dx = getX(maxX) - pointer.getIntrinsicWidth() / 2;
|
||||||
int dy = getY(series[index], chartData.get(chartData.size() - 1)[index + 1])
|
double value = firstChartValueSeries.extractDataFromChartPoint(chartData.get(chartData.size() - 1));
|
||||||
- pointer.getIntrinsicHeight();
|
int dy = getY(firstChartValueSeries, value) - pointer.getIntrinsicHeight();
|
||||||
canvas.translate(dx, dy);
|
canvas.translate(dx, dy);
|
||||||
pointer.draw(canvas);
|
pointer.draw(canvas);
|
||||||
}
|
}
|
||||||
@@ -801,7 +888,7 @@ public class ChartView extends View {
|
|||||||
*/
|
*/
|
||||||
private void updatePaths() {
|
private void updatePaths() {
|
||||||
synchronized (chartData) {
|
synchronized (chartData) {
|
||||||
for (ChartValueSeries chartValueSeries : series) {
|
for (ChartValueSeries chartValueSeries : seriesList) {
|
||||||
chartValueSeries.getPath().reset();
|
chartValueSeries.getPath().reset();
|
||||||
}
|
}
|
||||||
drawPaths();
|
drawPaths();
|
||||||
@@ -813,17 +900,19 @@ public class ChartView extends View {
|
|||||||
* Draws all paths.
|
* Draws all paths.
|
||||||
*/
|
*/
|
||||||
private void drawPaths() {
|
private void drawPaths() {
|
||||||
boolean[] hasMoved = new boolean[series.length];
|
boolean[] hasMoved = new boolean[seriesList.size()];
|
||||||
|
|
||||||
for (double[] dataPoint : chartData) {
|
for (ChartPoint dataPoint : chartData) {
|
||||||
for (int j = 0; j < series.length; j++) {
|
for (int j = 0; j < seriesList.size(); j++) {
|
||||||
double value = dataPoint[j + 1];
|
ChartValueSeries chartValueSeries = seriesList.get(j);
|
||||||
|
|
||||||
|
|
||||||
|
double value = chartValueSeries.extractDataFromChartPoint(dataPoint);
|
||||||
if (Double.isNaN(value)) {
|
if (Double.isNaN(value)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ChartValueSeries chartValueSeries = series[j];
|
|
||||||
Path path = chartValueSeries.getPath();
|
Path path = chartValueSeries.getPath();
|
||||||
int x = getX(dataPoint[0]);
|
int x = getX(dataPoint.getTimeOrDistance());
|
||||||
int y = getY(chartValueSeries, value);
|
int y = getY(chartValueSeries, value);
|
||||||
if (!hasMoved[j]) {
|
if (!hasMoved[j]) {
|
||||||
hasMoved[j] = true;
|
hasMoved[j] = true;
|
||||||
@@ -839,20 +928,21 @@ public class ChartView extends View {
|
|||||||
* Closes all paths.
|
* Closes all paths.
|
||||||
*/
|
*/
|
||||||
private void closePaths() {
|
private void closePaths() {
|
||||||
for (int i = 0; i < series.length; i++) {
|
for (int i = 0; i < seriesList.size(); i++) {
|
||||||
int first = getFirstPopulatedChartDataIndex(i);
|
ChartValueSeries chartValueSeries = seriesList.get(i);
|
||||||
|
int first = getFirstPopulatedChartDataIndex(chartValueSeries);
|
||||||
|
|
||||||
if (first != -1) {
|
if (first != -1) {
|
||||||
int xCorner = getX(chartData.get(first)[0]);
|
int xCorner = getX(chartData.get(first).getTimeOrDistance());
|
||||||
int yCorner = topBorder + effectiveHeight;
|
int yCorner = topBorder + effectiveHeight;
|
||||||
ChartValueSeries chartValueSeries = series[i];
|
|
||||||
Path path = chartValueSeries.getPath();
|
Path path = chartValueSeries.getPath();
|
||||||
// Bottom right corner
|
// Bottom right corner
|
||||||
path.lineTo(getX(chartData.get(chartData.size() - 1)[0]), yCorner);
|
path.lineTo(getX(chartData.get(chartData.size() - 1).getTimeOrDistance()), yCorner);
|
||||||
// Bottom left corner
|
// Bottom left corner
|
||||||
path.lineTo(xCorner, yCorner);
|
path.lineTo(xCorner, yCorner);
|
||||||
// Top right corner
|
// Top right corner
|
||||||
path.lineTo(xCorner, getY(chartValueSeries, chartData.get(first)[i + 1]));
|
double value = chartValueSeries.extractDataFromChartPoint(chartData.get(first));
|
||||||
|
path.lineTo(xCorner, getY(chartValueSeries, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -860,12 +950,10 @@ public class ChartView extends View {
|
|||||||
/**
|
/**
|
||||||
* Finds the index of the first data point containing data for a series.
|
* Finds the index of the first data point containing data for a series.
|
||||||
* Returns -1 if no data point contains data for the series.
|
* Returns -1 if no data point contains data for the series.
|
||||||
*
|
|
||||||
* @param seriesIndex the series's index
|
|
||||||
*/
|
*/
|
||||||
private int getFirstPopulatedChartDataIndex(int seriesIndex) {
|
private int getFirstPopulatedChartDataIndex(ChartValueSeries chartValueSeries) {
|
||||||
for (int i = 0; i < chartData.size(); i++) {
|
for (int i = 0; i < chartData.size(); i++) {
|
||||||
if (!Double.isNaN(chartData.get(i)[seriesIndex + 1])) {
|
if (chartValueSeries.isChartPointValid(chartData.get(i))) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -877,7 +965,7 @@ public class ChartView extends View {
|
|||||||
*/
|
*/
|
||||||
private void updateDimensions() {
|
private void updateDimensions() {
|
||||||
maxX = xExtremityMonitor.hasData() ? xExtremityMonitor.getMax() : 1.0;
|
maxX = xExtremityMonitor.hasData() ? xExtremityMonitor.getMax() : 1.0;
|
||||||
for (ChartValueSeries chartValueSeries : series) {
|
for (ChartValueSeries chartValueSeries : seriesList) {
|
||||||
chartValueSeries.updateDimension();
|
chartValueSeries.updateDimension();
|
||||||
}
|
}
|
||||||
float density = getContext().getResources().getDisplayMetrics().density;
|
float density = getContext().getResources().getDisplayMetrics().density;
|
||||||
@@ -885,9 +973,9 @@ public class ChartView extends View {
|
|||||||
yAxisOffset = (int) (density * Y_AXIS_OFFSET);
|
yAxisOffset = (int) (density * Y_AXIS_OFFSET);
|
||||||
|
|
||||||
int markerLength = 0;
|
int markerLength = 0;
|
||||||
for (int i = 0; i < series.length; i++) {
|
for (int i = 0; i < seriesList.size(); i++) {
|
||||||
ChartValueSeries chartValueSeries = series[i];
|
ChartValueSeries chartValueSeries = seriesList.get(i);
|
||||||
if (chartValueSeries.isEnabled() && chartValueSeries.hasData() || allowIfEmpty(i)) {
|
if (chartValueSeries.isEnabled() && chartValueSeries.hasData() || allowIfEmpty(chartValueSeries)) {
|
||||||
Rect rect = getRect(chartValueSeries.getMarkerPaint(), chartValueSeries.getLargestMarker());
|
Rect rect = getRect(chartValueSeries.getMarkerPaint(), chartValueSeries.getLargestMarker());
|
||||||
markerLength += rect.width() + spacer;
|
markerLength += rect.width() + spacer;
|
||||||
}
|
}
|
||||||
@@ -980,22 +1068,12 @@ public class ChartView extends View {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the index is allowed when the chartData is empty.
|
* Returns true if the index is allowed when the chartData is empty.
|
||||||
*
|
|
||||||
* @param index the index
|
|
||||||
*/
|
*/
|
||||||
private boolean allowIfEmpty(int index) {
|
private boolean allowIfEmpty(ChartValueSeries chartValueSeries) {
|
||||||
if (!chartData.isEmpty()) {
|
if (!chartData.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (index) {
|
|
||||||
case ELEVATION_SERIES:
|
return chartValueSeries.drawIfChartPointHasNoData();
|
||||||
return true;
|
|
||||||
case SPEED_SERIES:
|
|
||||||
return reportSpeed;
|
|
||||||
case PACE_SERIES:
|
|
||||||
return !reportSpeed;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,18 +33,17 @@ import java.util.List;
|
|||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.TrackDetailActivity;
|
import de.dennisguse.opentracks.TrackDetailActivity;
|
||||||
|
import de.dennisguse.opentracks.chart.ChartPoint;
|
||||||
import de.dennisguse.opentracks.chart.ChartView;
|
import de.dennisguse.opentracks.chart.ChartView;
|
||||||
import de.dennisguse.opentracks.content.TrackDataHub;
|
import de.dennisguse.opentracks.content.TrackDataHub;
|
||||||
import de.dennisguse.opentracks.content.TrackDataListener;
|
import de.dennisguse.opentracks.content.TrackDataListener;
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||||
import de.dennisguse.opentracks.content.data.Waypoint;
|
import de.dennisguse.opentracks.content.data.Waypoint;
|
||||||
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
|
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
||||||
import de.dennisguse.opentracks.util.LocationUtils;
|
import de.dennisguse.opentracks.util.LocationUtils;
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
import de.dennisguse.opentracks.util.UnitConversions;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fragment to display track chart to the user.
|
* A fragment to display track chart to the user.
|
||||||
@@ -66,7 +65,7 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
|||||||
return chartFragment;
|
return chartFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final List<double[]> pendingPoints = new ArrayList<>();
|
private final List<ChartPoint> pendingPoints = new ArrayList<>();
|
||||||
|
|
||||||
private TrackDataHub trackDataHub;
|
private TrackDataHub trackDataHub;
|
||||||
|
|
||||||
@@ -74,11 +73,11 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
|||||||
private TrackStatisticsUpdater trackStatisticsUpdater;
|
private TrackStatisticsUpdater trackStatisticsUpdater;
|
||||||
private long startTime;
|
private long startTime;
|
||||||
|
|
||||||
|
//TODO Why is this needed?
|
||||||
private int recordingDistanceInterval;
|
private int recordingDistanceInterval;
|
||||||
|
|
||||||
// Modes of operation
|
// Modes of operation
|
||||||
private boolean chartByDistance;
|
private boolean chartByDistance;
|
||||||
private final boolean[] chartShow = new boolean[]{true, true, true, true, true, true};
|
|
||||||
|
|
||||||
// UI elements
|
// UI elements
|
||||||
private ChartView chartView;
|
private ChartView chartView;
|
||||||
@@ -104,8 +103,8 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
|||||||
boolean reportSpeed = PreferencesUtils.isReportSpeed(getContext());
|
boolean reportSpeed = PreferencesUtils.isReportSpeed(getContext());
|
||||||
if (reportSpeed != chartView.getReportSpeed()) {
|
if (reportSpeed != chartView.getReportSpeed()) {
|
||||||
chartView.setReportSpeed(reportSpeed);
|
chartView.setReportSpeed(reportSpeed);
|
||||||
setSeriesEnabled(ChartView.SPEED_SERIES, reportSpeed);
|
chartView.applyReportSpeed();
|
||||||
setSeriesEnabled(ChartView.PACE_SERIES, !reportSpeed);
|
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -236,7 +235,7 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
|||||||
@Override
|
@Override
|
||||||
public void onNewTrackPointsDone() {
|
public void onNewTrackPointsDone() {
|
||||||
if (isResumed()) {
|
if (isResumed()) {
|
||||||
chartView.addPendingPoints(pendingPoints);
|
chartView.addChartPoints(pendingPoints);
|
||||||
pendingPoints.clear();
|
pendingPoints.clear();
|
||||||
runOnUiThread(updateChart);
|
runOnUiThread(updateChart);
|
||||||
}
|
}
|
||||||
@@ -267,37 +266,12 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
|||||||
* Checks the chart settings.
|
* Checks the chart settings.
|
||||||
*/
|
*/
|
||||||
private void checkChartSettings() {
|
private void checkChartSettings() {
|
||||||
boolean needUpdate = false;
|
boolean needUpdate = chartView.applyReportSpeed();
|
||||||
|
|
||||||
if (setSeriesEnabled(ChartView.SPEED_SERIES, chartView.getReportSpeed())) {
|
|
||||||
needUpdate = true;
|
|
||||||
}
|
|
||||||
if (setSeriesEnabled(ChartView.PACE_SERIES, !chartView.getReportSpeed())) {
|
|
||||||
needUpdate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needUpdate) {
|
if (needUpdate) {
|
||||||
chartView.postInvalidate();
|
chartView.postInvalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the series enabled value.
|
|
||||||
*
|
|
||||||
* @param index the series index
|
|
||||||
* @param value the value
|
|
||||||
* @return true if changed
|
|
||||||
*/
|
|
||||||
private boolean setSeriesEnabled(int index, boolean value) {
|
|
||||||
if (chartShow[index] != value) {
|
|
||||||
chartShow[index] = value;
|
|
||||||
chartView.setChartValueSeriesEnabled(index, value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resumes the trackDataHub.
|
* Resumes the trackDataHub.
|
||||||
* Needs to be synchronized because trackDataHub can be accessed by multiple threads.
|
* Needs to be synchronized because trackDataHub can be accessed by multiple threads.
|
||||||
@@ -346,68 +320,10 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a {@link TrackPoint}, fill in a data point. <br>
|
|
||||||
* data[0] = time/distance <br>
|
|
||||||
* data[1] = elevation <br>
|
|
||||||
* data[2] = speed <br>
|
|
||||||
* data[3] = pace <br>
|
|
||||||
* data[4] = heart rate <br>
|
|
||||||
* data[5] = cadence <br>
|
|
||||||
* data[6] = power <br>
|
|
||||||
*
|
|
||||||
* @param trackPoint the trackPoint
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
double[] createPendingPoint(@NonNull TrackPoint trackPoint) {
|
ChartPoint createPendingPoint(@NonNull TrackPoint trackPoint) {
|
||||||
double timeOrDistance = Double.NaN;
|
trackStatisticsUpdater.addTrackPoint(trackPoint, recordingDistanceInterval);
|
||||||
double elevation = Double.NaN;
|
return new ChartPoint(trackStatisticsUpdater, trackPoint.getSensorDataSet(), chartByDistance, chartView.getMetricUnits());
|
||||||
double speed = Double.NaN;
|
|
||||||
double pace = Double.NaN;
|
|
||||||
|
|
||||||
if (trackStatisticsUpdater != null) {
|
|
||||||
trackStatisticsUpdater.addTrackPoint(trackPoint, recordingDistanceInterval);
|
|
||||||
TrackStatistics trackStatistics = trackStatisticsUpdater.getTrackStatistics();
|
|
||||||
if (chartByDistance) {
|
|
||||||
double distance = trackStatistics.getTotalDistance() * UnitConversions.M_TO_KM;
|
|
||||||
if (!chartView.getMetricUnits()) {
|
|
||||||
distance *= UnitConversions.KM_TO_MI;
|
|
||||||
}
|
|
||||||
timeOrDistance = distance;
|
|
||||||
} else {
|
|
||||||
timeOrDistance = trackStatistics.getTotalTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
elevation = trackStatisticsUpdater.getSmoothedElevation();
|
|
||||||
if (!chartView.getMetricUnits()) {
|
|
||||||
elevation *= UnitConversions.M_TO_FT;
|
|
||||||
}
|
|
||||||
|
|
||||||
speed = trackStatisticsUpdater.getSmoothedSpeed() * UnitConversions.MS_TO_KMH;
|
|
||||||
if (!chartView.getMetricUnits()) {
|
|
||||||
speed *= UnitConversions.KM_TO_MI;
|
|
||||||
}
|
|
||||||
pace = speed == 0 ? 0.0 : 60.0 / speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
double heartRate = Double.NaN;
|
|
||||||
double cadence = Double.NaN;
|
|
||||||
double power = Double.NaN;
|
|
||||||
if (trackPoint.getSensorDataSet() != null) {
|
|
||||||
SensorDataSet sensorDataSet = trackPoint.getSensorDataSet();
|
|
||||||
if (sensorDataSet.hasHeartRate()) {
|
|
||||||
heartRate = sensorDataSet.getHeartRate();
|
|
||||||
}
|
|
||||||
if (sensorDataSet.hasCadence()) {
|
|
||||||
cadence = sensorDataSet.getCadence();
|
|
||||||
}
|
|
||||||
if (sensorDataSet.hasPower()) {
|
|
||||||
power = sensorDataSet.getPower();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Is related to ChartView.ELEVATION_SERIES etc.
|
|
||||||
return new double[]{timeOrDistance, elevation, speed, pace, heartRate, cadence, power};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
|||||||
@@ -61,9 +61,9 @@ public class TrackStatisticsUpdater {
|
|||||||
private final TrackStatistics trackStatistics;
|
private final TrackStatistics trackStatistics;
|
||||||
|
|
||||||
// A buffer of the recent elevation readings (m)
|
// A buffer of the recent elevation readings (m)
|
||||||
private final DoubleBuffer elevationBuffer = new DoubleBuffer(ELEVATION_SMOOTHING_FACTOR);
|
private final DoubleBuffer elevationBuffer_m = new DoubleBuffer(ELEVATION_SMOOTHING_FACTOR);
|
||||||
// A buffer of the recent speed readings (m/s) for calculating max speed
|
// A buffer of the recent speed readings (m/s) for calculating max speed
|
||||||
private final DoubleBuffer speedBuffer = new DoubleBuffer(SPEED_SMOOTHING_FACTOR);
|
private final DoubleBuffer speedBuffer_ms = new DoubleBuffer(SPEED_SMOOTHING_FACTOR);
|
||||||
|
|
||||||
// The current segment's statistics
|
// The current segment's statistics
|
||||||
private TrackStatistics currentSegment;
|
private TrackStatistics currentSegment;
|
||||||
@@ -128,8 +128,8 @@ public class TrackStatisticsUpdater {
|
|||||||
currentSegment = init(trackPoint.getLocation().getTime());
|
currentSegment = init(trackPoint.getLocation().getTime());
|
||||||
lastTrackPoint = null;
|
lastTrackPoint = null;
|
||||||
lastMovingTrackPoint = null;
|
lastMovingTrackPoint = null;
|
||||||
elevationBuffer.reset();
|
elevationBuffer_m.reset();
|
||||||
speedBuffer.reset();
|
speedBuffer_ms.reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ public class TrackStatisticsUpdater {
|
|||||||
|
|
||||||
double movingDistance = lastMovingTrackPoint.distanceTo(trackPoint);
|
double movingDistance = lastMovingTrackPoint.distanceTo(trackPoint);
|
||||||
if (movingDistance < minRecordingDistance && (!trackPoint.hasSpeed() || trackPoint.getSpeed() < MAX_NO_MOVEMENT_SPEED)) {
|
if (movingDistance < minRecordingDistance && (!trackPoint.hasSpeed() || trackPoint.getSpeed() < MAX_NO_MOVEMENT_SPEED)) {
|
||||||
speedBuffer.reset();
|
speedBuffer_ms.reset();
|
||||||
lastTrackPoint = trackPoint;
|
lastTrackPoint = trackPoint;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -181,11 +181,11 @@ public class TrackStatisticsUpdater {
|
|||||||
* The elevation readings is noisy so the smoothed elevation is better than the raw elevation for many tasks.
|
* The elevation readings is noisy so the smoothed elevation is better than the raw elevation for many tasks.
|
||||||
*/
|
*/
|
||||||
public double getSmoothedElevation() {
|
public double getSmoothedElevation() {
|
||||||
return elevationBuffer.getAverage();
|
return elevationBuffer_m.getAverage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getSmoothedSpeed() {
|
public double getSmoothedSpeed() {
|
||||||
return speedBuffer.getAverage();
|
return speedBuffer_ms.getAverage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -199,11 +199,11 @@ public class TrackStatisticsUpdater {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
private void updateSpeed(long time, double speed, long lastLocationTime, double lastLocationSpeed) {
|
private void updateSpeed(long time, double speed, long lastLocationTime, double lastLocationSpeed) {
|
||||||
if (speed < MAX_NO_MOVEMENT_SPEED) {
|
if (speed < MAX_NO_MOVEMENT_SPEED) {
|
||||||
speedBuffer.reset();
|
speedBuffer_ms.reset();
|
||||||
} else if (isValidSpeed(time, speed, lastLocationTime, lastLocationSpeed)) {
|
} else if (isValidSpeed(time, speed, lastLocationTime, lastLocationSpeed)) {
|
||||||
speedBuffer.setNext(speed);
|
speedBuffer_ms.setNext(speed);
|
||||||
if (speedBuffer.getAverage() > currentSegment.getMaxSpeed()) {
|
if (speedBuffer_ms.getAverage() > currentSegment.getMaxSpeed()) {
|
||||||
currentSegment.setMaxSpeed(speedBuffer.getAverage());
|
currentSegment.setMaxSpeed(speedBuffer_ms.getAverage());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "Invalid speed. speed: " + speed + " lastLocationSpeed: " + lastLocationSpeed);
|
Log.d(TAG, "Invalid speed. speed: " + speed + " lastLocationSpeed: " + lastLocationSpeed);
|
||||||
@@ -218,9 +218,9 @@ public class TrackStatisticsUpdater {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
private double updateElevation(double elevation) {
|
private double updateElevation(double elevation) {
|
||||||
// Update elevation using the smoothed average
|
// Update elevation using the smoothed average
|
||||||
double oldAverage = elevationBuffer.getAverage();
|
double oldAverage = elevationBuffer_m.getAverage();
|
||||||
elevationBuffer.setNext(elevation);
|
elevationBuffer_m.setNext(elevation);
|
||||||
double newAverage = elevationBuffer.getAverage();
|
double newAverage = elevationBuffer_m.getAverage();
|
||||||
|
|
||||||
currentSegment.updateElevationExtremities(newAverage);
|
currentSegment.updateElevationExtremities(newAverage);
|
||||||
double difference = newAverage - oldAverage;
|
double difference = newAverage - oldAverage;
|
||||||
@@ -264,8 +264,8 @@ public class TrackStatisticsUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only check if the speed buffer is full. Check that the speed is less than 10X the smoothed average and the speed difference doesn't imply 2g acceleration.
|
// Only check if the speed buffer is full. Check that the speed is less than 10X the smoothed average and the speed difference doesn't imply 2g acceleration.
|
||||||
if (speedBuffer.isFull()) {
|
if (speedBuffer_ms.isFull()) {
|
||||||
double average = speedBuffer.getAverage();
|
double average = speedBuffer_ms.getAverage();
|
||||||
double diff = Math.abs(average - speed);
|
double diff = Math.abs(average - speed);
|
||||||
return (speed < average * 10) && (diff < MAX_ACCELERATION * timeDifference);
|
return (speed < average * 10) && (diff < MAX_ACCELERATION * timeDifference);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user