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);
}
}