package tim.prune.data; /** * Class to hold an altitude and provide conversion functions */ public class Altitude { private boolean _valid = false; private int _value = 0; private Unit _unit = null; private String _stringValue = null; /** Constant to use for a lack of altitude */ public static final Altitude NONE = new Altitude(null, null); /** * Constructor using String * @param inString string to parse * @param inUnit of altitude, either metres or feet */ public Altitude(String inString, Unit inUnit) { _unit = inUnit; if (inString != null && !inString.equals("")) { try { _stringValue = inString; _value = (int) Double.parseDouble(inString.trim()); _valid = true; } catch (NumberFormatException nfe) {} } } /** * Constructor with int value * @param inValue int value of altitude * @param inUnit unit of altitude, either metres or feet */ public Altitude(int inValue, Unit inUnit) { _value = inValue; _unit = inUnit; _valid = true; _stringValue = "" + inValue; } /** * @return an exact copy of this Altitude object */ public Altitude clone() { return new Altitude(_stringValue, _unit); } /** * Reset the altitude parameters to the same as the given object * @param inClone clone object to copy */ public void reset(Altitude inClone) { _stringValue = inClone._stringValue; _value = inClone._value; _unit = inClone._unit; _valid = inClone._valid; } /** * @return true if the value could be parsed */ public boolean isValid() { return _valid; } /** * @return raw value as int */ public int getValue() { return _value; } /** * @param inAltUnit altitude units to use * @return rounded value in specified units */ public int getValue(Unit inAltUnit) { if (inAltUnit == null) { return getValue(); } return (int) (getMetricValue() * inAltUnit.getMultFactorFromStd()); } /** * @return unit of number */ public Unit getUnit() { return _unit; } /** * @return value of altitude in metres, used for calculations and charts */ public double getMetricValue() { if (_unit == UnitSetLibrary.UNITS_METRES || _unit == null) { return _value; } return _value / _unit.getMultFactorFromStd(); } /** * Get a string version of the value * @param inUnit specified unit * @return string value, if possible the original one */ public String getStringValue(Unit inUnit) { if (!_valid) {return "";} // Return string value if the same format or "no format" was requested if ((inUnit == _unit || inUnit == null) && _stringValue != null && !_stringValue.equals("")) { return _stringValue; } return "" + getValue(inUnit); } /** * Interpolate a new Altitude object between the given ones * @param inStart start altitude * @param inEnd end altitude * @param inIndex index of interpolated point * @param inNumSteps number of steps to interpolate * @return Interpolated Altitude object */ public static Altitude interpolate(Altitude inStart, Altitude inEnd, int inIndex, int inNumSteps) { return interpolate(inStart, inEnd, 1.0 * (inIndex + 1) / (inNumSteps + 1)); } /** * Interpolate a new Altitude object between the given ones * @param inStart start altitude * @param inEnd end altitude * @param inFrac fraction of distance from first point * @return Interpolated Altitude object */ public static Altitude interpolate(Altitude inStart, Altitude inEnd, double inFrac) { // Check if altitudes are valid if (inStart == null || inEnd == null || !inStart.isValid() || !inEnd.isValid()) return Altitude.NONE; // Use altitude format of first point Unit altUnit = inStart.getUnit(); int startValue = inStart.getValue(); int endValue = inEnd.getValue(altUnit); // interpolate between start and end int newValue = startValue + (int) ((endValue - startValue) * inFrac); return new Altitude(newValue, altUnit); } /** * Add the given offset to the current altitude * @param inOffset offset as double * @param inUnit unit of offset, feet or metres * @param inDecimals number of decimal places */ public void addOffset(double inOffset, Unit inUnit, int inDecimals) { // Use the maximum number of decimal places from current value and offset int numDecimals = NumberUtils.getDecimalPlaces(_stringValue); if (numDecimals < inDecimals) {numDecimals = inDecimals;} // Convert offset to correct units double offset = inOffset; if (inUnit != _unit && inUnit != null) { offset = inOffset / inUnit.getMultFactorFromStd() * _unit.getMultFactorFromStd(); } // FIXME: The following will fail if _stringValue is null - not sure how it can get in that state! if (_stringValue == null) System.err.println("*** Altitude.addOffset - how did the string value get to be null?"); // Add the offset double newValue = Double.parseDouble(_stringValue.trim()) + offset; _value = (int) newValue; _stringValue = NumberUtils.formatNumberUk(newValue, numDecimals); } }