]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/data/AltitudeRange.java
Version 17, September 2014
[GpsPrune.git] / tim / prune / data / AltitudeRange.java
1 package tim.prune.data;
2
3 import tim.prune.config.Config;
4
5 /**
6  * Represents a range of altitudes, taking units into account.
7  * Values assumed to be >= 0.
8  */
9 public class AltitudeRange
10 {
11         /** Range of altitudes in metres */
12         private IntegerRange _range = new IntegerRange();
13         /** Flag for whether previous value exists or not */
14         private boolean _gotPreviousValue;
15         /** Previous metric value */
16         private int _previousValue;
17         /** Total climb in metres */
18         private int _climb;
19         /** Total descent in metres */
20         private int _descent;
21         /** Flags for whether minimum or maximum has been found */
22         private boolean _gotPreviousMinimum = false, _gotPreviousMaximum = false;
23         /** Integer values of previous minimum and maximum, if any */
24         private int     _previousExtreme = 0;
25
26
27         /**
28          * Constructor
29          */
30         public AltitudeRange() {
31                 clear();
32         }
33
34         /**
35          * Clear the altitude range
36          */
37         public void clear()
38         {
39                 _range.clear();
40                 _climb = _descent = 0;
41                 _gotPreviousValue = false;
42                 _previousValue = 0;
43                 _gotPreviousMinimum = _gotPreviousMaximum = false;
44                 _previousExtreme = 0;
45         }
46
47
48         /**
49          * Add a value to the range
50          * @param inAltitude value to add, only positive values considered
51          */
52         public void addValue(Altitude inAltitude)
53         {
54                 final int wiggleLimit = Config.getConfigInt(Config.KEY_ALTITUDE_TOLERANCE) / 100;
55
56                 if (inAltitude != null && inAltitude.isValid())
57                 {
58                         int altValue = (int) inAltitude.getMetricValue();
59                         _range.addValue(altValue);
60                         // Compare with previous value if any
61                         if (_gotPreviousValue)
62                         {
63                                 if (altValue != _previousValue)
64                                 {
65                                         // Got an altitude value which is different from the previous one
66                                         final boolean locallyUp = (altValue > _previousValue);
67                                         final boolean overallUp = _gotPreviousMinimum && _previousValue > _previousExtreme;
68                                         final boolean overallDn = _gotPreviousMaximum && _previousValue < _previousExtreme;
69                                         final boolean moreThanWiggle = Math.abs(altValue - _previousValue) > wiggleLimit;
70                                         // Do we know whether we're going up or down yet?
71                                         if (!_gotPreviousMinimum && !_gotPreviousMaximum)
72                                         {
73                                                 // we don't know whether we're going up or down yet - check limit
74                                                 if (moreThanWiggle)
75                                                 {
76                                                         if (locallyUp) {_gotPreviousMinimum = true;}
77                                                         else {_gotPreviousMaximum = true;}
78                                                         _previousExtreme = _previousValue;
79                                                         _previousValue = altValue;
80                                                         _gotPreviousValue = true;
81                                                 }
82                                         }
83                                         else if (overallUp)
84                                         {
85                                                 if (locallyUp) {
86                                                         // we're still going up - do nothing
87                                                         _previousValue = altValue;
88                                                 }
89                                                 else if (moreThanWiggle)
90                                                 {
91                                                         // we're going up but have dropped over a maximum
92                                                         // Add the climb from _previousExtreme up to _previousValue
93                                                         _climb += (_previousValue - _previousExtreme);
94                                                         _previousExtreme = _previousValue;
95                                                         _gotPreviousMinimum = false; _gotPreviousMaximum = true;
96                                                         _previousValue = altValue;
97                                                         _gotPreviousValue = true;
98                                                 }
99                                         }
100                                         else if (overallDn)
101                                         {
102                                                 if (locallyUp) {
103                                                         if (moreThanWiggle)
104                                                         {
105                                                                 // we're going down but have climbed up from a minimum
106                                                                 // Add the descent from _previousExtreme down to _previousValue
107                                                                 _descent += (_previousExtreme - _previousValue);
108                                                                 _previousExtreme = _previousValue;
109                                                                 _gotPreviousMinimum = true; _gotPreviousMaximum = false;
110                                                                 _previousValue = altValue;
111                                                                 _gotPreviousValue = true;
112                                                         }
113                                                 }
114                                                 else {
115                                                         // we're still going down - do nothing
116                                                         _previousValue = altValue;
117                                                         _gotPreviousValue = true;
118                                                 }
119                                         }
120                                         // TODO: Behaviour when WIGGLE_LIMIT == 0 should be same as before, all differences cumulated
121                                 }
122                         }
123                         else
124                         {
125                                 // we haven't got a previous value at all, so it's the start of a new segment
126                                 _previousValue = altValue;
127                                 _gotPreviousValue = true;
128                         }
129
130 //                      if (!_empty)
131 //                      {
132 //                              if (altValue > _previousValue)
133 //                                      _climb += (altValue - _previousValue);
134 //                              else
135 //                                      _descent += (_previousValue - altValue);
136 //                      }
137 //                      _previousValue = altValue;
138 //                      _empty = false;
139                 }
140         }
141
142         /**
143          * Reset the climb/descent calculations starting from the given value
144          * @param inAltitude altitude value
145          */
146         public void ignoreValue(Altitude inAltitude)
147         {
148                 // Process the previous value, if any, to update climb/descent as that's the end of the previous segment
149                 if (_gotPreviousValue && _gotPreviousMinimum && _previousValue > _previousExtreme) {
150                         _climb += (_previousValue - _previousExtreme);
151                 }
152                 else if (_gotPreviousValue && _gotPreviousMaximum && _previousValue < _previousExtreme) {
153                         _descent += (_previousExtreme - _previousValue);
154                 }
155                 // Eliminate the counting values to start the new segment
156                 _gotPreviousMinimum = _gotPreviousMaximum = false;
157                 _gotPreviousValue = false;
158                 // Now process this value if there is one
159                 if (inAltitude != null && inAltitude.isValid())
160                 {
161                         final int altValue = (int) inAltitude.getMetricValue();
162                         _range.addValue(altValue);
163                         _previousValue = altValue;
164                         _gotPreviousValue = true;
165                 }
166         }
167
168         /**
169          * @return true if altitude range found
170          */
171         public boolean hasRange()
172         {
173                 return _range.getMaximum() > _range.getMinimum();
174         }
175
176
177         /**
178          * @param inUnit altitude units to use
179          * @return minimum value, or -1 if none found
180          */
181         public int getMinimum(Unit inUnit)
182         {
183                 if (_range.getMinimum() <= 0) return _range.getMinimum();
184                 return (int) (_range.getMinimum() * inUnit.getMultFactorFromStd());
185         }
186
187         /**
188          * @param inUnit altitude units to use
189          * @return maximum value, or -1 if none found
190          */
191         public int getMaximum(Unit inUnit)
192         {
193                 if (_range.getMaximum() <= 0) return _range.getMaximum();
194                 return (int) (_range.getMaximum() * inUnit.getMultFactorFromStd());
195         }
196
197         /**
198          * @param inUnit altitude units to use
199          * @return total climb
200          */
201         public int getClimb(Unit inUnit)
202         {
203                 // May need to add climb from last segment
204                 int lastSegmentClimb = 0;
205                 if (_gotPreviousValue && _gotPreviousMinimum && _previousValue > _previousExtreme) {
206                         lastSegmentClimb = _previousValue - _previousExtreme;
207                 }
208                 return (int) ((_climb + lastSegmentClimb) * inUnit.getMultFactorFromStd());
209         }
210
211         /**
212          * @param inUnit altitude units to use
213          * @return total descent
214          */
215         public int getDescent(Unit inUnit)
216         {
217                 // May need to add descent from last segment
218                 int lastSegmentDescent = 0;
219                 if (_gotPreviousValue && _gotPreviousMaximum && _previousValue < _previousExtreme) {
220                         lastSegmentDescent = _previousExtreme - _previousValue;
221                 }
222                 return (int) ((_descent + lastSegmentDescent) * inUnit.getMultFactorFromStd());
223         }
224
225         /**
226          * @return overall height gain in metres
227          */
228         public double getMetricHeightDiff()
229         {
230                 return getClimb(UnitSetLibrary.UNITS_METRES) - getDescent(UnitSetLibrary.UNITS_METRES);
231         }
232 }