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 horizontal 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 if (point.hasHSpeed()) {
32 speedValue = point.getHSpeed().getValue(Config.getUnitSet().getSpeedUnit());
36 // otherwise, see if we can calculate it from the timestamps
37 if (!pointHasSpeed && point.hasTimestamp() && !point.isWaypoint())
39 double totalRadians = 0.0;
40 int index = inIndex-1;
43 Timestamp earlyStamp = point.getTimestamp();
46 // Count backwards until timestamp earlier than now; total distances back to this point
47 if (!point.getSegmentStart())
51 p = inTrack.getPoint(index);
52 boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isAfter(point.getTimestamp());
53 boolean pValid = timeOk && !p.isWaypoint();
55 totalRadians += DataPoint.calculateRadiansBetween(p, q);
56 earlyStamp = p.getTimestamp();
58 stop = (p == null) || (p.hasTimestamp() && !p.getTimestamp().isEqual(point.getTimestamp())
59 || p.getSegmentStart());
61 if (p != null && !p.isWaypoint()) {
67 // Count forwards until timestamp later than now; total distances forward to this point
68 Timestamp lateStamp = point.getTimestamp();
73 p = inTrack.getPoint(index);
74 boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isBefore(point.getTimestamp());
75 boolean pValid = timeOk && !p.isWaypoint() && !p.getSegmentStart();
77 totalRadians += DataPoint.calculateRadiansBetween(p, q);
78 lateStamp = p.getTimestamp();
80 stop = (p == null) || (p.hasTimestamp() && !p.getTimestamp().isEqual(point.getTimestamp())
81 || p.getSegmentStart());
83 if (p != null && !p.isWaypoint()) {
89 // See if we've managed to get a time range of at least a second
90 long milliseconds = lateStamp.getMillisecondsSince(earlyStamp);
91 if (milliseconds >= 1000L)
93 double dist = Distance.convertRadiansToDistance(totalRadians);
94 // Store the value and maintain max and min values
95 speedValue = dist / milliseconds * 1000.0 * 60.0 * 60.0; // convert from per millisec to per hour
99 // Did we get a value?
102 inValue.setValue(speedValue);
104 // otherwise, just leave value as invalid
109 * Calculate the vertical speed value of the track at the specified index
110 * @param inTrack track object
111 * @param inIndex index of point to calculate speed for
112 * @param inValue object in which to place the result of calculation
114 public static void calculateVerticalSpeed(Track inTrack, int inIndex, SpeedValue inValue)
116 if (inTrack == null || inIndex < 0 || inValue == null) {
117 System.err.println("Cannot calculate vert speed for index " + inIndex);
120 inValue.setInvalid();
122 DataPoint point = inTrack.getPoint(inIndex);
123 boolean pointHasSpeed = false;
124 double speedValue = 0.0;
126 // First, see if point has a speed value already
127 if (point != null && point.hasVSpeed())
129 speedValue = point.getVSpeed().getValue(Config.getUnitSet().getVerticalSpeedUnit());
130 pointHasSpeed = true;
132 // otherwise, see if we can calculate it from the heights and timestamps
134 && point != null && point.hasTimestamp() && point.hasAltitude() && !point.isWaypoint())
136 int index = inIndex-1;
138 Timestamp earlyStamp = point.getTimestamp();
139 Altitude firstAlt = point.getAltitude();
140 boolean stop = false;
142 // Count backwards until timestamp earlier than now
143 if (!point.getSegmentStart())
147 p = inTrack.getPoint(index);
148 boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isAfter(point.getTimestamp());
149 boolean pValid = timeOk && !p.isWaypoint();
151 earlyStamp = p.getTimestamp();
152 if (p.hasAltitude()) firstAlt = p.getAltitude();
154 stop = (p == null) || (p.hasTimestamp() && !p.getTimestamp().isEqual(point.getTimestamp())
155 || p.getSegmentStart());
161 // Count forwards until timestamp later than now
162 Timestamp lateStamp = point.getTimestamp();
163 Altitude lastAlt = point.getAltitude();
167 p = inTrack.getPoint(index);
168 boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isBefore(point.getTimestamp());
169 boolean pValid = timeOk && !p.isWaypoint() && !p.getSegmentStart();
171 lateStamp = p.getTimestamp();
172 if (p.hasAltitude()) lastAlt = p.getAltitude();
174 stop = (p == null) || (p.hasTimestamp() && !p.getTimestamp().isEqual(point.getTimestamp())
175 || p.getSegmentStart());
180 // See if we've managed to get a non-zero time range
181 long milliseconds = lateStamp.getMillisecondsSince(earlyStamp);
182 if (milliseconds >= 1000L)
184 double altDiff = (lastAlt.getMetricValue() - firstAlt.getMetricValue())
185 * Config.getUnitSet().getVerticalSpeedUnit().getMultFactorFromStd();
186 speedValue = altDiff / milliseconds * 1000.0; // units are feet/sec or metres/sec
187 pointHasSpeed = true;
190 // Check whether we got a value from either method
193 inValue.setValue(speedValue);