+++ /dev/null
-package tim.prune.data;
-
-import tim.prune.config.Config;
-
-/**
- * Abstract class to hold static calculation functions
- * for speed (and vertical speed)
- */
-public abstract class SpeedCalculator
-{
- /**
- * Calculate the horizontal speed value of the track at the specified index
- * @param inTrack track object
- * @param inIndex index of point to calculate speed for
- * @param inValue object in which to place result of calculation
- */
- public static void calculateSpeed(Track inTrack, int inIndex, SpeedValue inValue)
- {
- if (inValue != null)
- {
- inValue.setInvalid();
- }
- if (inTrack == null || inIndex < 0 || inValue == null)
- {
- System.err.println("Cannot calculate speed for index " + inIndex);
- return;
- }
-
- DataPoint point = inTrack.getPoint(inIndex);
- if (point == null) {return;}
- boolean pointHasSpeed = false;
- double speedValue = 0.0;
-
- // First, see if point has a speed value already
- if (point.hasHSpeed()) {
- speedValue = point.getHSpeed().getValue(Config.getUnitSet().getSpeedUnit());
- pointHasSpeed = true;
- }
-
- // otherwise, see if we can calculate it from the timestamps
- if (!pointHasSpeed && point.hasTimestamp() && !point.isWaypoint())
- {
- double totalRadians = 0.0;
- int index = inIndex-1;
- DataPoint p = null;
- DataPoint q = point;
- Timestamp earlyStamp = point.getTimestamp();
- boolean stop = false;
-
- // Count backwards until timestamp earlier than now; total distances back to this point
- if (!point.getSegmentStart())
- {
- do
- {
- p = inTrack.getPoint(index);
- boolean timeOk = p != null && p.hasTimestamp() && p.getTimestamp().isBefore(point.getTimestamp());
- boolean pValid = timeOk && !p.isWaypoint();
- if (pValid) {
- totalRadians += DataPoint.calculateRadiansBetween(p, q);
- earlyStamp = p.getTimestamp();
- }
-
- stop = (p == null) || p.getSegmentStart() || hasSufficientTimeDifference(p, point);
- index--;
- if (p != null && !p.isWaypoint()) {
- q = p;
- }
- }
- while (!stop);
- }
- // Count forwards until timestamp later than now; total distances forward to this point
- Timestamp lateStamp = point.getTimestamp();
- q = point;
- index = inIndex+1;
- do
- {
- p = inTrack.getPoint(index);
- boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isBefore(point.getTimestamp());
- boolean pValid = timeOk && !p.isWaypoint() && !p.getSegmentStart();
- if (pValid) {
- totalRadians += DataPoint.calculateRadiansBetween(p, q);
- lateStamp = p.getTimestamp();
- }
-
- stop = (p == null) || p.getSegmentStart() || hasSufficientTimeDifference(point, p);
- index++;
- if (p != null && !p.isWaypoint()) {
- q = p;
- }
- }
- while (!stop);
-
- // See if we've managed to get a time range of at least a second
- long milliseconds = lateStamp.getMillisecondsSince(earlyStamp);
- if (milliseconds >= 1000L)
- {
- double dist = Distance.convertRadiansToDistance(totalRadians);
- // Store the value and maintain max and min values
- speedValue = dist / milliseconds * 1000.0 * 60.0 * 60.0; // convert from per millisec to per hour
- pointHasSpeed = true;
- }
- }
- // Did we get a value?
- if (pointHasSpeed)
- {
- inValue.setValue(speedValue);
- }
- // otherwise, just leave value as invalid
- }
-
-
- /**
- * Calculate the vertical speed value of the track at the specified index
- * @param inTrack track object
- * @param inIndex index of point to calculate speed for
- * @param inValue object in which to place the result of calculation
- */
- public static void calculateVerticalSpeed(Track inTrack, int inIndex, SpeedValue inValue)
- {
- if (inTrack == null || inIndex < 0 || inValue == null) {
- System.err.println("Cannot calculate vert speed for index " + inIndex);
- return;
- }
- inValue.setInvalid();
-
- DataPoint point = inTrack.getPoint(inIndex);
- boolean pointHasSpeed = false;
- double speedValue = 0.0;
-
- // First, see if point has a speed value already
- if (point != null && point.hasVSpeed())
- {
- speedValue = point.getVSpeed().getValue(Config.getUnitSet().getVerticalSpeedUnit());
- pointHasSpeed = true;
- }
- // otherwise, see if we can calculate it from the heights and timestamps
- if (!pointHasSpeed
- && point != null && point.hasTimestamp() && point.hasAltitude() && !point.isWaypoint())
- {
- int index = inIndex-1;
- DataPoint p = null;
- Timestamp earlyStamp = point.getTimestamp();
- Altitude firstAlt = point.getAltitude();
- boolean stop = false;
-
- // Count backwards until timestamp earlier than now
- if (!point.getSegmentStart())
- {
- do
- {
- p = inTrack.getPoint(index);
- boolean timeOk = p != null && p.hasTimestamp() && p.getTimestamp().isBefore(point.getTimestamp());
- boolean pValid = timeOk && !p.isWaypoint();
- if (pValid) {
- earlyStamp = p.getTimestamp();
- if (p.hasAltitude()) firstAlt = p.getAltitude();
- }
-
- stop = (p == null) || p.getSegmentStart() || hasSufficientTimeDifference(p, point);
- index--;
- }
- while (!stop);
- }
-
- // Count forwards until timestamp later than now
- Timestamp lateStamp = point.getTimestamp();
- Altitude lastAlt = point.getAltitude();
- index = inIndex+1;
- do
- {
- p = inTrack.getPoint(index);
- boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isBefore(point.getTimestamp());
- boolean pValid = timeOk && !p.isWaypoint() && !p.getSegmentStart();
- if (pValid) {
- lateStamp = p.getTimestamp();
- if (p.hasAltitude()) lastAlt = p.getAltitude();
- }
-
- stop = (p == null) || p.getSegmentStart() || hasSufficientTimeDifference(point, p);
- index++;
- }
- while (!stop);
-
- // See if we've managed to get a non-zero time range
- long milliseconds = lateStamp.getMillisecondsSince(earlyStamp);
- if (milliseconds >= 1000L)
- {
- double altDiff = (lastAlt.getMetricValue() - firstAlt.getMetricValue())
- * Config.getUnitSet().getVerticalSpeedUnit().getMultFactorFromStd();
- speedValue = altDiff / milliseconds * 1000.0; // units are feet/sec or metres/sec
- pointHasSpeed = true;
- }
- }
- // Check whether we got a value from either method
- if (pointHasSpeed)
- {
- inValue.setValue(speedValue);
- }
- }
-
- /**
- * Check whether the time difference between P1 and P2 is sufficiently large
- * @param inP1 earlier point
- * @param inP2 later point
- * @return true if we can stop looking now, found a point early/late enough
- */
- private static boolean hasSufficientTimeDifference(DataPoint inP1, DataPoint inP2)
- {
- if (inP1 == null || inP2 == null)
- return true; // we have to give up now
- if (!inP1.hasTimestamp() || !inP2.hasTimestamp())
- return false; // keep looking
- final long MIN_TIME_DIFFERENCE_MS = 1000L;
- return inP2.getTimestamp().getMillisecondsSince(inP1.getTimestamp()) >= MIN_TIME_DIFFERENCE_MS;
- }
-}