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:
Axel Uhl committed 2013-08-14 18:00:45 +02:00
1 parent 33ff5e6279
commit f1fa1d74f6
228 files changed
+471 -353

No files matched your search

@@ -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();
}
@@ -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);
}
@@ -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);
}
}
@@ -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;
}
}
@@ -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) {}
}
@@ -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";
}
}
@@ -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;
}
}
@@ -21,4 +21,9 @@ public class MeterDistance extends AbstractDistance {
return new MeterDistance(factor * meters);
}
@Override
public double getCentralAngleDeg() {
return getGeographicalMiles() / 60.;
}
}
@@ -18,6 +18,6 @@ public class MeterPerSecondSpeedImpl extends AbstractSpeedImpl implements Speed
@Override
public double getKilometersPerHour() {
return metersPerSecond/3.6;
return metersPerSecond*3.6;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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 {
}