1 package tim.prune.data;
4 * Class to manage the scaling of points
6 public class PointScaler
9 private Track _track = null;
11 private double _latMedian = 0.0;
12 private double _lonMedian = 0.0;
13 private int _minAltitude = 0;
14 // Scaling information
15 private double _longFactor = 0.0;
16 private double _altFactor = 0.0;
18 private double[] _xValues = null;
19 private double[] _yValues = null;
20 private double[] _altValues = null;
22 private double _maxX = 0.0;
23 private double _maxY = 0.0;
24 private double _maxScaledAlt = 0.0;
26 private double[] _latLinesDegs = null;
27 private double[] _lonLinesDegs = null;
28 private double[] _latLinesScaled = null;
29 private double[] _lonLinesScaled = null;
32 private static final double[] COORD_SEPARATIONS = {
34 30.0/60.0, 20.0/60.0, // 30min, 20min
35 10.0/60.0, 5.0/60.0, // 10min, 5min
36 3.0/60.0, 2.0/60.0, 1.0/60.0 // 3min, 2min, 1min
38 private static final int MAX_COORD_SEPARATION_INDEX = COORD_SEPARATIONS.length - 1;
42 * @param inTrack Track object
44 public PointScaler(Track inTrack)
56 DoubleRange latRange = new DoubleRange();
57 DoubleRange lonRange = new DoubleRange();
58 DoubleRange altRange = new DoubleRange();
61 DataPoint point = null;
62 // Find limits of data
63 if (_track != null && (numPoints = _track.getNumPoints()) > 0)
65 for (p=0; p<numPoints; p++)
67 point = _track.getPoint(p);
70 latRange.addValue(point.getLatitude().getDouble());
71 lonRange.addValue(point.getLongitude().getDouble());
72 altRange.addValue(point.getAltitude().getValue(Altitude.Format.METRES));
76 // Find median latitude and calculate factor
77 _latMedian = (latRange.getMinimum() + latRange.getMaximum()) / 2;
78 _lonMedian = (lonRange.getMinimum() + lonRange.getMaximum()) / 2;
79 _minAltitude = (int) altRange.getMinimum();
80 _longFactor = Math.cos(_latMedian / 180.0 * Math.PI); // quite rough
81 // Find altitude scale factor using distance
82 DataPoint p1 = new DataPoint(new Latitude(latRange.getMinimum(), Coordinate.FORMAT_DEG),
83 new Longitude(_lonMedian, Coordinate.FORMAT_DEG), null);
84 DataPoint p2 = new DataPoint(new Latitude(latRange.getMaximum(), Coordinate.FORMAT_DEG),
85 new Longitude(_lonMedian, Coordinate.FORMAT_DEG), null);
86 double horizDist = Distance.convertRadiansToDistance(
87 DataPoint.calculateRadiansBetween(p1, p2), UnitSetLibrary.UNITS_METRES); // both in m
88 _altFactor = 1.0 / horizDist;
90 // create new arrays for scaled values
91 if (_xValues == null || _xValues.length != numPoints)
93 _xValues = new double[numPoints];
94 _yValues = new double[numPoints];
95 _altValues = new double[numPoints];
97 // Calculate scaled values
98 for (p=0; p<numPoints; p++)
100 point = _track.getPoint(p);
103 _xValues[p] = getScaledLongitude(point.getLongitude().getDouble());
104 _yValues[p] = getScaledLatitude(point.getLatitude().getDouble());
105 _altValues[p] = getScaledAltitude(point.getAltitude());
106 if (_altValues[p] > _maxScaledAlt) {_maxScaledAlt = _altValues[p];}
109 // Calculate x and y range
110 _maxX = getScaledLongitude(lonRange.getMaximum());
111 _maxY = getScaledLatitude(latRange.getMaximum());
117 * @return maximum horiz value
119 public double getMaximumHoriz() { return _maxX; }
121 * @return maximum vert value
123 public double getMaximumVert() { return _maxY; }
125 /** @return maximum scaled altitude value */
126 public double getMaxScaledAlt() { return _maxScaledAlt; }
129 * Get the horizontal value for the specified point
130 * @param inIndex index of point, starting at 0
131 * @return scaled horizontal value
133 public double getHorizValue(int inIndex)
135 return _xValues[inIndex];
138 * Get the vertical value for the specified point
139 * @param inIndex index of point, starting at 0
140 * @return scaled vertical value
142 public double getVertValue(int inIndex)
144 return _yValues[inIndex];
147 * Get the altitude value for the specified point
148 * @param inIndex index of point, starting at 0
149 * @return scaled altitude value
151 public double getAltValue(int inIndex)
153 return _altValues[inIndex];
157 * Scale the given latitude value
158 * @param inLatitude latitude in degrees
159 * @return scaled latitude
161 private double getScaledLatitude(double inLatitude)
163 return inLatitude - _latMedian;
166 * Scale the given longitude value
167 * @param inLongitude longitude in degrees
168 * @return scaled longitude
170 private double getScaledLongitude(double inLongitude)
172 return (inLongitude - _lonMedian) * _longFactor;
175 * Scale the given altitude value
176 * @param inAltitude Altitude object
177 * @return scaled altitude
179 private double getScaledAltitude(Altitude inAltitude)
181 if (inAltitude == null) return -1;
182 return (inAltitude.getValue(Altitude.Format.METRES) - _minAltitude) * _altFactor;
186 * Unscale the given latitude value
187 * @param inScaledLatitude scaled latitude
188 * @return latitude in degrees
190 private double getUnscaledLatitude(double inScaledLatitude)
192 return inScaledLatitude + _latMedian;
195 * Unscale the given longitude value
196 * @param inScaledLongitude scaled longitude
197 * @return longitude in degrees
199 private double getUnscaledLongitude(double inScaledLongitude)
201 return inScaledLongitude / _longFactor + _lonMedian;
205 * Calculate the latitude and longitude lines
207 public void calculateLatLongLines()
209 double maxValue = getMaximumHoriz() > getMaximumVert() ?
210 getMaximumHoriz():getMaximumVert();
211 // calculate boundaries in degrees
212 double minLong = getUnscaledLongitude(-maxValue);
213 double maxLong = getUnscaledLongitude(maxValue);
214 double minLat = getUnscaledLatitude(-maxValue);
215 double maxLat = getUnscaledLatitude(maxValue);
216 // work out what line separation to use to give at least two lines
219 int numLatLines = 0, numLonLines = 0;
223 separation = COORD_SEPARATIONS[sepIndex];
224 numLatLines = getNumLinesBetween(minLat, maxLat, separation);
225 numLonLines = getNumLinesBetween(minLong, maxLong, separation);
227 while ((numLonLines <= 1 || numLatLines <= 1) && sepIndex < MAX_COORD_SEPARATION_INDEX);
228 // create lines based on this separation
229 _latLinesDegs = getLines(minLat, maxLat, separation, numLatLines);
230 _lonLinesDegs = getLines(minLong, maxLong, separation, numLonLines);
232 _latLinesScaled = new double[numLatLines];
233 for (int i=0; i<numLatLines; i++) _latLinesScaled[i] = getScaledLatitude(_latLinesDegs[i]);
234 _lonLinesScaled = new double[numLonLines];
235 for (int i=0; i<numLonLines; i++) _lonLinesScaled[i] = getScaledLongitude(_lonLinesDegs[i]);
240 * Calculate the number of lines in the given range using the specified separation
241 * @param inMin minimum value
242 * @param inMax maximum value
243 * @param inSeparation line separation
244 * @return number of lines
246 private static int getNumLinesBetween(double inMin, double inMax, double inSeparation)
248 // Start looking from round number of degrees below minimum
249 double value = (int) inMin;
250 if (inMin < 0.0) value = value - 1.0;
251 // Loop until bigger than maximum
253 while (value < inMax)
255 if (value >= inMin) numLines++;
256 value += inSeparation;
263 * Get the line values in the given range using the specified separation
264 * @param inMin minimum value
265 * @param inMax maximum value
266 * @param inSeparation line separation
267 * @param inCount number of lines already counted
268 * @return array of line values
270 private static double[] getLines(double inMin, double inMax, double inSeparation, int inCount)
272 double[] values = new double[inCount];
273 // Start looking from round number of degrees below minimum
274 double value = (int) inMin;
275 if (inMin < 0.0) value = value - 1.0;
276 // Loop until bigger than maximum
278 while (value < inMax)
282 values[numLines] = value;
285 value += inSeparation;
291 * @return array of latitude lines in degrees
293 public double[] getLatitudeLines()
295 return _latLinesDegs;
298 * @return array of longitude lines in degrees
300 public double[] getLongitudeLines()
302 return _lonLinesDegs;
305 * @return array of latitude lines in scaled units
307 public double[] getScaledLatitudeLines()
309 return _latLinesScaled;
312 * @return array of longitude lines in scaled units
314 public double[] getScaledLongitudeLines()
316 return _lonLinesScaled;