]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/data/AltitudeRange.java
Version 19, May 2018
[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.hasValues();
174         }
175
176
177         /**
178          * @param inUnit altitude units to use
179          * @return minimum value
180          */
181         public int getMinimum(Unit inUnit)
182         {
183                 return (int) (_range.getMinimum() * inUnit.getMultFactorFromStd());
184         }
185
186         /**
187          * @param inUnit altitude units to use
188          * @return maximum value
189          */
190         public int getMaximum(Unit inUnit)
191         {
192                 return (int) (_range.getMaximum() * inUnit.getMultFactorFromStd());
193         }
194
195         /**
196          * @param inUnit altitude units to use
197          * @return total climb
198          */
199         public int getClimb(Unit inUnit)
200         {
201                 // May need to add climb from last segment
202                 int lastSegmentClimb = 0;
203                 if (_gotPreviousValue && _gotPreviousMinimum && _previousValue > _previousExtreme) {
204                         lastSegmentClimb = _previousValue - _previousExtreme;
205                 }
206                 return (int) ((_climb + lastSegmentClimb) * inUnit.getMultFactorFromStd());
207         }
208
209         /**
210          * @param inUnit altitude units to use
211          * @return total descent
212          */
213         public int getDescent(Unit inUnit)
214         {
215                 // May need to add descent from last segment
216                 int lastSegmentDescent = 0;
217                 if (_gotPreviousValue && _gotPreviousMaximum && _previousValue < _previousExtreme) {
218                         lastSegmentDescent = _previousExtreme - _previousValue;
219                 }
220                 return (int) ((_descent + lastSegmentDescent) * inUnit.getMultFactorFromStd());
221         }
222
223         /**
224          * @return overall height gain in metres
225          */
226         public double getMetricHeightDiff()
227         {
228                 return getClimb(UnitSetLibrary.UNITS_METRES) - getDescent(UnitSetLibrary.UNITS_METRES);
229         }
230 }