1 package au.gov.amsa.geo.distance;
2
3 import java.util.concurrent.TimeUnit;
4
5 import com.google.common.base.Optional;
6
7 import au.gov.amsa.geo.model.SegmentOptions;
8 import au.gov.amsa.risky.format.Fix;
9 import au.gov.amsa.util.navigation.Position;
10
11 public class EffectiveSpeedChecker {
12
13 public static boolean effectiveSpeedOk(Fix a, Fix b, SegmentOptions o) {
14 return effectiveSpeedOk(a.time(), a.lat(), a.lon(), b.time(), b.lat(), b.lon(), o);
15 }
16
17 public static boolean effectiveSpeedOk(long aTime, double aLat, double aLon, long bTime,
18 double bLat, double bLon, SegmentOptions o) {
19 Optional<Double> speedKnots = effectiveSpeedKnots(aTime, aLat, aLon, bTime, bLat, bLon, o);
20 return !speedKnots.isPresent() || speedKnots.get() <= o.maxSpeedKnots();
21 }
22
23 public static Optional<Double> effectiveSpeedKnots(Fix a, Fix b, SegmentOptions o) {
24 return effectiveSpeedKnots(a.time(), a.lat(), a.lon(), b.time(), b.lat(), b.lon(), o);
25 }
26
27 public static Optional<Double> effectiveSpeedKnots(long aTime, double aLat, double aLon,
28 long bTime, double bLat, double bLon, SegmentOptions o) {
29 long timeDiffMs = Math.abs(aTime - bTime);
30
31 if (o.acceptAnyFixAfterHours() != null
32 && timeDiffMs >= TimeUnit.HOURS.toMillis(o.acceptAnyFixAfterHours())) {
33 return Optional.absent();
34 } else {
35 double distanceBetweenFixesNm = Position.create(aLat, aLon)
36 .getDistanceToKm(Position.create(bLat, bLon)) / 1.852;
37 if (distanceBetweenFixesNm > o.speedCheckDistanceThresholdNm()) {
38 double timeDiffHoursFloored = (double) Math.max(timeDiffMs,
39 o.speedCheckMinTimeDiffMs()) / TimeUnit.HOURS.toMillis(1);
40 double effectiveSpeedKnots = distanceBetweenFixesNm / timeDiffHoursFloored;
41 return Optional.of(effectiveSpeedKnots);
42 } else
43 return Optional.absent();
44 }
45 }
46 }