File: PointScaler.java

package info (click to toggle)
gpsprune 10-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 2,220 kB
  • ctags: 3,013
  • sloc: java: 22,662; sh: 23; makefile: 16; python: 15
file content (315 lines) | stat: -rw-r--r-- 8,443 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
package tim.prune.data;

/**
 * Class to manage the scaling of points
 */
public class PointScaler
{
	// Original data
	private Track _track = null;
	// Range information
	private AltitudeRange _altRange = null;
	private DoubleRange _latRange = null;
	private DoubleRange _lonRange = null;
	private double _latMedian = 0.0;
	private double _lonMedian = 0.0;
	private int _minAltitude = 0;
	private int _maxAltitude = 0;
	// Scaling information
	private double _longFactor = 0.0;
	// Scaled points
	private double[] _xValues = null;
	private double[] _yValues = null;
	private int[] _altValues = null;
	private double _maxX = 0.0;
	private double _maxY = 0.0;
	// lat/long lines
	private double[] _latLinesDegs = null;
	private double[] _lonLinesDegs = null;
	private double[] _latLinesScaled = null;
	private double[] _lonLinesScaled = null;

	// Constants
	private static final double[] COORD_SEPARATIONS = {
		1.0,                      // 1deg
		30.0/60.0, 20.0/60.0,     // 30min, 20min
		10.0/60.0, 5.0/60.0,      // 10min, 5min
		3.0/60.0, 2.0/60.0, 1.0/60.0   // 3min, 2min, 1min
	};
	private static final int MAX_COORD_SEPARATION_INDEX = COORD_SEPARATIONS.length - 1;

	/**
	 * Constructor
	 * @param inTrack Track object
	 */
	public PointScaler(Track inTrack)
	{
		_track = inTrack;
		_altRange = new AltitudeRange();
		_latRange = new DoubleRange();
		_lonRange = new DoubleRange();
	}


	/**
	 * Scale the points
	 */
	public void scale()
	{
		// Clear data
		_altRange.clear();
		_latRange.clear();
		_lonRange.clear();
		int numPoints = 0;
		int p = 0;
		DataPoint point = null;
		// Find limits of data
		if (_track != null && (numPoints = _track.getNumPoints()) > 0)
		{
			for (p=0; p<numPoints; p++)
			{
				point = _track.getPoint(p);
				if (point != null)
				{
					_latRange.addValue(point.getLatitude().getDouble());
					_lonRange.addValue(point.getLongitude().getDouble());
					_altRange.addValue(point.getAltitude());
				}
			}

			// Find median latitude and calculate factor
			_latMedian = (_latRange.getMinimum() + _latRange.getMaximum()) / 2;
			_lonMedian = (_lonRange.getMinimum() + _lonRange.getMaximum()) / 2;
			_minAltitude = _altRange.getMinimum();
			_longFactor = Math.cos(_latMedian / 180.0 * Math.PI); // quite rough

			// create new arrays for scaled values
			if (_xValues == null || _xValues.length != numPoints)
			{
				_xValues = new double[numPoints];
				_yValues = new double[numPoints];
				_altValues = new int[numPoints];
			}
			// Calculate scaled values
			for (p=0; p<numPoints; p++)
			{
				point = _track.getPoint(p);
				if (point != null)
				{
					_xValues[p] = getScaledLongitude(point.getLongitude().getDouble());
					_yValues[p] = getScaledLatitude(point.getLatitude().getDouble());
					_altValues[p] = getScaledAltitude(point.getAltitude());
				}
			}
			// Calculate x and y range
			_maxX = getScaledLongitude(_lonRange.getMaximum());
			_maxY = getScaledLatitude(_latRange.getMaximum());
			_maxAltitude = _altRange.getMaximum() - _altRange.getMinimum();
		}
	}


	/**
	 * @return maximum horiz value
	 */
	public double getMaximumHoriz() { return _maxX; }
	/**
	 * @return maximum vert value
	 */
	public double getMaximumVert() { return _maxY; }
	/**
	 * @return maximum alt value
	 */
	public int getMaximumAlt() { return _maxAltitude; }

	/**
	 * Get the horizontal value for the specified point
	 * @param inIndex index of point, starting at 0
	 * @return scaled horizontal value
	 */
	public double getHorizValue(int inIndex)
	{
		return _xValues[inIndex];
	}
	/**
	 * Get the vertical value for the specified point
	 * @param inIndex index of point, starting at 0
	 * @return scaled vertical value
	 */
	public double getVertValue(int inIndex)
	{
		return _yValues[inIndex];
	}
	/**
	 * Get the altitude value for the specified point
	 * @param inIndex index of point, starting at 0
	 * @return scaled altitude value
	 */
	public int getAltValue(int inIndex)
	{
		return _altValues[inIndex];
	}

	/**
	 * Scale the given latitude value
	 * @param inLatitude latitude in degrees
	 * @return scaled latitude
	 */
	public double getScaledLatitude(double inLatitude)
	{
		return inLatitude - _latMedian;
	}
	/**
	 * Scale the given longitude value
	 * @param inLongitude longitude in degrees
	 * @return scaled longitude
	 */
	public double getScaledLongitude(double inLongitude)
	{
		return (inLongitude - _lonMedian) * _longFactor;
	}
	/**
	 * Scale the given altitude value
	 * @param inAltitude Altitude object
	 * @return scaled altitude
	 */
	public int getScaledAltitude(Altitude inAltitude)
	{
		if (inAltitude == null) return -1;
		return inAltitude.getValue(_altRange.getFormat()) - _minAltitude;
	}

	/**
	 * Unscale the given latitude value
	 * @param inScaledLatitude scaled latitude
	 * @return latitude in degrees
	 */
	public double getUnscaledLatitude(double inScaledLatitude)
	{
		return inScaledLatitude + _latMedian;
	}
	/**
	 * Unscale the given longitude value
	 * @param inScaledLongitude scaled longitude
	 * @return longitude in degrees
	 */
	public double getUnscaledLongitude(double inScaledLongitude)
	{
		return inScaledLongitude / _longFactor + _lonMedian;
	}

	/**
	 * Calculate the latitude and longitude lines
	 */
	public void calculateLatLongLines()
	{
		double maxValue = getMaximumHoriz() > getMaximumVert() ?
			getMaximumHoriz():getMaximumVert();
		// calculate boundaries in degrees
		double minLong = getUnscaledLongitude(-maxValue);
		double maxLong = getUnscaledLongitude(maxValue);
		double minLat = getUnscaledLatitude(-maxValue);
		double maxLat = getUnscaledLatitude(maxValue);
		// work out what line separation to use to give at least two lines
		int sepIndex = -1;
		double separation;
		int numLatLines = 0, numLonLines = 0;
		do
		{
			sepIndex++;
			separation = COORD_SEPARATIONS[sepIndex];
			numLatLines = getNumLinesBetween(minLat, maxLat, separation);
			numLonLines = getNumLinesBetween(minLong, maxLong, separation);
		}
		while ((numLonLines <= 1 || numLatLines <= 1) && sepIndex < MAX_COORD_SEPARATION_INDEX);
		// create lines based on this separation
		_latLinesDegs = getLines(minLat, maxLat, separation, numLatLines);
		_lonLinesDegs = getLines(minLong, maxLong, separation, numLonLines);
		// scale lines also
		_latLinesScaled = new double[numLatLines];
		for (int i=0; i<numLatLines; i++) _latLinesScaled[i] = getScaledLatitude(_latLinesDegs[i]);
		_lonLinesScaled = new double[numLonLines];
		for (int i=0; i<numLonLines; i++) _lonLinesScaled[i] = getScaledLongitude(_lonLinesDegs[i]);
	}


	/**
	 * Calculate the number of lines in the given range using the specified separation
	 * @param inMin minimum value
	 * @param inMax maximum value
	 * @param inSeparation line separation
	 * @return number of lines
	 */
	private static int getNumLinesBetween(double inMin, double inMax, double inSeparation)
	{
		// Start looking from round number of degrees below minimum
		double value = (int) inMin;
		if (inMin < 0.0) value = value - 1.0;
		// Loop until bigger than maximum
		int numLines = 0;
		while (value < inMax)
		{
			if (value >= inMin) numLines++;
			value += inSeparation;
		}
		return numLines;
	}


	/**
	 * Get the line values in the given range using the specified separation
	 * @param inMin minimum value
	 * @param inMax maximum value
	 * @param inSeparation line separation
	 * @param inCount number of lines already counted
	 * @return array of line values
	 */
	private static double[] getLines(double inMin, double inMax, double inSeparation, int inCount)
	{
		double[] values = new double[inCount];
		// Start looking from round number of degrees below minimum
		double value = (int) inMin;
		if (inMin < 0.0) value = value - 1.0;
		// Loop until bigger than maximum
		int numLines = 0;
		while (value < inMax)
		{
			if (value >= inMin)
			{
				values[numLines] = value;
				numLines++;
			}
			value += inSeparation;
		}
		return values;
	}

	/**
	 * @return array of latitude lines in degrees
	 */
	public double[] getLatitudeLines()
	{
		return _latLinesDegs;
	}
	/**
	 * @return array of longitude lines in degrees
	 */
	public double[] getLongitudeLines()
	{
		return _lonLinesDegs;
	}
	/**
	 * @return array of latitude lines in scaled units
	 */
	public double[] getScaledLatitudeLines()
	{
		return _latLinesScaled;
	}
	/**
	 * @return array of longitude lines in scaled units
	 */
	public double[] getScaledLongitudeLines()
	{
		return _lonLinesScaled;
	}
}