Position: use for TrackPoint.

This commit is contained in:
Dennis Guse
2025-02-28 22:20:39 +01:00
parent e83ba04d71
commit 1d5f65be48
7 changed files with 212 additions and 162 deletions
@@ -622,31 +622,19 @@ public class ContentProviderUtils {
* @param indexes the cached trackPoints indexes * @param indexes the cached trackPoints indexes
*/ */
static TrackPoint fillTrackPoint(Cursor cursor, CachedTrackPointsIndexes indexes) { static TrackPoint fillTrackPoint(Cursor cursor, CachedTrackPointsIndexes indexes) {
Instant time = Instant.ofEpochMilli(cursor.getLong(indexes.timeIndex)); TrackPoint trackPoint = new TrackPoint(
TrackPoint trackPoint = new TrackPoint(TrackPoint.Type.getById(cursor.getInt(indexes.typeIndex)), time); new TrackPoint.Id(cursor.getInt(indexes.idIndex)),
trackPoint.setId(new TrackPoint.Id(cursor.getInt(indexes.idIndex))); TrackPoint.Type.getById(cursor.getInt(indexes.typeIndex)),
new Position(
if (!cursor.isNull(indexes.longitudeIndex)) { Instant.ofEpochMilli(cursor.getLong(indexes.timeIndex)),
trackPoint.setLongitude(((double) cursor.getInt(indexes.longitudeIndex)) / 1E6); !cursor.isNull(indexes.latitudeIndex) ? ((double) cursor.getInt(indexes.latitudeIndex)) / 1E6 : null,
} !cursor.isNull(indexes.longitudeIndex) ? ((double) cursor.getInt(indexes.longitudeIndex)) / 1E6 : null,
if (!cursor.isNull(indexes.latitudeIndex)) { !cursor.isNull(indexes.accuracyIndex) ? Distance.of(cursor.getFloat(indexes.accuracyIndex)) : null,
trackPoint.setLatitude(((double) cursor.getInt(indexes.latitudeIndex)) / 1E6); !cursor.isNull(indexes.altitudeIndex) ? Altitude.WGS84.of(cursor.getFloat(indexes.altitudeIndex)) : null,
} !cursor.isNull(indexes.accuracyVerticalIndex) ? Distance.of(cursor.getFloat(indexes.accuracyVerticalIndex)) : null,
if (!cursor.isNull(indexes.altitudeIndex)) { !cursor.isNull(indexes.bearingIndex) ? cursor.getFloat(indexes.bearingIndex) : null,
trackPoint.setAltitude(Altitude.WGS84.of(cursor.getFloat(indexes.altitudeIndex))); !cursor.isNull(indexes.speedIndex) ? Speed.of(cursor.getFloat(indexes.speedIndex)) : null
} ));
if (!cursor.isNull(indexes.accuracyIndex)) {
trackPoint.setHorizontalAccuracy(Distance.of(cursor.getFloat(indexes.accuracyIndex)));
}
if (!cursor.isNull(indexes.accuracyVerticalIndex)) {
trackPoint.setVerticalAccuracy(Distance.of(cursor.getFloat(indexes.accuracyVerticalIndex)));
}
if (!cursor.isNull(indexes.speedIndex)) {
trackPoint.setSpeed(Speed.of(cursor.getFloat(indexes.speedIndex)));
}
if (!cursor.isNull(indexes.bearingIndex)) {
trackPoint.setBearing(cursor.getFloat(indexes.bearingIndex));
}
if (!cursor.isNull(indexes.sensorHeartRateIndex)) { if (!cursor.isNull(indexes.sensorHeartRateIndex)) {
trackPoint.setHeartRate(cursor.getFloat(indexes.sensorHeartRateIndex)); trackPoint.setHeartRate(cursor.getFloat(indexes.sensorHeartRateIndex));
@@ -2,22 +2,29 @@ package de.dennisguse.opentracks.data.models;
import android.location.Location; import android.location.Location;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.time.Instant; import java.time.Instant;
//TODO Use everywhere instead of android.location.Location. //TODO Use everywhere instead of android.location.Location.
public record Position( public record Position(
Instant time, @Nullable Instant time,
Double latitude, @Nullable Double latitude,
Double longitude, @Nullable Double longitude,
Distance horizontalAccuracy, @Nullable Distance horizontalAccuracy,
Altitude altitude, @Nullable Altitude altitude,
Distance verticalAccuracy, @Nullable Distance verticalAccuracy,
Float bearing, @Nullable Float bearing,
Speed speed @Nullable Speed speed
) { ) {
public static Position empty() { public static Position empty() {
return of((Instant) null);
}
public static Position of(@NonNull Instant time) {
return new Position( return new Position(
null, time,
null, null,
null, null,
null, null,
@@ -28,9 +35,13 @@ public record Position(
); );
} }
public static Position of(Location location) { public static Position of(@NonNull Location location) {
return of(location, Instant.ofEpochMilli(location.getTime()));
}
public static Position of(@NonNull Location location, @NonNull Instant time) {
return new Position( return new Position(
Instant.ofEpochMilli(location.getTime()), time,
location.getLatitude(), location.getLatitude(),
location.getLongitude(), location.getLongitude(),
location.hasAccuracy() ? Distance.of(location.getAccuracy()) : null, location.hasAccuracy() ? Distance.of(location.getAccuracy()) : null,
@@ -53,6 +64,10 @@ public record Position(
return altitude != null; return altitude != null;
} }
public boolean hasVerticalAccuracy() {
return verticalAccuracy != null;
}
public boolean hasBearing() { public boolean hasBearing() {
return bearing != null; return bearing != null;
} }
@@ -67,7 +82,9 @@ public record Position(
} }
Location location = new Location(""); Location location = new Location("");
location.setTime(time.toEpochMilli()); if (time != null) {
location.setTime(time.toEpochMilli());
}
location.setLatitude(latitude); location.setLatitude(latitude);
location.setLongitude(longitude); location.setLongitude(longitude);
if (hasBearing()) { if (hasBearing()) {
@@ -103,4 +120,34 @@ public record Position(
.lessThan(thresholdHorizontalAccuracy); .lessThan(thresholdHorizontalAccuracy);
} }
public Position with(Instant time) {
return new Position(time, latitude, longitude, horizontalAccuracy, altitude, verticalAccuracy, bearing, speed);
}
public Position with(Altitude altitude) {
return new Position(time, latitude, longitude, horizontalAccuracy, altitude, verticalAccuracy, bearing, speed);
}
public Position with(Speed speed) {
return new Position(time, latitude, longitude, horizontalAccuracy, altitude, verticalAccuracy, bearing, speed);
}
//TODO Use double
public Position withCoordinates(Double latitude, Double longitude) {
return new Position(time, latitude, longitude, horizontalAccuracy, altitude, verticalAccuracy, bearing, speed);
}
//TODO Use float
public Position withBearing(Float bearing) {
return new Position(time, latitude, longitude, horizontalAccuracy, altitude, verticalAccuracy, bearing, speed);
}
public Position withHorizontalAccuracy(Distance horizontalAccuracy) {
return new Position(time, latitude, longitude, horizontalAccuracy, altitude, verticalAccuracy, bearing, speed);
}
public Position withVerticalAccuracy(Distance verticalAccuracy) {
return new Position(time, latitude, longitude, horizontalAccuracy, altitude, verticalAccuracy, bearing, speed);
}
} }
@@ -38,20 +38,12 @@ public class TrackPoint {
private static final Duration MAX_LOCATION_AGE = Duration.ofMinutes(1); private static final Duration MAX_LOCATION_AGE = Duration.ofMinutes(1);
@Nullable
private TrackPoint.Id id; private TrackPoint.Id id;
//Requires: position.time must be non-null
@NonNull @NonNull
private final Instant time; private Position position;
//TODO We may use Position for these items
private Double latitude;
private Double longitude;
private Distance horizontalAccuracy;
private Distance verticalAccuracy;
private Altitude altitude; //TODO use Altitude.WGS84
private Speed speed;
private Float bearing;
private Distance sensorDistance;
public enum Type { public enum Type {
SEGMENT_START_MANUAL(-2), //Start of a segment due to user interaction (start, resume) SEGMENT_START_MANUAL(-2), //Start of a segment due to user interaction (start, resume)
@@ -73,6 +65,7 @@ public class TrackPoint {
this.type_db = type_db; this.type_db = type_db;
} }
@NonNull
@Override @Override
public String toString() { public String toString() {
return name() + "(" + type_db + ")"; return name() + "(" + type_db + ")";
@@ -90,33 +83,55 @@ public class TrackPoint {
@NonNull @NonNull
private Type type; private Type type;
private Distance sensorDistance;
private HeartRate heartRate = null; private HeartRate heartRate = null;
private Cadence cadence = null; private Cadence cadence = null;
private Power power = null; private Power power = null;
private Float altitudeGain_m = null; private Float altitudeGain_m = null;
private Float altitudeLoss_m = null; private Float altitudeLoss_m = null;
public TrackPoint(@NonNull Type type, @NonNull Instant time) { public TrackPoint(@Nullable TrackPoint.Id id, @NonNull Type type, @NonNull Position position) {
this.id = id;
this.type = type; this.type = type;
this.time = time; this.position = position;
} }
//TODO Refactor constructors
public TrackPoint(@NonNull Type type, @NonNull Instant time) {
this.type = type;
this.position = Position.of(time);
}
@Deprecated
public TrackPoint(@NonNull Location location, @NonNull Instant time) { public TrackPoint(@NonNull Location location, @NonNull Instant time) {
this(Type.TRACKPOINT, location, time); this.type = Type.TRACKPOINT;
this.position = Position.of(location, time);
}
public TrackPoint(@NonNull Position position) {
this(null, Type.TRACKPOINT, position);
} }
public TrackPoint(@NonNull Type type, @NonNull Location location, @NonNull Instant time) { public TrackPoint(@NonNull Type type, @NonNull Location location, @NonNull Instant time) {
this(type, time); this.type = type;
this.position = Position.of(location, time);
setLocation(location);
} }
//TODO Remove; only used for TrackStatisticUpdaterTest
@Deprecated
@VisibleForTesting @VisibleForTesting
public TrackPoint(double latitude, double longitude, Altitude altitude, Instant time) { public TrackPoint(double latitude, double longitude, Altitude altitude, Instant time) {
this(Type.TRACKPOINT, time); this.type = Type.TRACKPOINT;
this.latitude = latitude; this.position = new Position(
this.longitude = longitude; time,
this.altitude = altitude; latitude,
longitude,
null,
altitude,
null,
null,
null
);
} }
public static TrackPoint createSegmentStartManualWithTime(Instant time) { public static TrackPoint createSegmentStartManualWithTime(Instant time) {
@@ -161,54 +176,46 @@ public class TrackPoint {
return id; return id;
} }
public void setId(TrackPoint.Id id) {
this.id = id;
}
public boolean hasLocation() { public boolean hasLocation() {
return latitude != null && longitude != null; return position.hasLocation();
} }
public double getLatitude() { //TODO Should be double
return latitude; @Deprecated //Use getPosition()
public Double getLatitude() {
return position.latitude();
} }
@Deprecated
public TrackPoint setLatitude(double latitude) { public TrackPoint setLatitude(double latitude) {
this.latitude = latitude; this.position = position.withCoordinates(latitude, getLongitude());
return this; return this;
} }
public double getLongitude() { //TODO Should be double
return longitude; @Deprecated //Use getPosition()
public Double getLongitude() {
return position.longitude();
} }
@Deprecated
public TrackPoint setLongitude(double longitude) { public TrackPoint setLongitude(double longitude) {
this.longitude = longitude; setCoordinates(getLatitude(), longitude);
return this;
}
public TrackPoint setCoordinates(double latitude, double longitude) {
this.position = this.position.withCoordinates(latitude, longitude);
return this; return this;
} }
@NonNull @NonNull
public Position getPosition() { public Position getPosition() {
return new Position( return position;
time,
latitude,
longitude,
horizontalAccuracy,
altitude,
verticalAccuracy,
bearing,
speed
);
} }
public TrackPoint setPosition(Position location) { public TrackPoint setPosition(Position position) {
this.latitude = location.latitude(); this.position = position.with(this.position.time());
this.longitude = location.longitude();
this.altitude = location.altitude();
this.speed = location.speed();
this.horizontalAccuracy = location.horizontalAccuracy();
this.verticalAccuracy = location.verticalAccuracy();
return this; return this;
} }
@@ -218,12 +225,6 @@ public class TrackPoint {
return getPosition().toLocation(); return getPosition().toLocation();
} }
@Deprecated
public TrackPoint setLocation(@NonNull Location location) {
setPosition(Position.of(location));
return this;
}
public boolean hasAltitudeGain() { public boolean hasAltitudeGain() {
return altitudeGain_m != null; return altitudeGain_m != null;
} }
@@ -252,83 +253,77 @@ public class TrackPoint {
@NonNull @NonNull
public Instant getTime() { public Instant getTime() {
return time; return position.time();
} }
public boolean isRecent() {
return Instant.now()
.isBefore(time.plus(MAX_LOCATION_AGE));
}
public boolean hasAltitude() { public boolean hasAltitude() {
return altitude != null; return position.hasAltitude();
} }
public Altitude getAltitude() { public Altitude getAltitude() {
return altitude; return position.altitude();
} }
@VisibleForTesting @VisibleForTesting
public TrackPoint setAltitude(double altitude_m) { public TrackPoint setAltitude(double altitude_m) {
this.altitude = Altitude.WGS84.of(altitude_m); setAltitude(Altitude.WGS84.of(altitude_m));
return this; return this;
} }
public TrackPoint setAltitude(Altitude altitude) { public TrackPoint setAltitude(Altitude altitude) {
this.altitude = altitude; position = position.with(altitude);
return this; return this;
} }
public boolean hasSpeed() { public boolean hasSpeed() {
return speed != null; return position.hasSpeed();
} }
public Speed getSpeed() { public Speed getSpeed() {
return speed; return position.speed();
} }
public TrackPoint setSpeed(Speed speed) { public TrackPoint setSpeed(Speed speed) {
this.speed = speed; this.position = position.with(speed);
return this; return this;
} }
public boolean hasBearing() { public boolean hasBearing() {
return bearing != null; return position.hasBearing();
} }
public float getBearing() { public float getBearing() {
return bearing; return position.bearing();
} }
public TrackPoint setBearing(Float bearing) { public TrackPoint setBearing(Float bearing) {
this.bearing = bearing; this.position = this.position.withBearing(bearing);
return this; return this;
} }
public boolean hasHorizontalAccuracy() { public boolean hasHorizontalAccuracy() {
return horizontalAccuracy != null; return position.hasHorizontalAccuracy();
} }
public Distance getHorizontalAccuracy() { public Distance getHorizontalAccuracy() {
return horizontalAccuracy; return position.horizontalAccuracy();
} }
public TrackPoint setHorizontalAccuracy(Distance horizontalAccuracy) { public TrackPoint setHorizontalAccuracy(Distance horizontalAccuracy) {
this.horizontalAccuracy = horizontalAccuracy; this.position = this.position.withHorizontalAccuracy(horizontalAccuracy);
return this; return this;
} }
public boolean hasVerticalAccuracy() { public boolean hasVerticalAccuracy() {
return verticalAccuracy != null; return position.hasVerticalAccuracy();
} }
public Distance getVerticalAccuracy() { public Distance getVerticalAccuracy() {
return verticalAccuracy; return position.verticalAccuracy();
} }
public TrackPoint setVerticalAccuracy(Distance horizontalAccuracy) { public TrackPoint setVerticalAccuracy(Distance verticalAccuracy) {
this.verticalAccuracy = horizontalAccuracy; this.position = this.position.withVerticalAccuracy(verticalAccuracy);
return this; return this;
} }
@@ -350,7 +345,7 @@ public class TrackPoint {
} }
public boolean fulfillsAccuracy(Distance thresholdHorizontalAccuracy) { public boolean fulfillsAccuracy(Distance thresholdHorizontalAccuracy) {
return hasHorizontalAccuracy() && horizontalAccuracy.lessThan(thresholdHorizontalAccuracy); return position.fulfillsAccuracy(thresholdHorizontalAccuracy);
} }
public Optional<Float> bearingTo(@NonNull Position dest) { public Optional<Float> bearingTo(@NonNull Position dest) {
@@ -459,14 +454,7 @@ public class TrackPoint {
public String toString() { public String toString() {
return "TrackPoint{" + return "TrackPoint{" +
"id=" + id + "id=" + id +
", time=" + time + ", position=" + position +
", latitude=" + latitude +
", longitude=" + longitude +
", horizontalAccuracy=" + horizontalAccuracy +
", verticalAccuracy=" + verticalAccuracy +
", altitude=" + altitude +
", speed=" + speed +
", bearing=" + bearing +
", sensorDistance=" + sensorDistance + ", sensorDistance=" + sensorDistance +
", type=" + type + ", type=" + type +
", heartRate=" + heartRate + ", heartRate=" + heartRate +
@@ -34,6 +34,7 @@ import java.util.Locale;
import de.dennisguse.opentracks.data.models.Altitude; import de.dennisguse.opentracks.data.models.Altitude;
import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Marker; import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Position;
import de.dennisguse.opentracks.data.models.Speed; import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
@@ -161,7 +162,7 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
case TAG_GPX -> onFileEnd(); case TAG_GPX -> onFileEnd();
case TAG_MARKER -> onMarkerEnd(); case TAG_MARKER -> onMarkerEnd();
case TAG_TRACK -> { case TAG_TRACK -> {
if (activityTypeLocalized == null ) { if (activityTypeLocalized == null) {
// Backward compatibility: up v4.9.1 as <type> contained localized content. // Backward compatibility: up v4.9.1 as <type> contained localized content.
activityTypeLocalized = activityType; activityTypeLocalized = activityType;
} }
@@ -282,33 +283,65 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse time: %s", time)), e); throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse time: %s", time)), e);
} }
TrackPoint trackPoint = new TrackPoint(TrackPoint.Type.TRACKPOINT, parsedTime.toInstant());
if (latitude == null || longitude == null) { if (latitude == null || longitude == null) {
return trackPoint; return new TrackPoint(TrackPoint.Type.TRACKPOINT, parsedTime.toInstant());
} }
double latitudeParsed;
double longitudeParsed;
Distance accuracyHorizontalParsed = null;
Altitude.WGS84 altitudeParsed = null;
Distance accuracyVerticalParsed = null;
Speed speedParsed = null;
try { try {
trackPoint.setLatitude(Double.parseDouble(latitude)); latitudeParsed = Double.parseDouble(latitude);
trackPoint.setLongitude(Double.parseDouble(longitude)); longitudeParsed = Double.parseDouble(longitude);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse latitude longitude: %s %s", latitude, longitude)), e); throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse latitude longitude: %s %s", latitude, longitude)), e);
} }
if (accuracyHorizontal != null) {
try {
accuracyHorizontalParsed = Distance.of(accuracyHorizontal);
} catch (NumberFormatException e) {
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse accuracy_horizontal: %s", sensorDistance)), e);
}
}
if (altitude != null) { if (altitude != null) {
try { try {
trackPoint.setAltitude(Altitude.WGS84.of(Double.parseDouble(altitude))); altitudeParsed = Altitude.WGS84.of(Double.parseDouble(altitude));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse altitude: %s", altitude)), e); throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse altitude: %s", altitude)), e);
} }
} }
if (accuracyVertical != null) {
try {
accuracyVerticalParsed = Distance.of(accuracyVertical);
} catch (NumberFormatException e) {
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse accuracy_vertical: %s", accuracyVertical)), e);
}
}
if (speed != null) { if (speed != null) {
try { try {
trackPoint.setSpeed(Speed.of(speed)); speedParsed = Speed.of(speed);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse speed: %s", speed)), e); throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse speed: %s", speed)), e);
} }
} }
TrackPoint trackPoint = new TrackPoint(new Position(
parsedTime.toInstant(),
latitudeParsed,
longitudeParsed,
accuracyHorizontalParsed,
altitudeParsed,
accuracyVerticalParsed,
null,
speedParsed
));
if (heartrate != null) { if (heartrate != null) {
try { try {
trackPoint.setHeartRate(Float.parseFloat(heartrate)); trackPoint.setHeartRate(Float.parseFloat(heartrate));
@@ -354,20 +387,6 @@ public class GpxTrackImporter extends DefaultHandler implements XMLImporter.Trac
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse distance: %s", sensorDistance)), e); throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse distance: %s", sensorDistance)), e);
} }
} }
if (accuracyHorizontal != null) {
try {
trackPoint.setHorizontalAccuracy(Distance.of(accuracyHorizontal));
} catch (NumberFormatException e) {
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse accuracy_horizontal: %s", sensorDistance)), e);
}
}
if (accuracyVertical != null) {
try {
trackPoint.setVerticalAccuracy(Distance.of(accuracyVertical));
} catch (NumberFormatException e) {
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse accuracy_vertical: %s", sensorDistance)), e);
}
}
return trackPoint; return trackPoint;
} }
@@ -313,9 +313,11 @@ public class KmlTrackImporter extends DefaultHandler implements XMLImporter.Trac
Instant time = whenList.get(i); Instant time = whenList.get(i);
Location location = locationList.get(i); Location location = locationList.get(i);
TrackPoint trackPoint = new TrackPoint(TrackPoint.Type.TRACKPOINT, time); TrackPoint trackPoint;
if (location != null) { if (location == null) {
trackPoint.setLocation(location); trackPoint = new TrackPoint(TrackPoint.Type.TRACKPOINT, time);
} else {
trackPoint = new TrackPoint(TrackPoint.Type.TRACKPOINT, location, time);
} }
if (i < trackpointTypeList.size() && trackpointTypeList.get(i) != null) { if (i < trackpointTypeList.size() && trackpointTypeList.get(i) != null) {
@@ -107,19 +107,19 @@ public class TrackPointCreator implements SharedPreferences.OnSharedPreferenceCh
public Pair<TrackPoint, SensorDataSet> createCurrentTrackPoint(@Nullable TrackPoint lastTrackPointUISpeed, @Nullable TrackPoint lastTrackPointUIAltitude, @Nullable TrackPoint lastStoredTrackPointWithLocation) { public Pair<TrackPoint, SensorDataSet> createCurrentTrackPoint(@Nullable TrackPoint lastTrackPointUISpeed, @Nullable TrackPoint lastTrackPointUIAltitude, @Nullable TrackPoint lastStoredTrackPointWithLocation) {
TrackPoint currentTrackPoint = new TrackPoint(TrackPoint.Type.TRACKPOINT, createNow()); TrackPoint currentTrackPoint = new TrackPoint(TrackPoint.Type.TRACKPOINT, createNow());
if (lastStoredTrackPointWithLocation != null && lastStoredTrackPointWithLocation.hasLocation()) {
//We are taking the coordinates from the last stored TrackPoint, so the distance is monotonously increasing.
currentTrackPoint.setPosition(lastStoredTrackPointWithLocation.getPosition());
}
if (lastTrackPointUISpeed != null) { if (lastTrackPointUISpeed != null) {
currentTrackPoint.setSpeed(lastTrackPointUISpeed.getSpeed()); currentTrackPoint.setSpeed(lastTrackPointUISpeed.getSpeed());
} }
if (lastTrackPointUIAltitude != null) { if (lastTrackPointUIAltitude != null) {
currentTrackPoint.setAltitude(lastTrackPointUIAltitude.getAltitude()); currentTrackPoint.setAltitude(lastTrackPointUIAltitude.getAltitude());
} }
if (lastStoredTrackPointWithLocation != null && lastStoredTrackPointWithLocation.hasLocation()) {
//We are taking the coordinates from the last stored TrackPoint, so the distance is monotonously increasing.
currentTrackPoint.setLongitude(lastStoredTrackPointWithLocation.getLongitude());
currentTrackPoint.setLatitude(lastStoredTrackPointWithLocation.getLatitude());
}
SensorDataSet sensorDataSet = addSensorData(currentTrackPoint); SensorDataSet sensorDataSet = addSensorData(currentTrackPoint);
return new Pair<>(currentTrackPoint, sensorDataSet); return new Pair<>(currentTrackPoint, sensorDataSet);
@@ -20,6 +20,7 @@ import java.util.concurrent.Callable;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.models.Altitude; import de.dennisguse.opentracks.data.models.Altitude;
import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Position;
import de.dennisguse.opentracks.data.models.Speed; import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
@@ -49,13 +50,18 @@ public class SettingsCustomLayoutEditAdapter extends RecyclerView.Adapter<Recycl
Track track = new Track(ZoneOffset.UTC); Track track = new Track(ZoneOffset.UTC);
track.setTrackStatistics(trackStatistics); track.setTrackStatistics(trackStatistics);
TrackPoint lastTrackPoint = new TrackPoint(TrackPoint.Type.TRACKPOINT, Instant.ofEpochMilli(0)); Position position = new Position(
lastTrackPoint.setLatitude(0); Instant.ofEpochMilli(0),
lastTrackPoint.setLongitude(0); 0.0,
lastTrackPoint.setAltitude(Altitude.EGM2008.of(0)); 0.0,
lastTrackPoint.setSpeed(Speed.of(0)); null,
Altitude.EGM2008.of(0),
null,
null,
Speed.zero()
);
demoData = new RecordingData(track, lastTrackPoint, null); demoData = new RecordingData(track, new TrackPoint(position), null);
} }
private RecordingLayout recordingLayout; private RecordingLayout recordingLayout;