]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/data/Altitude.java
Version 14, October 2012
[GpsPrune.git] / tim / prune / data / Altitude.java
1 package tim.prune.data;
2
3 /**
4  * Class to hold an altitude and provide conversion functions
5  */
6 public class Altitude
7 {
8         private boolean _valid = false;
9         private int _value = 0;
10         private Format _format = Format.NO_FORMAT;
11         private String _stringValue = null;
12
13         /** Altitude formats */
14         public enum Format {
15                 /** No format */
16                 NO_FORMAT,
17                 /** Metres */
18                 METRES,
19                 /** Feet */
20                 FEET
21         }
22
23         /** Constants for conversion */
24         private static final double CONVERT_METRES_TO_FEET = UnitSetLibrary.UNITS_FEET.getMultFactorFromStd();
25         private static final double CONVERT_FEET_TO_METRES = 1 / CONVERT_METRES_TO_FEET;
26
27         /** Constant for no altitude value */
28         public static final Altitude NONE = new Altitude(null, Format.NO_FORMAT);
29
30
31         /**
32          * Constructor using String
33          * @param inString string to parse
34          * @param inFormat format of altitude, either metres or feet
35          */
36         public Altitude(String inString, Format inFormat)
37         {
38                 if (inString != null && !inString.equals(""))
39                 {
40                         try
41                         {
42                                 _stringValue = inString;
43                                 _value = (int) Double.parseDouble(inString.trim());
44                                 _format = inFormat;
45                                 _valid = true;
46                         }
47                         catch (NumberFormatException nfe) {}
48                 }
49         }
50
51
52         /**
53          * Constructor with int value
54          * @param inValue int value of altitude
55          * @param inFormat format of altitude, either metres or feet
56          */
57         public Altitude(int inValue, Format inFormat)
58         {
59                 _value = inValue;
60                 _format = inFormat;
61                 _valid = true;
62         }
63
64         /**
65          * @return an exact copy of this Altitude object
66          */
67         public Altitude clone()
68         {
69                 return new Altitude(_stringValue, _format);
70         }
71
72         /**
73          * Reset the altitude parameters to the same as the given object
74          * @param inClone clone object to copy
75          */
76         public void reset(Altitude inClone)
77         {
78                 _stringValue = inClone._stringValue;
79                 _value = inClone._value;
80                 _format = inClone._format;
81                 _valid = inClone._valid;
82         }
83
84         /**
85          * @return true if the value could be parsed
86          */
87         public boolean isValid()
88         {
89                 return _valid;
90         }
91
92
93         /**
94          * @return raw value as int
95          */
96         public int getValue()
97         {
98                 return _value;
99         }
100
101         /**
102          * @param inAltUnit altitude units to use
103          * @return rounded value in specified units
104          */
105         public int getValue(Unit inAltUnit)
106         {
107                 return (int) (getMetricValue() * inAltUnit.getMultFactorFromStd());
108         }
109
110         /**
111          * @return format of number
112          */
113         public Format getFormat()
114         {
115                 return _format;
116         }
117
118
119         /**
120          * Get the altitude value in the specified format
121          * @param inFormat desired format, either FORMAT_METRES or FORMAT_FEET
122          * @return value as an int
123          */
124         public int getValue(Format inFormat)
125         {
126                 // Note possible rounding errors here if converting to/from units
127                 if (inFormat == _format)
128                         return _value;
129                 if (inFormat == Format.METRES)
130                         return (int) (_value * CONVERT_FEET_TO_METRES);
131                 if (inFormat == Format.FEET)
132                         return (int) (_value * CONVERT_METRES_TO_FEET);
133                 return _value;
134         }
135
136         /**
137          * @return value of altitude in metres, used for calculations and charts
138          */
139         public double getMetricValue()
140         {
141                 if (_format == Format.FEET) {
142                         return _value / UnitSetLibrary.UNITS_FEET.getMultFactorFromStd();
143                 }
144                 return _value;
145         }
146
147         /**
148          * Get a string version of the value
149          * @param inFormat specified format
150          * @return string value, if possible the original one
151          */
152         public String getStringValue(Format inFormat)
153         {
154                 if (!_valid) {return "";}
155                 // Return string value if the same format or "no format" was requested
156                 if ((inFormat == _format || inFormat == Format.NO_FORMAT)
157                  && _stringValue != null && !_stringValue.equals("")) {
158                         return _stringValue;
159                 }
160                 return "" + getValue(inFormat);
161         }
162
163
164         /**
165          * Interpolate a new Altitude object between the given ones
166          * @param inStart start altitude
167          * @param inEnd end altitude
168          * @param inIndex index of interpolated point
169          * @param inNumSteps number of steps to interpolate
170          * @return Interpolated Altitude object
171          */
172         public static Altitude interpolate(Altitude inStart, Altitude inEnd, int inIndex, int inNumSteps)
173         {
174                 return interpolate(inStart, inEnd, 1.0 * (inIndex + 1) / (inNumSteps + 1));
175         }
176
177
178         /**
179          * Interpolate a new Altitude object between the given ones
180          * @param inStart start altitude
181          * @param inEnd end altitude
182          * @param inFrac fraction of distance from first point
183          * @return Interpolated Altitude object
184          */
185         public static Altitude interpolate(Altitude inStart, Altitude inEnd, double inFrac)
186         {
187                 // Check if altitudes are valid
188                 if (inStart == null || inEnd == null || !inStart.isValid() || !inEnd.isValid())
189                         return Altitude.NONE;
190                 // Use altitude format of first point
191                 Format altFormat = inStart.getFormat();
192                 int startValue = inStart.getValue();
193                 int endValue = inEnd.getValue(altFormat);
194                 // interpolate between start and end
195                 int newValue = startValue + (int) ((endValue - startValue) * inFrac);
196                 return new Altitude(newValue, altFormat);
197         }
198
199         /**
200          * Add the given offset to the current altitude
201          * @param inOffset offset as double
202          * @param inFormat format of offset, feet or metres
203          * @param inDecimals number of decimal places
204          */
205         public void addOffset(double inOffset, Format inFormat, int inDecimals)
206         {
207                 // Use the maximum number of decimal places from current value and offset
208                 int numDecimals = NumberUtils.getDecimalPlaces(_stringValue);
209                 if (numDecimals < inDecimals) {numDecimals = inDecimals;}
210                 // Convert offset to correct units
211                 double offset = inOffset;
212                 if (inFormat != _format)
213                 {
214                         if (inFormat == Format.FEET)
215                                 offset = inOffset * CONVERT_FEET_TO_METRES;
216                         else
217                                 offset = inOffset * CONVERT_METRES_TO_FEET;
218                 }
219                 // FIXME: The following will fail if _stringValue is null - not sure how it can get in that state!
220                 if (_stringValue == null) System.err.println("*** Altitude.addOffset - how did the string value get to be null?");
221                 // Add the offset
222                 double newValue = Double.parseDouble(_stringValue.trim()) + offset;
223                 _value = (int) newValue;
224                 _stringValue = NumberUtils.formatNumber(newValue, numDecimals);
225         }
226 }