]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/data/Altitude.java
Version 14, October 2012
[GpsPrune.git] / tim / prune / data / Altitude.java
index b55a429200c723e9f511a7a4b769e65befdcc622..ac71d759cb4a45a8a7af971b8d6adc830010bf83 100644 (file)
@@ -7,25 +7,40 @@ public class Altitude
 {
        private boolean _valid = false;
        private int _value = 0;
-       private int _format = -1;
-       public static final int FORMAT_NONE   = -1;
-       public static final int FORMAT_METRES = 0;
-       public static final int FORMAT_FEET = 1;
+       private Format _format = Format.NO_FORMAT;
+       private String _stringValue = null;
+
+       /** Altitude formats */
+       public enum Format {
+               /** No format */
+               NO_FORMAT,
+               /** Metres */
+               METRES,
+               /** Feet */
+               FEET
+       }
+
+       /** Constants for conversion */
+       private static final double CONVERT_METRES_TO_FEET = UnitSetLibrary.UNITS_FEET.getMultFactorFromStd();
+       private static final double CONVERT_FEET_TO_METRES = 1 / CONVERT_METRES_TO_FEET;
 
-       private static final double CONVERT_FEET_TO_METRES = 0.3048;
-       private static final double CONVERT_METRES_TO_FEET = 3.28084;
+       /** Constant for no altitude value */
+       public static final Altitude NONE = new Altitude(null, Format.NO_FORMAT);
 
 
        /**
-        * Constructor
+        * Constructor using String
+        * @param inString string to parse
+        * @param inFormat format of altitude, either metres or feet
         */
-       public Altitude(String inString, int inFormat)
+       public Altitude(String inString, Format inFormat)
        {
                if (inString != null && !inString.equals(""))
                {
                        try
                        {
-                               _value = Integer.parseInt(inString.trim());
+                               _stringValue = inString;
+                               _value = (int) Double.parseDouble(inString.trim());
                                _format = inFormat;
                                _valid = true;
                        }
@@ -35,15 +50,36 @@ public class Altitude
 
 
        /**
-        * Constructor
+        * Constructor with int value
+        * @param inValue int value of altitude
+        * @param inFormat format of altitude, either metres or feet
         */
-       public Altitude(int inValue, int inFormat)
+       public Altitude(int inValue, Format inFormat)
        {
                _value = inValue;
                _format = inFormat;
                _valid = true;
        }
 
+       /**
+        * @return an exact copy of this Altitude object
+        */
+       public Altitude clone()
+       {
+               return new Altitude(_stringValue, _format);
+       }
+
+       /**
+        * 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;
+               _format = inClone._format;
+               _valid = inClone._valid;
+       }
 
        /**
         * @return true if the value could be parsed
@@ -62,11 +98,19 @@ public class Altitude
                return _value;
        }
 
+       /**
+        * @param inAltUnit altitude units to use
+        * @return rounded value in specified units
+        */
+       public int getValue(Unit inAltUnit)
+       {
+               return (int) (getMetricValue() * inAltUnit.getMultFactorFromStd());
+       }
 
        /**
         * @return format of number
         */
-       public int getFormat()
+       public Format getFormat()
        {
                return _format;
        }
@@ -77,18 +121,45 @@ public class Altitude
         * @param inFormat desired format, either FORMAT_METRES or FORMAT_FEET
         * @return value as an int
         */
-       public int getValue(int inFormat)
+       public int getValue(Format inFormat)
        {
-               // TODO: Fix rounding errors here converting between units - return double?
+               // Note possible rounding errors here if converting to/from units
                if (inFormat == _format)
                        return _value;
-               if (inFormat == FORMAT_METRES)
+               if (inFormat == Format.METRES)
                        return (int) (_value * CONVERT_FEET_TO_METRES);
-               if (inFormat == FORMAT_FEET)
+               if (inFormat == Format.FEET)
                        return (int) (_value * CONVERT_METRES_TO_FEET);
                return _value;
        }
 
+       /**
+        * @return value of altitude in metres, used for calculations and charts
+        */
+       public double getMetricValue()
+       {
+               if (_format == Format.FEET) {
+                       return _value / UnitSetLibrary.UNITS_FEET.getMultFactorFromStd();
+               }
+               return _value;
+       }
+
+       /**
+        * Get a string version of the value
+        * @param inFormat specified format
+        * @return string value, if possible the original one
+        */
+       public String getStringValue(Format inFormat)
+       {
+               if (!_valid) {return "";}
+               // Return string value if the same format or "no format" was requested
+               if ((inFormat == _format || inFormat == Format.NO_FORMAT)
+                && _stringValue != null && !_stringValue.equals("")) {
+                       return _stringValue;
+               }
+               return "" + getValue(inFormat);
+       }
+
 
        /**
         * Interpolate a new Altitude object between the given ones
@@ -99,16 +170,57 @@ public class Altitude
         * @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 new Altitude(null, FORMAT_NONE);
+                       return Altitude.NONE;
                // Use altitude format of first point
-               int altFormat = inStart.getFormat();
+               Format altFormat = inStart.getFormat();
                int startValue = inStart.getValue();
                int endValue = inEnd.getValue(altFormat);
-               int newValue = startValue
-                       + (int) ((endValue - startValue) * 1.0 / (inNumSteps + 1) * (inIndex + 1));
+               // interpolate between start and end
+               int newValue = startValue + (int) ((endValue - startValue) * inFrac);
                return new Altitude(newValue, altFormat);
        }
+
+       /**
+        * Add the given offset to the current altitude
+        * @param inOffset offset as double
+        * @param inFormat format of offset, feet or metres
+        * @param inDecimals number of decimal places
+        */
+       public void addOffset(double inOffset, Format inFormat, 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 (inFormat != _format)
+               {
+                       if (inFormat == Format.FEET)
+                               offset = inOffset * CONVERT_FEET_TO_METRES;
+                       else
+                               offset = inOffset * CONVERT_METRES_TO_FEET;
+               }
+               // 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.formatNumber(newValue, numDecimals);
+       }
 }