mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-10 06:10:56 +00:00
moved a few more distance and speed types to domain.common and fixed a grave bug in MeterPerSecondSpeed; added test for improved outlier filtering
This commit is contained in:
1 parent
33ff5e6279
commit
f1fa1d74f6
228 files changed
+471
-353
No files matched your search
+17
@@ -0,0 +1,17 @@
|
||||
package com.sap.sailing.domain.common;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A course change represents a change of the course over ground as well as the speed over ground.
|
||||
* {@link SpeedWithBearing#applyCourseChange(CourseChange) Applying} this {@link CourseChange} object to a
|
||||
* {@link SpeedWithBearing} results in the {@link SpeedWithBearing} as it was after this course change.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public interface CourseChange {
|
||||
double getCourseChangeInDegrees();
|
||||
|
||||
double getSpeedChangeInKnots();
|
||||
}
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
package com.sap.sailing.domain.common;
|
||||
|
||||
|
||||
|
||||
public interface SpeedWithBearing extends Speed {
|
||||
Bearing getBearing();
|
||||
|
||||
/**
|
||||
* Traveling at this speed starting at time <code>from</code> in position <code>pos</code> until time
|
||||
* </code>to</code>, how far have we traveled? If <code>to</code> is before </code>from</code>, the speed will be
|
||||
* applied in reverse.
|
||||
*/
|
||||
Position travelTo(Position pos, TimePoint from, TimePoint to);
|
||||
|
||||
/**
|
||||
* Computes the minimal (in terms of bearing change) course and speed change required to reach the
|
||||
* target speed and bearing specified.
|
||||
*/
|
||||
CourseChange getCourseChangeRequiredToReach(SpeedWithBearing targetSpeedWithBearing);
|
||||
|
||||
SpeedWithBearing applyCourseChange(CourseChange courseChange);
|
||||
|
||||
/**
|
||||
* Projects this speed onto <code>bearing</code>. The speed will keep its sign, regardless of whether the <code>bearing</code> points in
|
||||
* the opposite direction or not. The resulting speed can never be greater than this speed. If this speed's bearing is orthogonal to
|
||||
* <code>bearing</code>, a zero speed will result.
|
||||
*
|
||||
* @param position the position at which to perform the projection; the angle between the bearings depends on the position
|
||||
*/
|
||||
Speed projectTo(Position position, Bearing bearing);
|
||||
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package com.sap.sailing.domain.common.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.AbstractSpeedImpl;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.CourseChange;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
|
||||
public abstract class AbstractSpeedWithAbstractBearingImpl extends AbstractSpeedImpl implements SpeedWithBearing {
|
||||
private static final long serialVersionUID = 6136100417593538013L;
|
||||
|
||||
@Override
|
||||
public Position travelTo(Position pos, TimePoint from, TimePoint to) {
|
||||
return pos.translateGreatCircle(getBearing(), this.travel(from, to));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString()+" to "+getBearing().getDegrees()+"°";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode() ^ getBearing().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
return super.equals(object) && object instanceof SpeedWithBearing
|
||||
&& getBearing().equals(((SpeedWithBearing) object).getBearing());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CourseChange getCourseChangeRequiredToReach(SpeedWithBearing targetSpeedWithBearing) {
|
||||
return AbstractSpeedWithBearingImpl.getCourseChangeRequiredToReach(this, targetSpeedWithBearing);
|
||||
}
|
||||
|
||||
public static CourseChange getCourseChangeRequiredToReach(SpeedWithBearing from, SpeedWithBearing to) {
|
||||
double courseChangeInDegrees = to.getBearing().getDegrees() - from.getBearing().getDegrees();
|
||||
if (courseChangeInDegrees < -180.) {
|
||||
courseChangeInDegrees += 360.;
|
||||
} else if (courseChangeInDegrees > 180.) {
|
||||
courseChangeInDegrees -= 360.;
|
||||
}
|
||||
double speedChangeInKnots = to.getKnots() - from.getKnots();
|
||||
return new CourseChangeImpl(courseChangeInDegrees, speedChangeInKnots);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpeedWithBearing applyCourseChange(CourseChange courseChange) {
|
||||
return applyCourseChange(this, courseChange);
|
||||
}
|
||||
|
||||
public static SpeedWithBearing applyCourseChange(SpeedWithBearing from, CourseChange courseChange) {
|
||||
double newBearingDeg = from.getBearing().getDegrees() + courseChange.getCourseChangeInDegrees();
|
||||
if (newBearingDeg < 0) {
|
||||
newBearingDeg += 360;
|
||||
} else if (newBearingDeg > 360) {
|
||||
newBearingDeg -= 360;
|
||||
}
|
||||
Bearing newBearing = new DegreeBearingImpl(newBearingDeg);
|
||||
double newSpeedInKnots = from.getKnots()+courseChange.getSpeedChangeInKnots();
|
||||
return new KnotSpeedWithBearingImpl(newSpeedInKnots, newBearing);
|
||||
}
|
||||
|
||||
private final static TimePoint start = new MillisecondsTimePoint(0);
|
||||
private final static TimePoint end = start.plus(60000);
|
||||
|
||||
public static Speed projectTo(SpeedWithBearing speedWithBearing, Position position, Bearing projectTo) {
|
||||
Position traveledOneMinute = speedWithBearing.travelTo(position, start, end);
|
||||
Position traveledToProjected = traveledOneMinute.projectToLineThrough(position, projectTo);
|
||||
Distance projectedDistance = position.getDistance(traveledToProjected);
|
||||
return projectedDistance.inTime(end.asMillis() - start.asMillis());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed projectTo(Position position, Bearing projectTo) {
|
||||
return projectTo(this, position, projectTo);
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.sap.sailing.domain.common.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
|
||||
public abstract class AbstractSpeedWithBearingImpl extends AbstractSpeedWithAbstractBearingImpl implements SpeedWithBearing {
|
||||
private static final long serialVersionUID = -8594305027333573010L;
|
||||
private final Bearing bearing;
|
||||
|
||||
protected AbstractSpeedWithBearingImpl(Bearing bearing) {
|
||||
this.bearing = bearing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getBearing() {
|
||||
return bearing;
|
||||
}
|
||||
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
package com.sap.sailing.domain.common.impl;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
|
||||
public abstract class AbstractTimePoint implements TimePoint {
|
||||
private static final long serialVersionUID = 8825508619301420378L;
|
||||
|
||||
public static SimpleDateFormat TIMEPOINT_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
||||
|
||||
public static Comparator<TimePoint> TIMEPOINT_COMPARATOR = new SerializableComparator<TimePoint>() {
|
||||
private static final long serialVersionUID = 7644726881387366025L;
|
||||
|
||||
@Override
|
||||
public int compare(TimePoint o1, TimePoint o2) {
|
||||
long milliDiff = o1.asMillis() - o2.asMillis();
|
||||
return milliDiff<0 ? -1 : milliDiff == 0 ? 0 : 1;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int compareTo(TimePoint o) {
|
||||
return TIMEPOINT_COMPARATOR.compare(this, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date asDate() {
|
||||
Date result = getDateFromCache();
|
||||
if (result == null) {
|
||||
result = new Date(asMillis());
|
||||
cacheDate(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePoint plus(long milliseconds) {
|
||||
return new MillisecondsTimePoint(asMillis()+milliseconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePoint minus(long milliseconds) {
|
||||
return plus(-milliseconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean after(TimePoint other) {
|
||||
return this.compareTo(other) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean before(TimePoint other) {
|
||||
return this.compareTo(other) < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) (asMillis() & Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return compareTo((TimePoint) obj) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return TIMEPOINT_FORMATTER.format(asDate());
|
||||
}
|
||||
|
||||
/**
|
||||
* A subclass may implement a cache for the {@link Date} representation by overriding this method as well
|
||||
* as {@link #cacheDate(Date)}.
|
||||
*/
|
||||
protected Date getDateFromCache() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A subclass may implement a cache for the {@link Date} representation by overriding this method as well
|
||||
* as {@link #getDate()}.
|
||||
*/
|
||||
protected void cacheDate(Date date) {}
|
||||
}
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
package com.sap.sailing.domain.common.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.CourseChange;
|
||||
|
||||
public class CourseChangeImpl implements CourseChange {
|
||||
private final double courseChangeInDegrees;
|
||||
private final double speedChangeInKnots;
|
||||
|
||||
public CourseChangeImpl(double courseChangeInDegrees, double speedChangeInKnots) {
|
||||
this.courseChangeInDegrees = courseChangeInDegrees;
|
||||
this.speedChangeInKnots = speedChangeInKnots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCourseChangeInDegrees() {
|
||||
return courseChangeInDegrees;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getSpeedChangeInKnots() {
|
||||
return speedChangeInKnots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "changing course by "+getCourseChangeInDegrees()+"deg, "+getSpeedChangeInKnots()+"kn";
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.sap.sailing.domain.common.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
|
||||
public class KnotSpeedWithBearingImpl extends AbstractSpeedWithBearingImpl {
|
||||
private static final long serialVersionUID = -2300633070560631053L;
|
||||
private final double speedInKnots;
|
||||
|
||||
public KnotSpeedWithBearingImpl(double speedInKnots, Bearing bearing) {
|
||||
super(bearing);
|
||||
this.speedInKnots = speedInKnots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getKnots() {
|
||||
return speedInKnots;
|
||||
}
|
||||
|
||||
}
|
||||
+5
@@ -21,4 +21,9 @@ public class MeterDistance extends AbstractDistance {
|
||||
return new MeterDistance(factor * meters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCentralAngleDeg() {
|
||||
return getGeographicalMiles() / 60.;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -18,6 +18,6 @@ public class MeterPerSecondSpeedImpl extends AbstractSpeedImpl implements Speed
|
||||
|
||||
@Override
|
||||
public double getKilometersPerHour() {
|
||||
return metersPerSecond/3.6;
|
||||
return metersPerSecond*3.6;
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.sap.sailing.domain.common.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
|
||||
public class MeterPerSecondSpeedWithDegreeBearingImpl extends AbstractSpeedWithAbstractBearingImpl {
|
||||
private static final long serialVersionUID = -524654796500981303L;
|
||||
private final double metersPerSecond;
|
||||
private final Bearing bearing;
|
||||
|
||||
public MeterPerSecondSpeedWithDegreeBearingImpl(double metersPerSecond, Bearing bearing) {
|
||||
this.metersPerSecond = metersPerSecond;
|
||||
this.bearing = bearing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMetersPerSecond() {
|
||||
return metersPerSecond;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getKilometersPerHour() {
|
||||
return metersPerSecond*3.6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getBearing() {
|
||||
return bearing;
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.sap.sailing.domain.common.impl;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
public class MillisecondsTimePoint extends AbstractTimePoint {
|
||||
private static final long serialVersionUID = -1021748860232043166L;
|
||||
private final long millis;
|
||||
private Date date;
|
||||
|
||||
public static MillisecondsTimePoint now() {
|
||||
return new MillisecondsTimePoint(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public MillisecondsTimePoint(long millis) {
|
||||
super();
|
||||
this.millis = millis;
|
||||
}
|
||||
|
||||
public MillisecondsTimePoint(Date date) {
|
||||
super();
|
||||
this.millis = date.getTime();
|
||||
}
|
||||
|
||||
protected Date getDateFromCache() {
|
||||
return date;
|
||||
}
|
||||
|
||||
protected void cacheDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asMillis() {
|
||||
return millis;
|
||||
}
|
||||
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.sap.sailing.domain.common.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Comparator;
|
||||
|
||||
public interface SerializableComparator<T> extends Comparator<T>, Serializable {
|
||||
}
|
||||
Reference in new issue
Block a user