forked from upstream-mirrors/OpenTracks
TrackPoint is now a record.
This commit is contained in:
@@ -90,20 +90,20 @@ public class CSVTrackExporter implements TrackExporter {
|
||||
public boolean writeTrack(@NonNull List<Track> tracks, @NonNull OutputStream outputStream) {
|
||||
List<Column> columns = List.of(
|
||||
new Column("time", null),
|
||||
new Column("trackpoint_type", t -> quote(t.getType().name())),
|
||||
new Column("latitude", t -> t.hasLocation() ? COORDINATE_FORMAT.format(t.getPosition().latitude()) : ""),
|
||||
new Column("longitude", t -> t.hasLocation() ? COORDINATE_FORMAT.format(t.getPosition().longitude()) : ""),
|
||||
new Column("altitude", t -> t.hasAltitude() ? ALTITUDE_FORMAT.format(t.getAltitude().toM()) : ""),
|
||||
new Column("accuracy_horizontal", t -> t.hasHorizontalAccuracy() ? DISTANCE_FORMAT.format(t.getHorizontalAccuracy().toM()) : ""),
|
||||
new Column("accuracy_vertical", t -> t.hasVerticalAccuracy() ? DISTANCE_FORMAT.format(t.getVerticalAccuracy().toM()) : ""),
|
||||
new Column("trackpoint_type", t -> quote(t.type().name())),
|
||||
new Column("latitude", t -> t.position().hasLocation() ? COORDINATE_FORMAT.format(t.position().latitude()) : ""),
|
||||
new Column("longitude", t -> t.position().hasLocation() ? COORDINATE_FORMAT.format(t.position().longitude()) : ""),
|
||||
new Column("altitude", t -> t.position().hasAltitude() ? ALTITUDE_FORMAT.format(t.position().altitude().toM()) : ""),
|
||||
new Column("accuracy_horizontal", t -> t.position().hasHorizontalAccuracy() ? DISTANCE_FORMAT.format(t.position().horizontalAccuracy().toM()) : ""),
|
||||
new Column("accuracy_vertical", t -> t.position().hasVerticalAccuracy() ? DISTANCE_FORMAT.format(t.position().verticalAccuracy().toM()) : ""),
|
||||
|
||||
new Column("speed", t -> t.hasSpeed() ? SPEED_FORMAT.format(t.getSpeed().toKMH()) : ""),
|
||||
new Column("altitude_gain", t -> t.hasAltitudeGainLoss() ? ALTITUDE_FORMAT.format(t.getAltitudeGainLoss().gain_m()) : ""),
|
||||
new Column("altitude_loss", t -> t.hasAltitudeGainLoss() ? ALTITUDE_FORMAT.format(t.getAltitudeGainLoss().loss_m()) : ""),
|
||||
new Column("sensor_distance", t -> t.hasSensorDistance() ? DISTANCE_FORMAT.format(t.getSensorDistance().toM()) : ""),
|
||||
new Column("heartrate", t -> t.hasHeartRate() ? HEARTRATE_FORMAT.format(t.getHeartRate().getBPM()) : ""),
|
||||
new Column("cadence", t -> t.hasCadence() ? CADENCE_FORMAT.format(t.getCadence().getRPM()) : ""),
|
||||
new Column("power", t -> t.hasPower() ? POWER_FORMAT.format(t.getPower().getW()) : ""));
|
||||
new Column("speed", t -> t.position().hasSpeed() ? SPEED_FORMAT.format(t.position().speed().toKMH()) : ""),
|
||||
new Column("altitude_gain", t -> t.altitudeGainLoss() != null ? ALTITUDE_FORMAT.format(t.altitudeGainLoss().gain_m()) : ""),
|
||||
new Column("altitude_loss", t -> t.altitudeGainLoss() != null ? ALTITUDE_FORMAT.format(t.altitudeGainLoss().loss_m()) : ""),
|
||||
new Column("sensor_distance", t -> t.sensorDistance() != null ? DISTANCE_FORMAT.format(t.sensorDistance().toM()) : ""),
|
||||
new Column("heartrate", t -> t.heartRate() != null ? HEARTRATE_FORMAT.format(t.heartRate().getBPM()) : ""),
|
||||
new Column("cadence", t -> t.cadence() != null ? CADENCE_FORMAT.format(t.cadence().getRPM()) : ""),
|
||||
new Column("power", t -> t.power() != null ? POWER_FORMAT.format(t.power().getW()) : ""));
|
||||
|
||||
try {
|
||||
prepare(outputStream);
|
||||
|
||||
@@ -140,7 +140,7 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
wroteTrack = true;
|
||||
}
|
||||
|
||||
switch (trackPoint.getType()) {
|
||||
switch (trackPoint.type()) {
|
||||
case SEGMENT_START_MANUAL ->
|
||||
Log.i(TAG, "Exporting " + TrackPoint.Type.SEGMENT_START_MANUAL.name() + " is not supported.");
|
||||
case SEGMENT_END_MANUAL -> {
|
||||
@@ -152,7 +152,7 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
if (wroteSegment) writeCloseSegment();
|
||||
writeOpenSegment();
|
||||
wroteSegment = true;
|
||||
if (trackPoint.hasLocation()) {
|
||||
if (trackPoint.position().hasLocation()) {
|
||||
trackDistance = trackDistance.plus(writeTrackPoint(track.zoneOffset(), trackPoint, sensorPoints, trackDistance));
|
||||
sensorPoints.clear();
|
||||
} else {
|
||||
@@ -165,7 +165,7 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
writeOpenSegment();
|
||||
wroteSegment = true;
|
||||
}
|
||||
if (trackPoint.hasLocation()) {
|
||||
if (trackPoint.position().hasLocation()) {
|
||||
trackDistance = trackDistance.plus(writeTrackPoint(track.zoneOffset(), trackPoint, sensorPoints, trackDistance));
|
||||
sensorPoints.clear();
|
||||
} else {
|
||||
@@ -176,7 +176,7 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
// Not supported as IDLE-TrackPoints have no location.
|
||||
}
|
||||
default ->
|
||||
throw new RuntimeException("Exporting this TrackPoint type is not implemented: " + trackPoint.getType());
|
||||
throw new RuntimeException("Exporting this TrackPoint type is not implemented: " + trackPoint.type());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,10 +306,10 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
private Distance writeTrackPoint(ZoneOffset zoneOffset, TrackPoint trackPoint, List<TrackPoint> sensorPoints, Distance trackDistance) {
|
||||
Distance cumulativeDistance;
|
||||
|
||||
printWriter.println("<trkpt " + formatLocation(trackPoint.getPosition()) + ">");
|
||||
printWriter.println("<trkpt " + formatLocation(trackPoint.position()) + ">");
|
||||
|
||||
if (trackPoint.hasAltitude()) {
|
||||
printWriter.println("<ele>" + ALTITUDE_FORMAT.format(trackPoint.getAltitude().toM()) + "</ele>");
|
||||
if (trackPoint.position().hasAltitude()) {
|
||||
printWriter.println("<ele>" + ALTITUDE_FORMAT.format(trackPoint.position().altitude().toM()) + "</ele>");
|
||||
}
|
||||
|
||||
printWriter.println("<time>" + StringUtils.formatDateTimeIso8601(trackPoint.getTime(), zoneOffset) + "</time>");
|
||||
@@ -317,41 +317,41 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
{
|
||||
String trackPointExtensionV2Content = "";
|
||||
|
||||
if (trackPoint.hasHeartRate()) {
|
||||
trackPointExtensionV2Content += "<gpxtpx:hr>" + HEARTRATE_FORMAT.format(trackPoint.getHeartRate().getBPM()) + "</gpxtpx:hr>\n";
|
||||
if (trackPoint.heartRate() != null) {
|
||||
trackPointExtensionV2Content += "<gpxtpx:hr>" + HEARTRATE_FORMAT.format(trackPoint.heartRate().getBPM()) + "</gpxtpx:hr>\n";
|
||||
}
|
||||
|
||||
if (trackPoint.hasCadence()) {
|
||||
trackPointExtensionV2Content += "<gpxtpx:cad>" + CADENCE_FORMAT.format(trackPoint.getCadence().getRPM()) + "</gpxtpx:cad>\n";
|
||||
if (trackPoint.cadence() != null) {
|
||||
trackPointExtensionV2Content += "<gpxtpx:cad>" + CADENCE_FORMAT.format(trackPoint.cadence().getRPM()) + "</gpxtpx:cad>\n";
|
||||
}
|
||||
|
||||
if (trackPoint.hasSpeed()) {
|
||||
trackPointExtensionV2Content += "<gpxtpx:speed>" + SPEED_FORMAT.format(trackPoint.getSpeed().toMPS()) + "</gpxtpx:speed>\n";
|
||||
if (trackPoint.position().hasSpeed()) {
|
||||
trackPointExtensionV2Content += "<gpxtpx:speed>" + SPEED_FORMAT.format(trackPoint.position().speed().toMPS()) + "</gpxtpx:speed>\n";
|
||||
}
|
||||
|
||||
String extensionContent = "";
|
||||
if (trackPoint.hasPower()) {
|
||||
extensionContent += "<pwr:PowerInWatts>" + POWER_FORMAT.format(trackPoint.getPower().getW()) + "</pwr:PowerInWatts>\n";
|
||||
if (trackPoint.power() != null) {
|
||||
extensionContent += "<pwr:PowerInWatts>" + POWER_FORMAT.format(trackPoint.power().getW()) + "</pwr:PowerInWatts>\n";
|
||||
}
|
||||
|
||||
Double cumulativeGain = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasAltitudeGainLoss() ? (double) tp.getAltitudeGainLoss().gain_m() : null);
|
||||
Double cumulativeGain = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.altitudeGainLoss() != null ? (double) tp.altitudeGainLoss().gain_m() : null);
|
||||
if (cumulativeGain != null) {
|
||||
extensionContent += ("<opentracks:gain>" + ALTITUDE_FORMAT.format(cumulativeGain) + "</opentracks:gain>\n");
|
||||
}
|
||||
|
||||
Double cumulativeLoss = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasAltitudeGainLoss() ? (double) tp.getAltitudeGainLoss().loss_m() : null);
|
||||
Double cumulativeLoss = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.altitudeGainLoss() != null ? (double) tp.altitudeGainLoss().loss_m() : null);
|
||||
if (cumulativeLoss != null) {
|
||||
extensionContent += ("<opentracks:loss>" + ALTITUDE_FORMAT.format(cumulativeLoss) + "</opentracks:loss>\n");
|
||||
}
|
||||
|
||||
if (trackPoint.hasHorizontalAccuracy()) {
|
||||
extensionContent += ("<opentracks:accuracy_horizontal>" + DISTANCE_FORMAT.format(trackPoint.getHorizontalAccuracy().toM()) + "</opentracks:accuracy_horizontal>");
|
||||
if (trackPoint.position().hasHorizontalAccuracy()) {
|
||||
extensionContent += ("<opentracks:accuracy_horizontal>" + DISTANCE_FORMAT.format(trackPoint.position().horizontalAccuracy().toM()) + "</opentracks:accuracy_horizontal>");
|
||||
}
|
||||
if (trackPoint.hasVerticalAccuracy()) {
|
||||
extensionContent += ("<opentracks:accuracy_vertical>" + DISTANCE_FORMAT.format(trackPoint.getVerticalAccuracy().toM()) + "</opentracks:accuracy_vertical>");
|
||||
if (trackPoint.position().hasVerticalAccuracy()) {
|
||||
extensionContent += ("<opentracks:accuracy_vertical>" + DISTANCE_FORMAT.format(trackPoint.position().verticalAccuracy().toM()) + "</opentracks:accuracy_vertical>");
|
||||
}
|
||||
|
||||
cumulativeDistance = Distance.ofOrNull(cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasSensorDistance() ? tp.getSensorDistance().toM() : null));
|
||||
cumulativeDistance = Distance.ofOrNull(cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.sensorDistance() != null ? tp.sensorDistance().toM() : null));
|
||||
if (cumulativeDistance != null) {
|
||||
extensionContent += ("<opentracks:distance>" + DISTANCE_FORMAT.format(cumulativeDistance.toM()) + "</opentracks:distance>\n");
|
||||
extensionContent += ("<cluetrust:distance>" + DISTANCE_FORMAT.format(trackDistance.plus(cumulativeDistance).toM()) + "</cluetrust:distance>\n");
|
||||
|
||||
@@ -95,7 +95,7 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
private final List<Float> powerList = new ArrayList<>();
|
||||
private final List<Float> cadenceList = new ArrayList<>();
|
||||
private final List<Float> heartRateList = new ArrayList<>();
|
||||
private final List<Float> altitudeGainList = new ArrayList<>();
|
||||
private final List<Float> altitudeGainList = new ArrayList<>(); //TODO Join with altitudeLossList
|
||||
private final List<Float> altitudeLossList = new ArrayList<>();
|
||||
private final List<Float> accuracyHorizontal = new ArrayList<>();
|
||||
private final List<Float> accuracyVertical = new ArrayList<>();
|
||||
@@ -167,7 +167,7 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
wroteTrack = true;
|
||||
}
|
||||
|
||||
switch (trackPoint.getType()) {
|
||||
switch (trackPoint.type()) {
|
||||
case SEGMENT_START_MANUAL, SEGMENT_START_AUTOMATIC -> {
|
||||
if (wroteSegment) writeCloseSegment();
|
||||
writeOpenSegment();
|
||||
@@ -190,7 +190,7 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
writeTrackPoint(track.zoneOffset(), trackPoint);
|
||||
}
|
||||
default ->
|
||||
throw new RuntimeException("Exporting this TrackPoint type is not implemented: " + trackPoint.getType());
|
||||
throw new RuntimeException("Exporting this TrackPoint type is not implemented: " + trackPoint.type());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,28 +370,28 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
void writeTrackPoint(ZoneOffset zoneOffset, TrackPoint trackPoint) {
|
||||
printWriter.println("<when>" + getTime(zoneOffset, trackPoint.getTime()) + "</when>");
|
||||
|
||||
trackpointTypeList.add(trackPoint.getType());
|
||||
trackpointTypeList.add(trackPoint.type());
|
||||
|
||||
if (trackPoint.hasLocation()) {
|
||||
printWriter.println("<coord>" + getCoordinates(trackPoint.getPosition(), " ") + "</coord>");
|
||||
if (trackPoint.position().hasLocation()) {
|
||||
printWriter.println("<coord>" + getCoordinates(trackPoint.position(), " ") + "</coord>");
|
||||
} else {
|
||||
printWriter.println("<coord/>");
|
||||
}
|
||||
speedList.add(trackPoint.hasSpeed() ? (float) trackPoint.getSpeed().toMPS() : null);
|
||||
speedList.add(trackPoint.position().hasSpeed() ? (float) trackPoint.position().speed().toMPS() : null);
|
||||
|
||||
distanceList.add(trackPoint.hasSensorDistance() ? (float) trackPoint.getSensorDistance().toM() : null);
|
||||
heartRateList.add(trackPoint.hasHeartRate() ? trackPoint.getHeartRate().getBPM() : null);
|
||||
cadenceList.add(trackPoint.hasCadence() ? trackPoint.getCadence().getRPM() : null);
|
||||
powerList.add(trackPoint.hasPower() ? trackPoint.getPower().getW() : null);
|
||||
if (trackPoint.hasAltitudeGainLoss()) {
|
||||
altitudeGainList.add(trackPoint.getAltitudeGainLoss().loss_m());
|
||||
altitudeLossList.add(trackPoint.getAltitudeGainLoss().loss_m());
|
||||
distanceList.add(trackPoint.sensorDistance() != null ? (float) trackPoint.sensorDistance().toM() : null);
|
||||
heartRateList.add(trackPoint.heartRate() != null ? trackPoint.heartRate().getBPM() : null);
|
||||
cadenceList.add(trackPoint.cadence() != null ? trackPoint.cadence().getRPM() : null);
|
||||
powerList.add(trackPoint.power() != null ? trackPoint.power().getW() : null);
|
||||
if (trackPoint.altitudeGainLoss() != null) {
|
||||
altitudeGainList.add(trackPoint.altitudeGainLoss().loss_m());
|
||||
altitudeLossList.add(trackPoint.altitudeGainLoss().loss_m());
|
||||
} else {
|
||||
altitudeGainList.add(null);
|
||||
altitudeLossList.add(null);
|
||||
}
|
||||
accuracyHorizontal.add(trackPoint.hasHorizontalAccuracy() ? (float) trackPoint.getHorizontalAccuracy().toM() : null);
|
||||
accuracyVertical.add(trackPoint.hasVerticalAccuracy() ? (float) trackPoint.getVerticalAccuracy().toM() : null);
|
||||
accuracyHorizontal.add(trackPoint.position().hasHorizontalAccuracy() ? (float) trackPoint.position().horizontalAccuracy().toM() : null);
|
||||
accuracyVertical.add(trackPoint.position().hasVerticalAccuracy() ? (float) trackPoint.position().verticalAccuracy().toM() : null);
|
||||
}
|
||||
|
||||
private void writeSimpleArraySensorData(List<Float> list, String name) {
|
||||
|
||||
@@ -32,9 +32,13 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Altitude;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
|
||||
import de.dennisguse.opentracks.data.models.Cadence;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
@@ -265,8 +269,8 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
return;
|
||||
}
|
||||
|
||||
TrackPoint first = currentSegment.getFirst();
|
||||
first.setType(TrackPoint.Type.SEGMENT_START_AUTOMATIC);
|
||||
TrackPoint first = currentSegment.removeFirst();
|
||||
currentSegment.addFirst(first.with(TrackPoint.Type.SEGMENT_START_AUTOMATIC));
|
||||
|
||||
trackImporter.addTrackPoints(currentSegment);
|
||||
currentSegment.clear();
|
||||
@@ -332,59 +336,70 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
}
|
||||
}
|
||||
|
||||
TrackPoint trackPoint = new TrackPoint(
|
||||
TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
parsedTime.toInstant(),
|
||||
latitudeParsed,
|
||||
longitudeParsed,
|
||||
accuracyHorizontalParsed,
|
||||
altitudeParsed,
|
||||
accuracyVerticalParsed,
|
||||
null,
|
||||
speedParsed
|
||||
));
|
||||
|
||||
if (heartrate != null) {
|
||||
try {
|
||||
trackPoint.setHeartRate(Float.parseFloat(heartrate));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse heart rate: %s", heartrate)), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (cadence != null) {
|
||||
try {
|
||||
trackPoint.setCadence(Float.parseFloat(cadence));
|
||||
} catch (Exception e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse cadence: %s", cadence)), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (power != null) {
|
||||
try {
|
||||
trackPoint.setPower(Float.parseFloat(power));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse power: %s", power)), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (gain != null && loss != null) {
|
||||
try {
|
||||
trackPoint.setAltitudeGainLoss(Float.parseFloat(gain), Float.parseFloat(loss));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse altitude gain: %s or los: %s", gain, loss)), e);
|
||||
}
|
||||
}
|
||||
Distance parsedSensorDistance = null;
|
||||
if (sensorDistance != null) {
|
||||
try {
|
||||
trackPoint.setSensorDistance(Distance.of(Float.parseFloat(sensorDistance)));
|
||||
parsedSensorDistance = Distance.of(Float.parseFloat(sensorDistance));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse distance: %s", sensorDistance)), e);
|
||||
}
|
||||
}
|
||||
|
||||
return trackPoint;
|
||||
HeartRate parsedHeartRate = null;
|
||||
if (heartrate != null) {
|
||||
try {
|
||||
parsedHeartRate = HeartRate.of(Float.parseFloat(heartrate));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse heart rate: %s", heartrate)), e);
|
||||
}
|
||||
}
|
||||
|
||||
Cadence parsedCadence = null;
|
||||
if (cadence != null) {
|
||||
try {
|
||||
parsedCadence = Cadence.of(Float.parseFloat(cadence));
|
||||
} catch (Exception e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse cadence: %s", cadence)), e);
|
||||
}
|
||||
}
|
||||
|
||||
Power parsedPower = null;
|
||||
if (power != null) {
|
||||
try {
|
||||
parsedPower = Power.of(Float.parseFloat(power));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse power: %s", power)), e);
|
||||
}
|
||||
}
|
||||
|
||||
AltitudeGainLoss altitudeGainLoss = null;
|
||||
if (gain != null && loss != null) {
|
||||
try {
|
||||
altitudeGainLoss = new AltitudeGainLoss(Float.parseFloat(gain), Float.parseFloat(loss));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse altitude gain: %s or los: %s", gain, loss)), e);
|
||||
}
|
||||
}
|
||||
|
||||
return new TrackPoint(
|
||||
null,
|
||||
TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
parsedTime.toInstant(),
|
||||
latitudeParsed,
|
||||
longitudeParsed,
|
||||
accuracyHorizontalParsed,
|
||||
altitudeParsed,
|
||||
accuracyVerticalParsed,
|
||||
null,
|
||||
speedParsed
|
||||
),
|
||||
parsedSensorDistance,
|
||||
parsedHeartRate,
|
||||
parsedCadence,
|
||||
parsedPower,
|
||||
altitudeGainLoss
|
||||
);
|
||||
}
|
||||
|
||||
private void onTrackPointStart(Attributes attributes) {
|
||||
@@ -425,8 +440,8 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
|
||||
TrackPoint trackPoint = createTrackPoint();
|
||||
|
||||
if (!trackPoint.hasLocation()) {
|
||||
Log.w(TAG, "Marker with invalid coordinates ignored: " + trackPoint.getPosition());
|
||||
if (!trackPoint.position().hasLocation()) {
|
||||
Log.w(TAG, "Marker with invalid coordinates ignored: " + trackPoint.position());
|
||||
return;
|
||||
}
|
||||
markers.add(new Marker(
|
||||
@@ -435,7 +450,7 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
name != null ? name : "",
|
||||
description != null ? description : "",
|
||||
markerType != null ? markerType : "",
|
||||
trackPoint.getPosition(),
|
||||
trackPoint.position(),
|
||||
photoUrl
|
||||
));
|
||||
}
|
||||
|
||||
@@ -33,9 +33,13 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
|
||||
import de.dennisguse.opentracks.data.models.Cadence;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
@@ -95,10 +99,11 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
private ZoneOffset zoneOffset;
|
||||
|
||||
private final ArrayList<Instant> whenList = new ArrayList<>();
|
||||
private final ArrayList<Position> positionList = new ArrayList<>();
|
||||
private final ArrayList<Position> positionList = new ArrayList<>(); //TODO This is only latitude, longitude, and altitude
|
||||
|
||||
private String dataType;
|
||||
|
||||
//TODO For ArrayList use specific data models; and why Float? Double would be easier.
|
||||
private final ArrayList<String> trackpointTypeList = new ArrayList<>();
|
||||
private final ArrayList<Float> sensorSpeedList = new ArrayList<>();
|
||||
private final ArrayList<Float> sensorDistanceList = new ArrayList<>();
|
||||
@@ -151,8 +156,7 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
}
|
||||
onTrackSegmentStart();
|
||||
}
|
||||
case TAG_EXTENDED_DATA, TAG_SIMPLE_ARRAY_DATA, TAG_KML22_SIMPLE_ARRAY_DATA ->
|
||||
dataType = attributes.getValue(ATTRIBUTE_NAME);
|
||||
case TAG_EXTENDED_DATA, TAG_SIMPLE_ARRAY_DATA, TAG_KML22_SIMPLE_ARRAY_DATA -> dataType = attributes.getValue(ATTRIBUTE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,62 +321,77 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
for (int i = 0; i < positionList.size(); i++) {
|
||||
Instant time = whenList.get(i);
|
||||
Position position = positionList.get(i);
|
||||
|
||||
TrackPoint trackPoint;
|
||||
if (position == null) {
|
||||
trackPoint = new TrackPoint(TrackPoint.Type.TRACKPOINT, Position.of(time));
|
||||
position = Position.of(time);
|
||||
} else {
|
||||
trackPoint = new TrackPoint(TrackPoint.Type.TRACKPOINT, position.with(time));
|
||||
position = position.with(time);
|
||||
}
|
||||
|
||||
TrackPoint.Type type = null;
|
||||
Speed speed = null;
|
||||
Distance sensorDistance = null;
|
||||
HeartRate heartRate = null;
|
||||
Cadence cadence = null;
|
||||
Power power = null;
|
||||
AltitudeGainLoss altitudeGainLoss = null;
|
||||
Distance horizontalAccuracy = null;
|
||||
Distance verticalAccuracy = null;
|
||||
|
||||
if (i < trackpointTypeList.size() && trackpointTypeList.get(i) != null) {
|
||||
TrackPoint.Type type = TrackPoint.Type.valueOf(trackpointTypeList.get(i));
|
||||
trackPoint.setType(type);
|
||||
type = TrackPoint.Type.valueOf(trackpointTypeList.get(i));
|
||||
}
|
||||
|
||||
if (i < sensorSpeedList.size() && sensorSpeedList.get(i) != null) {
|
||||
trackPoint.setSpeed(Speed.of(sensorSpeedList.get(i)));
|
||||
speed = Speed.of(sensorSpeedList.get(i));
|
||||
}
|
||||
if (i < sensorDistanceList.size() && sensorDistanceList.get(i) != null) {
|
||||
trackPoint.setSensorDistance(Distance.of(sensorDistanceList.get(i)));
|
||||
sensorDistance = Distance.of(sensorDistanceList.get(i));
|
||||
}
|
||||
if (i < sensorHeartRateList.size() && sensorHeartRateList.get(i) != null) {
|
||||
trackPoint.setHeartRate(sensorHeartRateList.get(i));
|
||||
if (i < sensorHeartRateList.size()) {
|
||||
heartRate = HeartRate.ofOrNull(sensorHeartRateList.get(i));
|
||||
}
|
||||
if (i < sensorCadenceList.size() && sensorCadenceList.get(i) != null) {
|
||||
trackPoint.setCadence(sensorCadenceList.get(i));
|
||||
cadence = Cadence.of(sensorCadenceList.get(i));
|
||||
}
|
||||
if (i < sensorPowerList.size() && sensorPowerList.get(i) != null) {
|
||||
trackPoint.setPower(sensorPowerList.get(i));
|
||||
power = Power.of(sensorPowerList.get(i));
|
||||
}
|
||||
if (i < altitudeGainList.size() && i < altitudeLossList.size()) {
|
||||
if (altitudeGainList.get(i) != null && altitudeLossList.get(i) != null) {
|
||||
trackPoint.setAltitudeGainLoss(altitudeGainList.get(i), altitudeLossList.get(i));
|
||||
}
|
||||
if ((i < altitudeGainList.size() && altitudeGainList.get(i) != null)
|
||||
&& (i < altitudeLossList.size() && altitudeLossList.get(i) != null)) {
|
||||
altitudeGainLoss = new AltitudeGainLoss(altitudeGainList.get(i), altitudeLossList.get(i));
|
||||
}
|
||||
if (i < accuracyHorizontal.size() && accuracyHorizontal.get(i) != null) {
|
||||
trackPoint.setHorizontalAccuracy(Distance.of(accuracyHorizontal.get(i)));
|
||||
horizontalAccuracy = Distance.of(accuracyHorizontal.get(i));
|
||||
}
|
||||
if (i < accuracyVertical.size() && accuracyVertical.get(i) != null) {
|
||||
trackPoint.setVerticalAccuracy(Distance.of(accuracyVertical.get(i)));
|
||||
verticalAccuracy = Distance.of(accuracyVertical.get(i));
|
||||
}
|
||||
|
||||
// Update TrackPoint type for START / STOP.
|
||||
TrackPoint.Type type = trackPoint.getType();
|
||||
if (i == 0) {
|
||||
//first
|
||||
if (!trackPoint.wasCreatedManually()) {
|
||||
type = TrackPoint.Type.SEGMENT_START_MANUAL;
|
||||
} else {
|
||||
if (wasCreatedAutomatically(position)) {
|
||||
type = TrackPoint.Type.SEGMENT_START_AUTOMATIC;
|
||||
} else {
|
||||
type = TrackPoint.Type.SEGMENT_START_MANUAL;
|
||||
}
|
||||
} else if (i == positionList.size() - 1 && !trackPoint.wasCreatedManually()) {
|
||||
} else if (i == positionList.size() - 1 && !wasCreatedAutomatically(position)) {
|
||||
//last
|
||||
type = TrackPoint.Type.SEGMENT_END_MANUAL;
|
||||
}
|
||||
trackPoint.setType(type);
|
||||
|
||||
trackImporter.addTrackPoint(trackPoint);
|
||||
trackImporter.addTrackPoint(new TrackPoint(
|
||||
null,
|
||||
type != null ? type : TrackPoint.Type.TRACKPOINT,
|
||||
position
|
||||
.with(speed)
|
||||
.withHorizontalAccuracy(horizontalAccuracy)
|
||||
.withVerticalAccuracy(verticalAccuracy),
|
||||
sensorDistance,
|
||||
heartRate,
|
||||
cadence,
|
||||
power,
|
||||
altitudeGainLoss
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,6 +411,7 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
}
|
||||
|
||||
private Position createPosition(String latitude, String longitude, String altitude) {
|
||||
//TODO Do not use Location.
|
||||
if (longitude != null && latitude != null) {
|
||||
Location location = new Location("import");
|
||||
try {
|
||||
@@ -439,12 +459,9 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_CADENCE -> sensorCadenceList.add(value);
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_ALTITUDE_GAIN -> altitudeGainList.add(value);
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_ALTITUDE_LOSS -> altitudeLossList.add(value);
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_ACCURACY_HORIZONTAL ->
|
||||
accuracyHorizontal.add(value);
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_ACCURACY_VERTICAL ->
|
||||
accuracyVertical.add(value);
|
||||
default ->
|
||||
Log.w(TAG, "Data from extended data " + dataType + " is not (yet) supported.");
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_ACCURACY_HORIZONTAL -> accuracyHorizontal.add(value);
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_ACCURACY_VERTICAL -> accuracyVertical.add(value);
|
||||
default -> Log.w(TAG, "Data from extended data " + dataType + " is not (yet) supported.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,6 +474,10 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
trackImporter.finish();
|
||||
}
|
||||
|
||||
public boolean wasCreatedAutomatically(Position position) {
|
||||
return position.hasLocation() || position.hasSpeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultHandler getHandler() {
|
||||
return this;
|
||||
|
||||
@@ -176,21 +176,19 @@ public class TrackImporter {
|
||||
TrackPoint previous = trackPoints.get(i - 1);
|
||||
TrackPoint current = trackPoints.get(i);
|
||||
|
||||
if (current.hasSensorDistance() || (previous.hasLocation() && current.hasLocation())) {
|
||||
if (current.sensorDistance() != null || (previous.position().hasLocation() && current.position().hasLocation())) {
|
||||
TrackPoint newCurrent = current;
|
||||
|
||||
Distance distanceToPrevious = current.distanceToPrevious(previous);
|
||||
if (!current.hasSpeed()) {
|
||||
if (!current.position().hasSpeed()) {
|
||||
Duration timeDifference = Duration.between(previous.getTime(), current.getTime());
|
||||
current.setSpeed(Speed.of(distanceToPrevious, timeDifference));
|
||||
newCurrent = newCurrent.with(newCurrent.position().with(Speed.of(distanceToPrevious, timeDifference)));
|
||||
}
|
||||
|
||||
if (!current.hasBearing()) {
|
||||
previous.bearingTo(current)
|
||||
.ifPresent(current::setBearing);
|
||||
}
|
||||
|
||||
if (current.getType().equals(TrackPoint.Type.TRACKPOINT) && distanceToPrevious.greaterThan(maxRecordingDistance)) {
|
||||
current.setType(TrackPoint.Type.SEGMENT_START_AUTOMATIC);
|
||||
if (current.type().equals(TrackPoint.Type.TRACKPOINT) && distanceToPrevious.greaterThan(maxRecordingDistance)) {
|
||||
newCurrent = newCurrent.with(TrackPoint.Type.SEGMENT_START_AUTOMATIC);
|
||||
}
|
||||
trackPoints.set(i, newCurrent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user