1 package tim.prune.data;
3 import tim.prune.DataSubscriber;
4 import tim.prune.UpdateMessageBroker;
7 * Class to represent a selected portion of a Track
10 public class Selection
12 private Track _track = null;
13 private int _currentPoint = -1;
14 private boolean _valid = false;
15 private int _startIndex = -1, _endIndex = -1;
16 private int _currentPhotoIndex = -1;
17 private IntegerRange _altitudeRange = null;
18 private int _climb = -1, _descent = -1;
19 private int _altitudeFormat = Altitude.FORMAT_NONE;
20 private long _seconds = 0L;
21 private double _angDistance = -1.0; //, _averageSpeed = -1.0;
26 * @param inTrack track object
28 public Selection(Track inTrack)
35 * Reset selection to be recalculated
44 * Select the point at the given index
45 * @param inIndex index number of selected point
47 public void selectPoint(int inIndex)
51 _currentPoint = inIndex;
57 * Select the specified point and range in one go
58 * @param inPointIndex point selection
59 * @param inStart range start
60 * @param inEnd range end
62 public void select(int inPointIndex, int inStart, int inEnd)
64 _currentPoint = inPointIndex;
65 _startIndex = inStart;
73 * Select the previous point
75 public void selectPreviousPoint()
77 if (_currentPoint > 0)
78 selectPoint(_currentPoint - 1);
82 * Select the next point
84 public void selectNextPoint()
86 selectPoint(_currentPoint + 1);
90 * @return the current point index
92 public int getCurrentPointIndex()
99 * @return true if range is selected
101 public boolean hasRangeSelected()
103 return _startIndex >= 0 && _endIndex > _startIndex;
108 * Recalculate all selection details
110 private void recalculate()
112 _altitudeFormat = Altitude.FORMAT_NONE;
113 if (_track.getNumPoints() > 0 && hasRangeSelected())
115 _altitudeRange = new IntegerRange();
118 Altitude altitude = null;
119 Timestamp time = null, startTime = null, endTime = null;
120 DataPoint lastPoint = null, currPoint = null;
123 int lastAltValue = 0;
124 boolean foundAlt = false;
125 for (int i=_startIndex; i<=_endIndex; i++)
127 currPoint = _track.getPoint(i);
128 altitude = currPoint.getAltitude();
129 // Ignore waypoints in altitude calculations
130 if (!currPoint.isWaypoint() && altitude.isValid())
132 altValue = altitude.getValue(_altitudeFormat);
133 if (_altitudeFormat == Altitude.FORMAT_NONE)
134 _altitudeFormat = altitude.getFormat();
135 _altitudeRange.addValue(altValue);
138 if (altValue > lastAltValue)
139 _climb += (altValue - lastAltValue);
141 _descent += (lastAltValue - altValue);
143 lastAltValue = altValue;
146 // Store the first and last timestamp in the range
147 time = currPoint.getTimestamp();
150 if (startTime == null) startTime = time;
153 // Calculate distances, again ignoring waypoints
154 if (!currPoint.isWaypoint())
156 if (lastPoint != null)
158 _angDistance += DataPoint.calculateRadiansBetween(lastPoint, currPoint);
160 lastPoint = currPoint;
165 _seconds = endTime.getSecondsSince(startTime);
177 * @return start index
179 public int getStart()
181 if (!_valid) recalculate();
191 if (!_valid) recalculate();
197 * @return the altitude format, ie feet or metres
199 public int getAltitudeFormat()
201 return _altitudeFormat;
205 * @return altitude range
207 public IntegerRange getAltitudeRange()
209 if (!_valid) recalculate();
210 return _altitudeRange;
217 public int getClimb()
219 if (!_valid) recalculate();
226 public int getDescent()
228 if (!_valid) recalculate();
234 * @return number of seconds spanned by selection
236 public long getNumSeconds()
238 if (!_valid) recalculate();
244 * @param inUnits distance units to use, from class Distance
245 * @return distance of Selection in specified units
247 public double getDistance(int inUnits)
249 return Distance.convertRadiansToDistance(_angDistance, inUnits);
254 * Clear selected point and range
256 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 UpdateMessageBroker.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 UpdateMessageBroker.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)
383 public void deselectPhoto()
385 _currentPhotoIndex = -1;
391 * Select the specified photo and point
392 * @param inPhotoIndex index of selected photo in PhotoList
393 * @param inPointIndex index of selected point
395 public void selectPhotoAndPoint(int inPhotoIndex, int inPointIndex)
397 _currentPhotoIndex = inPhotoIndex;
398 if (inPointIndex > -1)
400 // select associated point, if any
401 selectPoint(inPointIndex);
405 // Check if not already done
412 * @return currently selected photo index
414 public int getCurrentPhotoIndex()
416 return _currentPhotoIndex;
420 * Check that the selection still makes sense
421 * and fire update message to listeners
427 if (_track.getNumPoints() > 0)
429 int maxIndex = _track.getNumPoints() - 1;
430 if (_currentPoint > maxIndex)
432 _currentPoint = maxIndex;
434 if (_endIndex > maxIndex)
436 _endIndex = maxIndex;
438 if (_startIndex > maxIndex)
440 _startIndex = maxIndex;
445 // track is empty, clear selections
446 _currentPoint = _startIndex = _endIndex = -1;
449 UpdateMessageBroker.informSubscribers(DataSubscriber.SELECTION_CHANGED);