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 }