1 package tim.prune.data;
3 import tim.prune.UpdateMessageBroker;
6 * Class to represent a selected portion of a Track
11 private Track _track = null;
12 private UpdateMessageBroker _broker = null;
13 private int _currentPoint = -1;
14 private boolean _valid = false;
15 private int _startIndex = -1, _endIndex = -1;
16 private IntegerRange _altitudeRange = null;
17 private int _climb = -1, _descent = -1;
18 private int _altitudeFormat = Altitude.FORMAT_NONE;
19 private long _seconds = 0L;
20 private double _angDistance = -1.0; //, _averageSpeed = -1.0;
25 * @param inTrack track object
26 * @param inBroker broker object
28 public Selection(Track inTrack, UpdateMessageBroker inBroker)
36 * Reset selection to be recalculated
45 * Select the point at the given index
46 * @param inIndex index number of selected point
48 public void selectPoint(int inIndex)
52 _currentPoint = inIndex;
58 * Select the specified point and range in one go
59 * @param inPointIndex point selection
60 * @param inStart range start
61 * @param inEnd range end
63 public void select(int inPointIndex, int inStart, int inEnd)
65 _currentPoint = inPointIndex;
66 _startIndex = inStart;
74 * Select the previous point
76 public void selectPreviousPoint()
78 if (_currentPoint > 0)
79 selectPoint(_currentPoint - 1);
83 * Select the next point
85 public void selectNextPoint()
87 selectPoint(_currentPoint + 1);
91 * @return the current point index
93 public int getCurrentPointIndex()
100 * @return true if range is selected
102 public boolean hasRangeSelected()
104 return _startIndex >= 0 && _endIndex > _startIndex;
109 * Recalculate all selection details
111 private void recalculate()
113 _altitudeFormat = Altitude.FORMAT_NONE;
114 if (_track.getNumPoints() > 0 && hasRangeSelected())
116 _altitudeRange = new IntegerRange();
119 Altitude altitude = null;
120 Timestamp time = null, startTime = null, endTime = null;
121 DataPoint lastPoint = null, currPoint = null;
124 int lastAltValue = 0;
125 boolean foundAlt = false;
126 for (int i=_startIndex; i<=_endIndex; i++)
128 currPoint = _track.getPoint(i);
129 altitude = currPoint.getAltitude();
130 // Ignore waypoints in altitude calculations
131 if (!currPoint.isWaypoint() && altitude.isValid())
133 altValue = altitude.getValue(_altitudeFormat);
134 if (_altitudeFormat == Altitude.FORMAT_NONE)
135 _altitudeFormat = altitude.getFormat();
136 _altitudeRange.addValue(altValue);
139 if (altValue > lastAltValue)
140 _climb += (altValue - lastAltValue);
142 _descent += (lastAltValue - altValue);
144 lastAltValue = altValue;
147 // Store the first and last timestamp in the range
148 time = currPoint.getTimestamp();
151 if (startTime == null) startTime = time;
154 // Calculate distances, again ignoring waypoints
155 if (!currPoint.isWaypoint())
157 if (lastPoint != null)
159 _angDistance += DataPoint.calculateRadiansBetween(lastPoint, currPoint);
161 lastPoint = currPoint;
166 _seconds = endTime.getSecondsSince(startTime);
178 * @return start index
180 public int getStart()
182 if (!_valid) recalculate();
192 if (!_valid) recalculate();
198 * @return the altitude format, ie feet or metres
200 public int getAltitudeFormat()
202 return _altitudeFormat;
206 * @return altitude range
208 public IntegerRange getAltitudeRange()
210 if (!_valid) recalculate();
211 return _altitudeRange;
218 public int getClimb()
220 if (!_valid) recalculate();
227 public int getDescent()
229 if (!_valid) recalculate();
235 * @return number of seconds spanned by selection
237 public long getNumSeconds()
239 if (!_valid) recalculate();
245 * @param inFormat distance units to use, from class Distance
246 * @return distance of Selection in specified units
248 public double getDistance(int inUnits)
250 return Distance.convertRadians(_angDistance, inUnits);
255 * Clear selected point and range
257 public void clearAll()
267 public void deselectRange()
269 _startIndex = _endIndex = -1;
276 * Select the range from the current point
278 public void selectRangeStart()
280 selectRangeStart(_currentPoint);
285 * Set the index for the start of the range selection
286 * @param inStartIndex start index
288 public void selectRangeStart(int inStartIndex)
290 if (inStartIndex < 0)
292 _startIndex = _endIndex = -1;
296 _startIndex = inStartIndex;
297 // Move end of selection to max if necessary
298 if (_endIndex <= _startIndex)
300 _endIndex = _track.getNumPoints() - 1;
304 _broker.informSubscribers();
309 * Select the range up to the current point
311 public void selectRangeEnd()
313 selectRangeEnd(_currentPoint);
318 * Set the index for the end of the range selection
319 * @param inEndIndex end index
321 public void selectRangeEnd(int inEndIndex)
325 _startIndex = _endIndex = -1;
329 _endIndex = inEndIndex;
330 // Move start of selection to min if necessary
331 if (_startIndex > _endIndex || _startIndex < 0)
337 _broker.informSubscribers();
342 * Modify the selection given that the selected range has been deleted
344 public void modifyRangeDeleted()
346 // Modify current point, if any
347 if (_currentPoint > _endIndex)
349 _currentPoint -= (_endIndex - _startIndex);
351 else if (_currentPoint > _startIndex)
353 _currentPoint = _startIndex;
355 // Clear selected range
356 _startIndex = _endIndex = -1;
357 // Check for consistency and fire update
363 * Modify the selection when a point is deleted
365 public void modifyPointDeleted()
367 // current point index doesn't change, just gets checked
368 // range needs to get altered if deleted point is inside or before
369 if (hasRangeSelected() && _currentPoint <= _endIndex)
372 if (_currentPoint < _startIndex)
381 * Check that the selection still makes sense
382 * and fire update message to listeners
388 if (_track.getNumPoints() > 0)
390 int maxIndex = _track.getNumPoints() - 1;
391 if (_currentPoint > maxIndex)
393 _currentPoint = maxIndex;
395 if (_endIndex > maxIndex)
397 _endIndex = maxIndex;
399 if (_startIndex > maxIndex)
401 _startIndex = maxIndex;
406 // track is empty, clear selections
407 _currentPoint = _startIndex = _endIndex = -1;
410 _broker.informSubscribers();