]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/data/PointScaler.java
4d2290f0b5e0f6b26f9dea13850efcf9d9db585d
[GpsPrune.git] / tim / prune / data / PointScaler.java
1 package tim.prune.data;
2
3 /**
4  * Class to manage the scaling of points
5  */
6 public class PointScaler
7 {
8         // Original data
9         private Track _track = null;
10         // Range information
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;
20         // Scaled points
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;
26         // lat/long lines
27         private double[] _latLinesDegs = null;
28         private double[] _lonLinesDegs = null;
29         private double[] _latLinesScaled = null;
30         private double[] _lonLinesScaled = null;
31
32         // Constants
33         private static final double[] COORD_SEPARATIONS = {
34                 1.0,                      // 1deg
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
38         };
39         private static final int MAX_COORD_SEPARATION_INDEX = COORD_SEPARATIONS.length - 1;
40
41         /**
42          * Constructor
43          * @param inTrack Track object
44          */
45         public PointScaler(Track inTrack)
46         {
47                 _track = inTrack;
48                 _altRange = new AltitudeRange();
49                 _latRange = new DoubleRange();
50                 _lonRange = new DoubleRange();
51         }
52
53
54         /**
55          * Scale the points
56          */
57         public void scale()
58         {
59                 // Clear data
60                 _altRange.clear();
61                 _latRange.clear();
62                 _lonRange.clear();
63                 int numPoints = 0;
64                 int p = 0;
65                 DataPoint point = null;
66                 // Find limits of data
67                 if (_track != null && (numPoints = _track.getNumPoints()) > 0)
68                 {
69                         for (p=0; p<numPoints; p++)
70                         {
71                                 point = _track.getPoint(p);
72                                 if (point != null)
73                                 {
74                                         _latRange.addValue(point.getLatitude().getDouble());
75                                         _lonRange.addValue(point.getLongitude().getDouble());
76                                         _altRange.addValue(point.getAltitude());
77                                 }
78                         }
79
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
85
86                         // create new arrays for scaled values
87                         if (_xValues == null || _xValues.length != numPoints)
88                         {
89                                 _xValues = new double[numPoints];
90                                 _yValues = new double[numPoints];
91                                 _altValues = new int[numPoints];
92                         }
93                         // Calculate scaled values
94                         for (p=0; p<numPoints; p++)
95                         {
96                                 point = _track.getPoint(p);
97                                 if (point != null)
98                                 {
99                                         _xValues[p] = getScaledLongitude(point.getLongitude().getDouble());
100                                         _yValues[p] = getScaledLatitude(point.getLatitude().getDouble());
101                                         _altValues[p] = getScaledAltitude(point.getAltitude());
102                                 }
103                         }
104                         // Calculate x and y range
105                         _maxX = getScaledLongitude(_lonRange.getMaximum());
106                         _maxY = getScaledLatitude(_latRange.getMaximum());
107                         _maxAltitude = _altRange.getMaximum() - _altRange.getMinimum();
108                 }
109         }
110
111
112         /**
113          * @return maximum horiz value
114          */
115         public double getMaximumHoriz() { return _maxX; }
116         /**
117          * @return maximum vert value
118          */
119         public double getMaximumVert() { return _maxY; }
120         /**
121          * @return maximum alt value
122          */
123         public int getMaximumAlt() { return _maxAltitude; }
124
125         /**
126          * Get the horizontal value for the specified point
127          * @param inIndex index of point, starting at 0
128          * @return scaled horizontal value
129          */
130         public double getHorizValue(int inIndex)
131         {
132                 return _xValues[inIndex];
133         }
134         /**
135          * Get the vertical value for the specified point
136          * @param inIndex index of point, starting at 0
137          * @return scaled vertical value
138          */
139         public double getVertValue(int inIndex)
140         {
141                 return _yValues[inIndex];
142         }
143         /**
144          * Get the altitude value for the specified point
145          * @param inIndex index of point, starting at 0
146          * @return scaled altitude value
147          */
148         public int getAltValue(int inIndex)
149         {
150                 return _altValues[inIndex];
151         }
152
153         /**
154          * Scale the given latitude value
155          * @param inLatitude latitude in degrees
156          * @return scaled latitude
157          */
158         public double getScaledLatitude(double inLatitude)
159         {
160                 return inLatitude - _latMedian;
161         }
162         /**
163          * Scale the given longitude value
164          * @param inLongitude longitude in degrees
165          * @return scaled longitude
166          */
167         public double getScaledLongitude(double inLongitude)
168         {
169                 return (inLongitude - _lonMedian) * _longFactor;
170         }
171         /**
172          * Scale the given altitude value
173          * @param inAltitude Altitude object
174          * @return scaled altitude
175          */
176         public int getScaledAltitude(Altitude inAltitude)
177         {
178                 if (inAltitude == null) return -1;
179                 return inAltitude.getValue(_altRange.getFormat()) - _minAltitude;
180         }
181
182         /**
183          * Unscale the given latitude value
184          * @param inScaledLatitude scaled latitude
185          * @return latitude in degrees
186          */
187         public double getUnscaledLatitude(double inScaledLatitude)
188         {
189                 return inScaledLatitude + _latMedian;
190         }
191         /**
192          * Unscale the given longitude value
193          * @param inScaledLongitude scaled longitude
194          * @return longitude in degrees
195          */
196         public double getUnscaledLongitude(double inScaledLongitude)
197         {
198                 return inScaledLongitude / _longFactor + _lonMedian;
199         }
200
201         /**
202          * Calculate the latitude and longitude lines
203          */
204         public void calculateLatLongLines()
205         {
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
214                 int sepIndex = -1;
215                 double separation;
216                 int numLatLines = 0, numLonLines = 0;
217                 do
218                 {
219                         sepIndex++;
220                         separation = COORD_SEPARATIONS[sepIndex];
221                         numLatLines = getNumLinesBetween(minLat, maxLat, separation);
222                         numLonLines = getNumLinesBetween(minLong, maxLong, separation);
223                 }
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);
228                 // scale lines also
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]);
233         }
234
235
236         /**
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
242          */
243         private static int getNumLinesBetween(double inMin, double inMax, double inSeparation)
244         {
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
249                 int numLines = 0;
250                 while (value < inMax)
251                 {
252                         if (value >= inMin) numLines++;
253                         value += inSeparation;
254                 }
255                 return numLines;
256         }
257
258
259         /**
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
266          */
267         private static double[] getLines(double inMin, double inMax, double inSeparation, int inCount)
268         {
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
274                 int numLines = 0;
275                 while (value < inMax)
276                 {
277                         if (value >= inMin)
278                         {
279                                 values[numLines] = value;
280                                 numLines++;
281                         }
282                         value += inSeparation;
283                 }
284                 return values;
285         }
286
287         /**
288          * @return array of latitude lines in degrees
289          */
290         public double[] getLatitudeLines()
291         {
292                 return _latLinesDegs;
293         }
294         /**
295          * @return array of longitude lines in degrees
296          */
297         public double[] getLongitudeLines()
298         {
299                 return _lonLinesDegs;
300         }
301         /**
302          * @return array of latitude lines in scaled units
303          */
304         public double[] getScaledLatitudeLines()
305         {
306                 return _latLinesScaled;
307         }
308         /**
309          * @return array of longitude lines in scaled units
310          */
311         public double[] getScaledLongitudeLines()
312         {
313                 return _lonLinesScaled;
314         }
315 }