forked from upstream-mirrors/OpenTracks
447d1bb7a3
Fixes #2258.
137 lines
4.1 KiB
Java
137 lines
4.1 KiB
Java
package de.dennisguse.opentracks.data.models;
|
|
|
|
import android.location.Location;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
|
|
import java.time.Instant;
|
|
|
|
public record Position(
|
|
@Nullable Instant time, //TODO It may be a good idea to move time out of Position
|
|
@Nullable Double latitude,
|
|
@Nullable Double longitude,
|
|
@Nullable Distance horizontalAccuracy,
|
|
@Nullable Altitude altitude,
|
|
@Nullable Distance verticalAccuracy,
|
|
@Nullable Float bearing,
|
|
@Nullable Speed speed
|
|
) {
|
|
|
|
public static Position of(@NonNull Instant time) {
|
|
return new Position(
|
|
time,
|
|
null,
|
|
null,
|
|
null,
|
|
null,
|
|
null,
|
|
null,
|
|
null
|
|
);
|
|
}
|
|
|
|
public static Position of(@NonNull Location location, @NonNull Instant time) {
|
|
return new Position(
|
|
time,
|
|
location.getLatitude(),
|
|
location.getLongitude(),
|
|
location.hasAccuracy() ? Distance.of(location.getAccuracy()) : null,
|
|
location.hasAltitude() ? Altitude.WGS84.of(location.getAltitude()) : null,
|
|
location.hasVerticalAccuracy() ? Distance.of(location.getVerticalAccuracyMeters()) : null,
|
|
location.hasBearing() ? location.getBearing() : null,
|
|
location.hasSpeed() ? Speed.of(location.getSpeed()) : null
|
|
);
|
|
}
|
|
|
|
public boolean hasLocation() {
|
|
return latitude != null && longitude != null;
|
|
}
|
|
|
|
public boolean hasHorizontalAccuracy() {
|
|
return horizontalAccuracy != null;
|
|
}
|
|
|
|
public boolean hasAltitude() {
|
|
return altitude != null;
|
|
}
|
|
|
|
public boolean hasVerticalAccuracy() {
|
|
return verticalAccuracy != null;
|
|
}
|
|
|
|
public boolean hasBearing() {
|
|
return bearing != null;
|
|
}
|
|
|
|
public boolean hasSpeed() {
|
|
return speed != null;
|
|
}
|
|
|
|
public Location toLocation() {
|
|
if (!hasLocation()) {
|
|
throw new RuntimeException("Cannot convert to Location.");
|
|
}
|
|
|
|
Location location = new Location("");
|
|
if (time != null) {
|
|
location.setTime(time.toEpochMilli());
|
|
}
|
|
location.setLatitude(latitude);
|
|
location.setLongitude(longitude);
|
|
if (hasBearing()) {
|
|
location.setBearing(bearing);
|
|
}
|
|
if (hasHorizontalAccuracy()) {
|
|
location.setAccuracy((float) horizontalAccuracy.toM());
|
|
}
|
|
if (hasAltitude()) {
|
|
location.setAltitude(altitude.toM());
|
|
}
|
|
if (hasSpeed()) {
|
|
location.setSpeed((float) speed.toMPS());
|
|
}
|
|
|
|
return location;
|
|
}
|
|
|
|
/**
|
|
* Checks if a given location is a valid (i.e. physically possible) location on Earth.
|
|
*
|
|
* @return true if the location is a valid location.
|
|
*/
|
|
public boolean hasValidLocation() {
|
|
return hasLocation()
|
|
&& Math.abs(latitude) <= 90
|
|
&& Math.abs(longitude) <= 180;
|
|
}
|
|
|
|
public boolean fulfillsAccuracy(Distance thresholdHorizontalAccuracy) {
|
|
return hasHorizontalAccuracy() &&
|
|
horizontalAccuracy
|
|
.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);
|
|
}
|
|
|
|
public Position withCoordinates(Position position) {
|
|
return new Position(time, position.latitude, position.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);
|
|
}
|
|
}
|