View Javadoc
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  }