+++ /dev/null
-package tim.prune.data;
-
-import tim.prune.config.Config;
-
-/**
- * Represents a range of altitudes, taking units into account.
- * Values assumed to be >= 0.
- */
-public class AltitudeRange
-{
- /** Range of altitudes in metres */
- private IntegerRange _range = new IntegerRange();
- /** Flag for whether previous value exists or not */
- private boolean _gotPreviousValue;
- /** Previous metric value */
- private int _previousValue;
- /** Total climb in metres */
- private int _climb;
- /** Total descent in metres */
- private int _descent;
- /** Flags for whether minimum or maximum has been found */
- private boolean _gotPreviousMinimum = false, _gotPreviousMaximum = false;
- /** Integer values of previous minimum and maximum, if any */
- private int _previousExtreme = 0;
-
-
- /**
- * Constructor
- */
- public AltitudeRange() {
- clear();
- }
-
- /**
- * Clear the altitude range
- */
- public void clear()
- {
- _range.clear();
- _climb = _descent = 0;
- _gotPreviousValue = false;
- _previousValue = 0;
- _gotPreviousMinimum = _gotPreviousMaximum = false;
- _previousExtreme = 0;
- }
-
-
- /**
- * Add a value to the range
- * @param inAltitude value to add, only positive values considered
- */
- public void addValue(Altitude inAltitude)
- {
- final int wiggleLimit = Config.getConfigInt(Config.KEY_ALTITUDE_TOLERANCE) / 100;
-
- if (inAltitude != null && inAltitude.isValid())
- {
- int altValue = (int) inAltitude.getMetricValue();
- _range.addValue(altValue);
- // Compare with previous value if any
- if (_gotPreviousValue)
- {
- if (altValue != _previousValue)
- {
- // Got an altitude value which is different from the previous one
- final boolean locallyUp = (altValue > _previousValue);
- final boolean overallUp = _gotPreviousMinimum && _previousValue > _previousExtreme;
- final boolean overallDn = _gotPreviousMaximum && _previousValue < _previousExtreme;
- final boolean moreThanWiggle = Math.abs(altValue - _previousValue) > wiggleLimit;
- // Do we know whether we're going up or down yet?
- if (!_gotPreviousMinimum && !_gotPreviousMaximum)
- {
- // we don't know whether we're going up or down yet - check limit
- if (moreThanWiggle)
- {
- if (locallyUp) {_gotPreviousMinimum = true;}
- else {_gotPreviousMaximum = true;}
- _previousExtreme = _previousValue;
- _previousValue = altValue;
- _gotPreviousValue = true;
- }
- }
- else if (overallUp)
- {
- if (locallyUp) {
- // we're still going up - do nothing
- _previousValue = altValue;
- }
- else if (moreThanWiggle)
- {
- // we're going up but have dropped over a maximum
- // Add the climb from _previousExtreme up to _previousValue
- _climb += (_previousValue - _previousExtreme);
- _previousExtreme = _previousValue;
- _gotPreviousMinimum = false; _gotPreviousMaximum = true;
- _previousValue = altValue;
- _gotPreviousValue = true;
- }
- }
- else if (overallDn)
- {
- if (locallyUp) {
- if (moreThanWiggle)
- {
- // we're going down but have climbed up from a minimum
- // Add the descent from _previousExtreme down to _previousValue
- _descent += (_previousExtreme - _previousValue);
- _previousExtreme = _previousValue;
- _gotPreviousMinimum = true; _gotPreviousMaximum = false;
- _previousValue = altValue;
- _gotPreviousValue = true;
- }
- }
- else {
- // we're still going down - do nothing
- _previousValue = altValue;
- _gotPreviousValue = true;
- }
- }
- // TODO: Behaviour when WIGGLE_LIMIT == 0 should be same as before, all differences cumulated
- }
- }
- else
- {
- // we haven't got a previous value at all, so it's the start of a new segment
- _previousValue = altValue;
- _gotPreviousValue = true;
- }
- }
- }
-
- /**
- * Reset the climb/descent calculations starting from the given value
- * @param inAltitude altitude value
- */
- public void ignoreValue(Altitude inAltitude)
- {
- // Process the previous value, if any, to update climb/descent as that's the end of the previous segment
- if (_gotPreviousValue && _gotPreviousMinimum && _previousValue > _previousExtreme) {
- _climb += (_previousValue - _previousExtreme);
- }
- else if (_gotPreviousValue && _gotPreviousMaximum && _previousValue < _previousExtreme) {
- _descent += (_previousExtreme - _previousValue);
- }
- // Eliminate the counting values to start the new segment
- _gotPreviousMinimum = _gotPreviousMaximum = false;
- _gotPreviousValue = false;
- // Now process this value if there is one
- if (inAltitude != null && inAltitude.isValid())
- {
- final int altValue = (int) inAltitude.getMetricValue();
- _range.addValue(altValue);
- _previousValue = altValue;
- _gotPreviousValue = true;
- }
- }
-
- /**
- * @return true if altitude range found
- */
- public boolean hasRange()
- {
- return _range.hasValues();
- }
-
-
- /**
- * @param inUnit altitude units to use
- * @return minimum value
- */
- public int getMinimum(Unit inUnit)
- {
- return (int) (_range.getMinimum() * inUnit.getMultFactorFromStd());
- }
-
- /**
- * @param inUnit altitude units to use
- * @return maximum value
- */
- public int getMaximum(Unit inUnit)
- {
- return (int) (_range.getMaximum() * inUnit.getMultFactorFromStd());
- }
-
- /**
- * @param inUnit altitude units to use
- * @return total climb
- */
- public int getClimb(Unit inUnit)
- {
- // May need to add climb from last segment
- int lastSegmentClimb = 0;
- if (_gotPreviousValue && _gotPreviousMinimum && _previousValue > _previousExtreme) {
- lastSegmentClimb = _previousValue - _previousExtreme;
- }
- return (int) ((_climb + lastSegmentClimb) * inUnit.getMultFactorFromStd());
- }
-
- /**
- * @param inUnit altitude units to use
- * @return total descent
- */
- public int getDescent(Unit inUnit)
- {
- // May need to add descent from last segment
- int lastSegmentDescent = 0;
- if (_gotPreviousValue && _gotPreviousMaximum && _previousValue < _previousExtreme) {
- lastSegmentDescent = _previousExtreme - _previousValue;
- }
- return (int) ((_descent + lastSegmentDescent) * inUnit.getMultFactorFromStd());
- }
-
- /**
- * @return overall height gain in metres
- */
- public double getMetricHeightDiff()
- {
- return getClimb(UnitSetLibrary.UNITS_METRES) - getDescent(UnitSetLibrary.UNITS_METRES);
- }
-}