1 package tim.prune.data;
4 * Class to manage the scaling of points
6 public class PointScaler
9 private Track _track = null;
11 private AltitudeRange _altRange = null;
12 private DoubleRange _latRange = null;
13 private DoubleRange _lonRange = null;
14 private double _latMedian = 0.0;
15 private double _lonMedian = 0.0;
16 private int _minAltitude = 0;
17 private int _maxAltitude = 0;
18 // Scaling information
19 private double _longFactor = 0.0;
21 private double[] _xValues = null;
22 private double[] _yValues = null;
23 private int[] _altValues = null;
24 private double _maxX = 0.0;
25 private double _maxY = 0.0;
27 private double[] _latLinesDegs = null;
28 private double[] _lonLinesDegs = null;
29 private double[] _latLinesScaled = null;
30 private double[] _lonLinesScaled = null;
33 private static final double[] COORD_SEPARATIONS = {
35 30.0/60.0, 20.0/60.0, // 30min, 20min
36 10.0/60.0, 5.0/60.0, // 10min, 5min
37 3.0/60.0, 2.0/60.0, 1.0/60.0 // 3min, 2min, 1min
39 private static final int MAX_COORD_SEPARATION_INDEX = COORD_SEPARATIONS.length - 1;
43 * @param inTrack Track object
45 public PointScaler(Track inTrack)
48 _altRange = new AltitudeRange();
49 _latRange = new DoubleRange();
50 _lonRange = new DoubleRange();
65 DataPoint point = null;
66 // Find limits of data
67 if (_track != null && (numPoints = _track.getNumPoints()) > 0)
69 for (p=0; p<numPoints; p++)
71 point = _track.getPoint(p);
74 _latRange.addValue(point.getLatitude().getDouble());
75 _lonRange.addValue(point.getLongitude().getDouble());
76 _altRange.addValue(point.getAltitude());
80 // Find median latitude and calculate factor
81 _latMedian = (_latRange.getMinimum() + _latRange.getMaximum()) / 2;
82 _lonMedian = (_lonRange.getMinimum() + _lonRange.getMaximum()) / 2;
83 _minAltitude = _altRange.getMinimum();
84 _longFactor = Math.cos(_latMedian / 180.0 * Math.PI); // quite rough
86 // create new arrays for scaled values
87 if (_xValues == null || _xValues.length != numPoints)
89 _xValues = new double[numPoints];
90 _yValues = new double[numPoints];
91 _altValues = new int[numPoints];
93 // Calculate scaled values
94 for (p=0; p<numPoints; p++)
96 point = _track.getPoint(p);
99 _xValues[p] = getScaledLongitude(point.getLongitude().getDouble());
100 _yValues[p] = getScaledLatitude(point.getLatitude().getDouble());
101 _altValues[p] = getScaledAltitude(point.getAltitude());
104 // Calculate x and y range
105 _maxX = getScaledLongitude(_lonRange.getMaximum());
106 _maxY = getScaledLatitude(_latRange.getMaximum());
107 _maxAltitude = _altRange.getMaximum() - _altRange.getMinimum();
113 * @return maximum horiz value
115 public double getMaximumHoriz() { return _maxX; }
117 * @return maximum vert value
119 public double getMaximumVert() { return _maxY; }
121 * @return maximum alt value
123 public int getMaximumAlt() { return _maxAltitude; }
126 * Get the horizontal value for the specified point
127 * @param inIndex index of point, starting at 0
128 * @return scaled horizontal value
130 public double getHorizValue(int inIndex)
132 return _xValues[inIndex];
135 * Get the vertical value for the specified point
136 * @param inIndex index of point, starting at 0
137 * @return scaled vertical value
139 public double getVertValue(int inIndex)
141 return _yValues[inIndex];
144 * Get the altitude value for the specified point
145 * @param inIndex index of point, starting at 0
146 * @return scaled altitude value
148 public int getAltValue(int inIndex)
150 return _altValues[inIndex];
154 * Scale the given latitude value
155 * @param inLatitude latitude in degrees
156 * @return scaled latitude
158 public double getScaledLatitude(double inLatitude)
160 return inLatitude - _latMedian;
163 * Scale the given longitude value
164 * @param inLongitude longitude in degrees
165 * @return scaled longitude
167 public double getScaledLongitude(double inLongitude)
169 return (inLongitude - _lonMedian) * _longFactor;
172 * Scale the given altitude value
173 * @param inAltitude Altitude object
174 * @return scaled altitude
176 public int getScaledAltitude(Altitude inAltitude)
178 if (inAltitude == null) return -1;
179 return inAltitude.getValue(_altRange.getFormat()) - _minAltitude;
183 * Unscale the given latitude value
184 * @param inScaledLatitude scaled latitude
185 * @return latitude in degrees
187 public double getUnscaledLatitude(double inScaledLatitude)
189 return inScaledLatitude + _latMedian;
192 * Unscale the given longitude value
193 * @param inScaledLongitude scaled longitude
194 * @return longitude in degrees
196 public double getUnscaledLongitude(double inScaledLongitude)
198 return inScaledLongitude / _longFactor + _lonMedian;
202 * Calculate the latitude and longitude lines
204 public void calculateLatLongLines()
206 double maxValue = getMaximumHoriz() > getMaximumVert() ?
207 getMaximumHoriz():getMaximumVert();
208 // calculate boundaries in degrees
209 double minLong = getUnscaledLongitude(-maxValue);
210 double maxLong = getUnscaledLongitude(maxValue);
211 double minLat = getUnscaledLatitude(-maxValue);
212 double maxLat = getUnscaledLatitude(maxValue);
213 // work out what line separation to use to give at least two lines
216 int numLatLines = 0, numLonLines = 0;
220 separation = COORD_SEPARATIONS[sepIndex];
221 numLatLines = getNumLinesBetween(minLat, maxLat, separation);
222 numLonLines = getNumLinesBetween(minLong, maxLong, separation);
224 while ((numLonLines <= 1 || numLatLines <= 1) && sepIndex < MAX_COORD_SEPARATION_INDEX);
225 // create lines based on this separation
226 _latLinesDegs = getLines(minLat, maxLat, separation, numLatLines);
227 _lonLinesDegs = getLines(minLong, maxLong, separation, numLonLines);
229 _latLinesScaled = new double[numLatLines];
230 for (int i=0; i<numLatLines; i++) _latLinesScaled[i] = getScaledLatitude(_latLinesDegs[i]);
231 _lonLinesScaled = new double[numLonLines];
232 for (int i=0; i<numLonLines; i++) _lonLinesScaled[i] = getScaledLongitude(_lonLinesDegs[i]);
237 * Calculate the number of lines in the given range using the specified separation
238 * @param inMin minimum value
239 * @param inMax maximum value
240 * @param inSeparation line separation
241 * @return number of lines
243 private static int getNumLinesBetween(double inMin, double inMax, double inSeparation)
245 // Start looking from round number of degrees below minimum
246 double value = (int) inMin;
247 if (inMin < 0.0) value = value - 1.0;
248 // Loop until bigger than maximum
250 while (value < inMax)
252 if (value >= inMin) numLines++;
253 value += inSeparation;
260 * Get the line values in the given range using the specified separation
261 * @param inMin minimum value
262 * @param inMax maximum value
263 * @param inSeparation line separation
264 * @param inCount number of lines already counted
265 * @return array of line values
267 private static double[] getLines(double inMin, double inMax, double inSeparation, int inCount)
269 double[] values = new double[inCount];
270 // Start looking from round number of degrees below minimum
271 double value = (int) inMin;
272 if (inMin < 0.0) value = value - 1.0;
273 // Loop until bigger than maximum
275 while (value < inMax)
279 values[numLines] = value;
282 value += inSeparation;
288 * @return array of latitude lines in degrees
290 public double[] getLatitudeLines()
292 return _latLinesDegs;
295 * @return array of longitude lines in degrees
297 public double[] getLongitudeLines()
299 return _lonLinesDegs;
302 * @return array of latitude lines in scaled units
304 public double[] getScaledLatitudeLines()
306 return _latLinesScaled;
309 * @return array of longitude lines in scaled units
311 public double[] getScaledLongitudeLines()
313 return _lonLinesScaled;