]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/data/Selection.java
Version 1, September 2006
[GpsPrune.git] / tim / prune / data / Selection.java
1 package tim.prune.data;
2
3 import tim.prune.UpdateMessageBroker;
4
5 /**
6  * Class to represent a selected portion of a Track
7  * and its properties
8  */
9 public class Selection
10 {
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;
21
22
23         /**
24          * Constructor
25          * @param inTrack track object
26          * @param inBroker broker object
27          */
28         public Selection(Track inTrack, UpdateMessageBroker inBroker)
29         {
30                 _track = inTrack;
31                 _broker = inBroker;
32         }
33
34
35         /**
36          * Reset selection to be recalculated
37          */
38         private void reset()
39         {
40                 _valid = false;
41         }
42
43
44         /**
45          * Select the point at the given index
46          * @param inIndex index number of selected point
47          */
48         public void selectPoint(int inIndex)
49         {
50                 if (inIndex >= -1)
51                 {
52                         _currentPoint = inIndex;
53                         check();
54                 }
55         }
56
57         /**
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
62          */
63         public void select(int inPointIndex, int inStart, int inEnd)
64         {
65                 _currentPoint = inPointIndex;
66                 _startIndex = inStart;
67                 _endIndex = inEnd;
68                 reset();
69                 check();
70         }
71
72
73         /**
74          * Select the previous point
75          */
76         public void selectPreviousPoint()
77         {
78                 if (_currentPoint > 0)
79                         selectPoint(_currentPoint - 1);
80         }
81
82         /**
83          * Select the next point
84          */
85         public void selectNextPoint()
86         {
87                 selectPoint(_currentPoint + 1);
88         }
89
90         /**
91          * @return the current point index
92          */
93         public int getCurrentPointIndex()
94         {
95                 return _currentPoint;
96         }
97
98
99         /**
100          * @return true if range is selected
101          */
102         public boolean hasRangeSelected()
103         {
104                 return _startIndex >= 0 && _endIndex > _startIndex;
105         }
106
107
108         /**
109          * Recalculate all selection details
110          */
111         private void recalculate()
112         {
113                 _altitudeFormat = Altitude.FORMAT_NONE;
114                 if (_track.getNumPoints() > 0 && hasRangeSelected())
115                 {
116                         _altitudeRange = new IntegerRange();
117                         _climb = 0;
118                         _descent = 0;
119                         Altitude altitude = null;
120                         Timestamp time = null, startTime = null, endTime = null;
121                         DataPoint lastPoint = null, currPoint = null;
122                         _angDistance = 0.0;
123                         int altValue = 0;
124                         int lastAltValue = 0;
125                         boolean foundAlt = false;
126                         for (int i=_startIndex; i<=_endIndex; i++)
127                         {
128                                 currPoint = _track.getPoint(i);
129                                 altitude = currPoint.getAltitude();
130                                 // Ignore waypoints in altitude calculations
131                                 if (!currPoint.isWaypoint() && altitude.isValid())
132                                 {
133                                         altValue = altitude.getValue(_altitudeFormat);
134                                         if (_altitudeFormat == Altitude.FORMAT_NONE)
135                                                 _altitudeFormat = altitude.getFormat();
136                                         _altitudeRange.addValue(altValue);
137                                         if (foundAlt)
138                                         {
139                                                 if (altValue > lastAltValue)
140                                                         _climb += (altValue - lastAltValue);
141                                                 else
142                                                         _descent += (lastAltValue - altValue);
143                                         }
144                                         lastAltValue = altValue;
145                                         foundAlt = true;
146                                 }
147                                 // Store the first and last timestamp in the range
148                                 time = currPoint.getTimestamp();
149                                 if (time.isValid())
150                                 {
151                                         if (startTime == null) startTime = time;
152                                         endTime = time;
153                                 }
154                                 // Calculate distances, again ignoring waypoints
155                                 if (!currPoint.isWaypoint())
156                                 {
157                                         if (lastPoint != null)
158                                         {
159                                                 _angDistance += DataPoint.calculateRadiansBetween(lastPoint, currPoint);
160                                         }
161                                         lastPoint = currPoint;
162                                 }
163                         }
164                         if (endTime != null)
165                         {
166                                 _seconds = endTime.getSecondsSince(startTime);
167                         }
168                         else
169                         {
170                                 _seconds = 0L;
171                         }
172                 }
173                 _valid = true;
174         }
175
176
177         /**
178          * @return start index
179          */
180         public int getStart()
181         {
182                 if (!_valid) recalculate();
183                 return _startIndex;
184         }
185
186
187         /**
188          * @return end index
189          */
190         public int getEnd()
191         {
192                 if (!_valid) recalculate();
193                 return _endIndex;
194         }
195
196
197         /**
198          * @return the altitude format, ie feet or metres
199          */
200         public int getAltitudeFormat()
201         {
202                 return _altitudeFormat;
203         }
204
205         /**
206          * @return altitude range
207          */
208         public IntegerRange getAltitudeRange()
209         {
210                 if (!_valid) recalculate();
211                 return _altitudeRange;
212         }
213
214
215         /**
216          * @return climb
217          */
218         public int getClimb()
219         {
220                 if (!_valid) recalculate();
221                 return _climb;
222         }
223
224         /**
225          * @return descent
226          */
227         public int getDescent()
228         {
229                 if (!_valid) recalculate();
230                 return _descent;
231         }
232
233
234         /**
235          * @return number of seconds spanned by selection
236          */
237         public long getNumSeconds()
238         {
239                 if (!_valid) recalculate();
240                 return _seconds;
241         }
242
243
244         /**
245          * @param inFormat distance units to use, from class Distance
246          * @return distance of Selection in specified units
247          */
248         public double getDistance(int inUnits)
249         {
250                 return Distance.convertRadians(_angDistance, inUnits);
251         }
252
253
254         /**
255          * Clear selected point and range
256          */
257         public void clearAll()
258         {
259                 _currentPoint = -1;
260                 deselectRange();
261         }
262
263
264         /**
265          * Deselect range
266          */
267         public void deselectRange()
268         {
269                 _startIndex = _endIndex = -1;
270                 reset();
271                 check();
272         }
273
274
275         /**
276          * Select the range from the current point
277          */
278         public void selectRangeStart()
279         {
280                 selectRangeStart(_currentPoint);
281         }
282
283
284         /**
285          * Set the index for the start of the range selection
286          * @param inStartIndex start index
287          */
288         public void selectRangeStart(int inStartIndex)
289         {
290                 if (inStartIndex < 0)
291                 {
292                         _startIndex = _endIndex = -1;
293                 }
294                 else
295                 {
296                         _startIndex = inStartIndex;
297                         // Move end of selection to max if necessary
298                         if (_endIndex <= _startIndex)
299                         {
300                                 _endIndex = _track.getNumPoints() - 1;
301                         }
302                 }
303                 reset();
304                 _broker.informSubscribers();
305         }
306
307
308         /**
309          * Select the range up to the current point
310          */
311         public void selectRangeEnd()
312         {
313                 selectRangeEnd(_currentPoint);
314         }
315
316
317         /**
318          * Set the index for the end of the range selection
319          * @param inEndIndex end index
320          */
321         public void selectRangeEnd(int inEndIndex)
322         {
323                 if (inEndIndex < 0)
324                 {
325                         _startIndex = _endIndex = -1;
326                 }
327                 else
328                 {
329                         _endIndex = inEndIndex;
330                         // Move start of selection to min if necessary
331                         if (_startIndex > _endIndex || _startIndex < 0)
332                         {
333                                 _startIndex = 0;
334                         }
335                 }
336                 reset();
337                 _broker.informSubscribers();
338         }
339
340
341         /**
342          * Modify the selection given that the selected range has been deleted
343          */
344         public void modifyRangeDeleted()
345         {
346                 // Modify current point, if any
347                 if (_currentPoint > _endIndex)
348                 {
349                         _currentPoint -= (_endIndex - _startIndex);
350                 }
351                 else if (_currentPoint > _startIndex)
352                 {
353                         _currentPoint = _startIndex;
354                 }
355                 // Clear selected range
356                 _startIndex = _endIndex = -1;
357                 // Check for consistency and fire update
358                 check();
359         }
360
361
362         /**
363          * Modify the selection when a point is deleted
364          */
365         public void modifyPointDeleted()
366         {
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)
370                 {
371                         _endIndex--;
372                         if (_currentPoint < _startIndex)
373                                 _startIndex--;
374                         reset();
375                 }
376                 check();
377         }
378
379
380         /**
381          * Check that the selection still makes sense
382          * and fire update message to listeners
383          */
384         private void check()
385         {
386                 if (_track != null && _track.getNumPoints() > 0)
387                 {
388                         int maxIndex = _track.getNumPoints() - 1;
389                         if (_currentPoint > maxIndex)
390                         {
391                                 _currentPoint = maxIndex;
392                         }
393                         if (_endIndex > maxIndex)
394                         {
395                                 _endIndex = maxIndex;
396                         }
397                         if (_startIndex > maxIndex)
398                         {
399                                 _startIndex = maxIndex;
400                         }
401                 }
402                 _broker.informSubscribers();
403         }
404 }