mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-04 19:33:52 +00:00
refactored Douglas-Peucker to use List<FixType> instead of GPSFix[]; moved DP usage to TrackedRaceImpl
This commit is contained in:
1 parent
bc703fd4b6
commit
f796f24858
7 files changed
+64
-36
No files matched your search
+9
-9
@@ -7,6 +7,7 @@ import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -19,7 +20,6 @@ import com.sap.sailing.domain.base.impl.DouglasPeucker;
|
||||
import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.base.impl.MeterDistance;
|
||||
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
@@ -53,18 +53,18 @@ public class ManeuverDetectionOnKielerWoche505Race2DataTest extends KielWeek2011
|
||||
Iterator<MarkPassing> hassosMarkPassingsIter = hassosMarkPassings.iterator();
|
||||
TimePoint startMarkPassing = hassosMarkPassingsIter.next().getTimePoint();
|
||||
TimePoint firstWindwardMarkPassing = hassosMarkPassingsIter.next().getTimePoint();
|
||||
GPSFix[] firstLegFineApproximation = dp.approximate(new MeterDistance(20), startMarkPassing, firstWindwardMarkPassing);
|
||||
List<GPSFixMoving> firstLegFineApproximation = dp.approximate(new MeterDistance(20), startMarkPassing, firstWindwardMarkPassing);
|
||||
assertNotNull(firstLegFineApproximation);
|
||||
assertEquals(9, firstLegFineApproximation.length);
|
||||
GPSFix[] firstLegCoarseApproximation = dp.approximate(new MeterDistance(50), startMarkPassing, firstWindwardMarkPassing);
|
||||
assertEquals(9, firstLegFineApproximation.size());
|
||||
List<GPSFixMoving> firstLegCoarseApproximation = dp.approximate(new MeterDistance(50), startMarkPassing, firstWindwardMarkPassing);
|
||||
assertNotNull(firstLegCoarseApproximation);
|
||||
assertEquals(4, firstLegCoarseApproximation.length);
|
||||
assertEquals(4, firstLegCoarseApproximation.size());
|
||||
TimePoint leewardGatePassing = hassosMarkPassingsIter.next().getTimePoint();
|
||||
GPSFix[] secondLegFineApproximation = dp.approximate(new MeterDistance(20), firstWindwardMarkPassing, leewardGatePassing);
|
||||
List<GPSFixMoving> secondLegFineApproximation = dp.approximate(new MeterDistance(20), firstWindwardMarkPassing, leewardGatePassing);
|
||||
assertNotNull(secondLegFineApproximation);
|
||||
assertEquals(7, secondLegFineApproximation.length);
|
||||
GPSFix[] secondLegCoarseApproximation = dp.approximate(new MeterDistance(50), firstWindwardMarkPassing, leewardGatePassing);
|
||||
assertEquals(7, secondLegFineApproximation.size());
|
||||
List<GPSFixMoving> secondLegCoarseApproximation = dp.approximate(new MeterDistance(50), firstWindwardMarkPassing, leewardGatePassing);
|
||||
assertNotNull(secondLegCoarseApproximation);
|
||||
assertEquals(3, secondLegCoarseApproximation.length);
|
||||
assertEquals(3, secondLegCoarseApproximation.size());
|
||||
}
|
||||
}
|
||||
+7
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.test.mock;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
@@ -405,4 +406,10 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GPSFixMoving> approximate(Competitor competitor, Distance maxDistance, TimePoint from, TimePoint to) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+22
-13
@@ -1,6 +1,9 @@
|
||||
package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.base.Bearing;
|
||||
import com.sap.sailing.domain.base.Distance;
|
||||
@@ -56,26 +59,32 @@ public class DouglasPeucker<ItemType, FixType extends GPSFix> {
|
||||
* the maximum distance of any fix on the {@link #track} to the approximation is less than
|
||||
* <code>maxDistance</code>.
|
||||
*/
|
||||
public GPSFix[] approximate(Distance maxDistance, TimePoint from, TimePoint to) {
|
||||
GPSFix[] resultWithoutFirstFix = approximateWithoutFirst(maxDistance, from, to);
|
||||
GPSFix[] result = new GPSFix[resultWithoutFirstFix.length+1];
|
||||
result[0] = track.getFirstFixAtOrAfter(from);
|
||||
System.arraycopy(resultWithoutFirstFix, 0, result, 1, resultWithoutFirstFix.length);
|
||||
public List<FixType> approximate(Distance maxDistance, TimePoint from, TimePoint to) {
|
||||
List<FixType> resultWithoutFirstFix = approximateWithoutFirst(maxDistance, from, to);
|
||||
List<FixType> result = new ArrayList<FixType>(resultWithoutFirstFix.size()+1);
|
||||
result.add(track.getFirstFixAtOrAfter(from));
|
||||
for (FixType f : resultWithoutFirstFix) {
|
||||
result.add(f);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private GPSFix[] approximateWithoutFirst(Distance maxDistance, TimePoint from, TimePoint to) {
|
||||
GPSFix[] result;
|
||||
private List<FixType> approximateWithoutFirst(Distance maxDistance, TimePoint from, TimePoint to) {
|
||||
List<FixType> result;
|
||||
Pair<GPSFix, Distance> fixAndDistance = getFixWithGreatestCrossTrackErrorInInterval(from, to);
|
||||
if (fixAndDistance.getB().compareTo(maxDistance) < 0) {
|
||||
// reached desired accuracy for interval from..to
|
||||
result = new GPSFix[] { track.getLastFixAtOrBefore(to) };
|
||||
result = Collections.singletonList(track.getLastFixAtOrBefore(to));
|
||||
} else {
|
||||
GPSFix[] left = approximateWithoutFirst(maxDistance, from, fixAndDistance.getA().getTimePoint());
|
||||
GPSFix[] right = approximateWithoutFirst(maxDistance, fixAndDistance.getA().getTimePoint(), to);
|
||||
result = new GPSFix[left.length+right.length];
|
||||
System.arraycopy(left, 0, result, 0, left.length);
|
||||
System.arraycopy(right, 0, result, left.length, right.length);
|
||||
List<FixType> left = approximateWithoutFirst(maxDistance, from, fixAndDistance.getA().getTimePoint());
|
||||
List<FixType> right = approximateWithoutFirst(maxDistance, fixAndDistance.getA().getTimePoint(), to);
|
||||
result = new ArrayList<FixType>(left.size()+right.size());
|
||||
for (FixType fixFromLeft : left) {
|
||||
result.add(fixFromLeft);
|
||||
}
|
||||
for (FixType fixFromRight : right) {
|
||||
result.add(fixFromRight);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.tracking;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
|
||||
import com.sap.sailing.domain.base.Buoy;
|
||||
@@ -12,6 +13,7 @@ import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Tack;
|
||||
import com.sap.sailing.domain.base.TimePoint;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.base.impl.DouglasPeucker;
|
||||
|
||||
/**
|
||||
* Live tracking data of a single race. The race follows a defined {@link Course} with a sequence of {@link Leg}s. The
|
||||
@@ -206,4 +208,11 @@ public interface TrackedRace {
|
||||
TrackedEvent getTrackedEvent();
|
||||
|
||||
Wind getDirectionFromStartToNextMark(TimePoint at);
|
||||
|
||||
/**
|
||||
* Uses a {@link DouglasPeucker Douglas-Peucker} algorithm to approximate this track's fixes starting at
|
||||
* time <code>from</code> until time point <code>to</code> such that the maximum distance between the
|
||||
* track's fixes and the approximation is at most <code>maxDistance</code>.
|
||||
*/
|
||||
List<GPSFixMoving> approximate(Competitor competitor, Distance maxDistance, TimePoint from, TimePoint to);
|
||||
}
|
||||
+9
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.tracking.impl;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
@@ -10,10 +11,12 @@ import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.base.Buoy;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Distance;
|
||||
import com.sap.sailing.domain.base.Leg;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.TimePoint;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.base.impl.DouglasPeucker;
|
||||
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedEvent;
|
||||
@@ -280,4 +283,10 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
|
||||
public DynamicTrackedEvent getTrackedEvent() {
|
||||
return (DynamicTrackedEvent) super.getTrackedEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GPSFixMoving> approximate(Competitor competitor, Distance maxDistance, TimePoint from, TimePoint to) {
|
||||
DouglasPeucker<Competitor, GPSFixMoving> douglasPeucker = new DouglasPeucker<Competitor, GPSFixMoving>(getTrack(competitor));
|
||||
return douglasPeucker.approximate(maxDistance, from, to);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -758,7 +758,7 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
|
||||
Map<CompetitorDAO, Date> to = new HashMap<CompetitorDAO, Date>();
|
||||
to.put(competitorDAO, fixes.get(competitorDAO).get(lastShownFix.get(competitorDAO)).timepoint);
|
||||
sailingService.getDouglasPoints(event.name, race.name, from,
|
||||
to, /* epsilon/meters */ 10, new AsyncCallback<Map<CompetitorDAO, List<GPSFixDAO>>>() {
|
||||
to, /* epsilon/meters */ 3, new AsyncCallback<Map<CompetitorDAO, List<GPSFixDAO>>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Error obtaining douglas positions: " + caught.getMessage());
|
||||
|
||||
+7
-13
@@ -40,7 +40,6 @@ import com.sap.sailing.domain.base.TimePoint;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.base.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.base.impl.DegreePosition;
|
||||
import com.sap.sailing.domain.base.impl.DouglasPeucker;
|
||||
import com.sap.sailing.domain.base.impl.KilometersPerHourSpeedImpl;
|
||||
import com.sap.sailing.domain.base.impl.KnotSpeedImpl;
|
||||
import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
|
||||
@@ -1117,28 +1116,23 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
Map<CompetitorDAO, Date> from, Map<CompetitorDAO, Date> to,
|
||||
double meters) {
|
||||
Map<CompetitorDAO, List<GPSFixDAO>> result = new HashMap<CompetitorDAO, List<GPSFixDAO>>();
|
||||
Event event = getService().getEventByName(eventName);
|
||||
RaceDefinition race = getRaceByName(event, raceName);
|
||||
TrackedRace trackedRace = getService().getOrCreateTrackedEvent(event).getTrackedRace(race);
|
||||
TrackedRace trackedRace = getTrackedRace(eventName, raceName);
|
||||
MeterDistance maxDistance = new MeterDistance(meters);
|
||||
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
|
||||
CompetitorDAO competitorDAO = getCompetitorDAO(competitor);
|
||||
if (from.containsKey(competitorDAO)) {
|
||||
// get Track of competitor
|
||||
GPSFixTrack<Competitor, GPSFixMoving> gpsFixTrack = getTrackedRace(eventName, raceName).getTrack(
|
||||
competitor);
|
||||
DouglasPeucker<Competitor, GPSFixMoving> douglas = new DouglasPeucker<Competitor, GPSFixMoving>(
|
||||
gpsFixTrack);
|
||||
GPSFixTrack<Competitor, GPSFixMoving> gpsFixTrack = trackedRace.getTrack(competitor);
|
||||
// Distance for DouglasPeucker
|
||||
TimePoint timePointFrom = new MillisecondsTimePoint(from.get(competitorDAO));
|
||||
TimePoint timePointTo = new MillisecondsTimePoint(to.get(competitorDAO));
|
||||
GPSFix[] gpsFixDouglas = douglas.approximate(maxDistance, timePointFrom, timePointTo);
|
||||
List<GPSFixMoving> gpsFixApproximation = trackedRace.approximate(competitor, maxDistance, timePointFrom, timePointTo);
|
||||
List<GPSFixDAO> gpsFixDouglasList = new ArrayList<GPSFixDAO>();
|
||||
for (int i = 0; i < gpsFixDouglas.length; i++) {
|
||||
GPSFix fix = gpsFixDouglas[i];
|
||||
for (int i = 0; i < gpsFixApproximation.size(); i++) {
|
||||
GPSFix fix = gpsFixApproximation.get(i);
|
||||
SpeedWithBearing speedWithBearing;
|
||||
if (i<gpsFixDouglas.length-1) {
|
||||
GPSFix next = gpsFixDouglas[i+1];
|
||||
if (i<gpsFixApproximation.size()-1) {
|
||||
GPSFix next = gpsFixApproximation.get(i+1);
|
||||
Bearing bearing = fix.getPosition().getBearingGreatCircle(next.getPosition());
|
||||
Speed speed = fix.getPosition().getDistance(next.getPosition()).inTime(
|
||||
next.getTimePoint().asMillis()-fix.getTimePoint().asMillis());
|
||||
|
||||
Reference in new issue
Block a user