1 package tim.prune.data;
3 import tim.prune.config.Config;
6 * Abstract class to hold static calculation functions
7 * for speed (and vertical speed)
9 public abstract class SpeedCalculator
12 * Calculate the speed value of the track at the specified index
13 * @param inTrack track object
14 * @param inIndex index of point to calculate speed for
15 * @param inValue object in which to place result of calculation
17 public static void calculateSpeed(Track inTrack, int inIndex, SpeedValue inValue)
19 if (inTrack == null || inIndex < 0 || inValue == null) {
20 System.err.println("Cannot calculate speed for index " + inIndex);
25 DataPoint point = inTrack.getPoint(inIndex);
26 if (point == null) {return;}
27 boolean pointHasSpeed = false;
28 double speedValue = 0.0;
30 // First, see if point has a speed value already
31 // FIXME: How do we know what units this speed is in? m/s or mph or km/h or what?
32 String speedStr = point.getFieldValue(Field.SPEED);
34 speedValue = Double.parseDouble(speedStr);
37 catch (Exception e) {} // ignore, leave pointHasSpeed false
39 // otherwise, see if we can calculate it from the timestamps
40 if (!pointHasSpeed && point.hasTimestamp() && !point.isWaypoint())
42 double totalRadians = 0.0;
43 int index = inIndex-1;
46 Timestamp earlyStamp = point.getTimestamp();
49 // Count backwards until timestamp earlier than now; total distances back to this point
50 if (!point.getSegmentStart())
54 p = inTrack.getPoint(index);
55 boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isAfter(point.getTimestamp());
56 boolean pValid = timeOk && !p.isWaypoint();
58 totalRadians += DataPoint.calculateRadiansBetween(p, q);
59 earlyStamp = p.getTimestamp();
61 stop = (p == null) || (p.hasTimestamp() && !p.getTimestamp().isEqual(point.getTimestamp())
62 || p.getSegmentStart());
64 if (p != null && !p.isWaypoint()) {
70 // Count forwards until timestamp later than now; total distances forward to this point
71 Timestamp lateStamp = point.getTimestamp();
76 p = inTrack.getPoint(index);
77 boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isBefore(point.getTimestamp());
78 boolean pValid = timeOk && !p.isWaypoint() && !p.getSegmentStart();
80 totalRadians += DataPoint.calculateRadiansBetween(p, q);
81 lateStamp = p.getTimestamp();
83 stop = (p == null) || (p.hasTimestamp() && !p.getTimestamp().isEqual(point.getTimestamp())
84 || p.getSegmentStart());
86 if (p != null && !p.isWaypoint()) {
92 // See if we've managed to get a time range of at least a second
93 long milliseconds = lateStamp.getMillisecondsSince(earlyStamp);
94 if (milliseconds >= 1000L)
96 double dist = Distance.convertRadiansToDistance(totalRadians);
97 // Store the value and maintain max and min values
98 speedValue = dist / milliseconds * 1000.0 * 60.0 * 60.0; // convert from per millisec to per hour
102 // Did we get a value?
105 inValue.setValue(speedValue);
107 // otherwise, just leave value as invalid
112 * Calculate the vertical speed value of the track at the specified index
113 * @param inTrack track object
114 * @param inIndex index of point to calculate speed for
115 * @param inValue object in which to place the result of calculation
117 public static void calculateVerticalSpeed(Track inTrack, int inIndex, SpeedValue inValue)
119 if (inTrack == null || inIndex < 0 || inValue == null) {
120 System.err.println("Cannot calculate vert speed for index " + inIndex);
123 inValue.setInvalid();
125 DataPoint point = inTrack.getPoint(inIndex);
126 boolean pointHasSpeed = false;
127 double speedValue = 0.0;
129 // First, see if point has a speed value already
132 // FIXME: Can we assume m/s or ft/s?
133 String speedStr = point.getFieldValue(Field.VERTICAL_SPEED);
135 speedValue = Double.parseDouble(speedStr);
136 pointHasSpeed = true;
138 catch (Exception e) {} // ignore, leave pointHasSpeed false
140 // otherwise, see if we can calculate it from the heights and timestamps
142 && point != null && point.hasTimestamp() && point.hasAltitude() && !point.isWaypoint())
144 int index = inIndex-1;
146 Timestamp earlyStamp = point.getTimestamp();
147 Altitude firstAlt = point.getAltitude();
148 boolean stop = false;
150 // Count backwards until timestamp earlier than now
151 if (!point.getSegmentStart())
155 p = inTrack.getPoint(index);
156 boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isAfter(point.getTimestamp());
157 boolean pValid = timeOk && !p.isWaypoint();
159 earlyStamp = p.getTimestamp();
160 if (p.hasAltitude()) firstAlt = p.getAltitude();
162 stop = (p == null) || (p.hasTimestamp() && !p.getTimestamp().isEqual(point.getTimestamp())
163 || p.getSegmentStart());
169 // Count forwards until timestamp later than now
170 Timestamp lateStamp = point.getTimestamp();
171 Altitude lastAlt = point.getAltitude();
175 p = inTrack.getPoint(index);
176 boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isBefore(point.getTimestamp());
177 boolean pValid = timeOk && !p.isWaypoint() && !p.getSegmentStart();
179 lateStamp = p.getTimestamp();
180 if (p.hasAltitude()) lastAlt = p.getAltitude();
182 stop = (p == null) || (p.hasTimestamp() && !p.getTimestamp().isEqual(point.getTimestamp())
183 || p.getSegmentStart());
188 // See if we've managed to get a non-zero time range
189 long milliseconds = lateStamp.getMillisecondsSince(earlyStamp);
190 if (milliseconds >= 1000L)
192 double altDiff = (lastAlt.getMetricValue() - firstAlt.getMetricValue())
193 * Config.getUnitSet().getVerticalSpeedUnit().getMultFactorFromStd();
194 speedValue = altDiff / milliseconds * 1000.0; // units are feet/sec or metres/sec
195 pointHasSpeed = true;
198 // Check whether we got a value from either method
201 inValue.setValue(speedValue);