File: ThreeDModel.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 (241 lines) | stat: -rw-r--r-- 5,539 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
package tim.prune.threedee;

import tim.prune.data.Altitude;
import tim.prune.data.DataPoint;
import tim.prune.data.PointScaler;
import tim.prune.data.Track;

/**
 * Class to hold a 3d model of the track data,
 * including all points and scaling operations.
 * Used by java3d and also Pov export functions
 */
public class ThreeDModel
{
	private Track _track = null;
	private PointScaler _scaler = null;
	private double _modelSize;
	private int _altitudeCap = -1;
	private double _scaleFactor = 1.0;
	private double _altFactor = 1.0;
	// MAYBE: How to store rods (lifts) in data?
	private byte[] _pointTypes = null;
	private byte[] _pointHeights = null;

	private static final double DEFAULT_MODEL_SIZE = 10.0;
	/** Minimum altitude cap */
	public static final int MINIMUM_ALTITUDE_CAP = 100;

	// Constants for point types
	public static final byte POINT_TYPE_WAYPOINT      = 1;
	public static final byte POINT_TYPE_NORMAL_POINT  = 2;
	public static final byte POINT_TYPE_SEGMENT_START = 3;


	/**
	 * Constructor
	 * @param inTrack Track object
	 */
	public ThreeDModel(Track inTrack)
	{
		this(inTrack, DEFAULT_MODEL_SIZE);
	}


	/**
	 * Constructor
	 * @param inTrack Track object
	 * @param inSize model size
	 */
	public ThreeDModel(Track inTrack, double inSize)
	{
		_track = inTrack;
		_modelSize = inSize;
		if (_modelSize <= 0.0) _modelSize = DEFAULT_MODEL_SIZE;
	}


	/**
	 * @return the number of points in the model
	 */
	public int getNumPoints()
	{
		if (_track == null) return 0;
		return _track.getNumPoints();
	}


	/**
	 * Set the altitude cap
	 * @param inAltitudeCap altitude range to cap to (ignored if less than data range)
	 */
	public void setAltitudeCap(int inAltitudeCap)
	{
		_altitudeCap = inAltitudeCap;
		if (_altitudeCap < MINIMUM_ALTITUDE_CAP)
		{
			_altitudeCap = MINIMUM_ALTITUDE_CAP;
		}
	}


	/**
	 * Scale all points and calculate factors
	 */
	public void scale()
	{
		// Use PointScaler to sort out x and y values
		_scaler = new PointScaler(_track);
		_scaler.scale();
		// Calculate scale factor to fit within box
		_scaleFactor = 1.0;
		if (_scaler.getMaximumHoriz() > 0.0 || _scaler.getMaximumVert() > 0.0)
		{
			if (_scaler.getMaximumHoriz() > _scaler.getMaximumVert())
			{
				// scale limited by longitude
				_scaleFactor = _modelSize / _scaler.getMaximumHoriz();
			}
			else
			{
				// scale limited by latitude
				_scaleFactor = _modelSize / _scaler.getMaximumVert();
			}
		}
		// calculate altitude scale factor
		_altFactor = 1.0;
		if (_scaler.getMaximumAlt() >= 0)
		{
			// limit by altitude cap or by data range?
			if (_scaler.getMaximumAlt() > _altitudeCap)
			{
				// data is bigger than cap
				_altFactor = _modelSize / _scaler.getMaximumAlt();
			}
			else
			{
				// capped
				_altFactor = _modelSize / _altitudeCap;
			}
		}
		// calculate lat/long lines
		_scaler.calculateLatLongLines();

		// calculate point types and height codes
		calculatePointTypes();
	}


	/**
	 * Calculate the point types and height codes
	 */
	private void calculatePointTypes()
	{
		int numPoints = getNumPoints();
		_pointTypes = new byte[numPoints];
		_pointHeights = new byte[numPoints];
		// Loop over points in track
		for (int i=0; i<numPoints; i++)
		{
			DataPoint point = _track.getPoint(i);
			_pointTypes[i] = (point.isWaypoint()?POINT_TYPE_WAYPOINT:(point.getSegmentStart()?POINT_TYPE_SEGMENT_START:POINT_TYPE_NORMAL_POINT));
			_pointHeights[i] = (byte) (point.getAltitude().getValue(Altitude.Format.METRES) / 500);
		}
	}


	/**
	 * Get the scaled horizontal value for the specified point
	 * @param inIndex index of point
	 * @return scaled horizontal value
	 */
	public double getScaledHorizValue(int inIndex)
	{
		return _scaler.getHorizValue(inIndex) * _scaleFactor;
	}

	/**
	 * Get the scaled vertical value for the specified point
	 * @param inIndex index of point
	 * @return scaled vertical value
	 */
	public double getScaledVertValue(int inIndex)
	{
		return _scaler.getVertValue(inIndex) * _scaleFactor;
	}

	/**
	 * Get the scaled altitude value for the specified point
	 * @param inIndex index of point
	 * @return scaled altitude value
	 */
	public double getScaledAltValue(int inIndex)
	{
		// if no altitude, just return 0
		int altVal = _scaler.getAltValue(inIndex);
		if (altVal < 0) return 0;
		// scale according to altitude cap
		return altVal * _altFactor;
	}


	/**
	 * @return latitude lines
	 */
	public double[] getLatitudeLines()
	{
		return _scaler.getLatitudeLines();
	}

	/**
	 * @param inIndex index of line, starting at 0
	 * @return scaled position of latitude line
	 */
	public double getScaledLatitudeLine(int inIndex)
	{
		return _scaler.getScaledLatitudeLines()[inIndex] * _scaleFactor;
	}

	/**
	 * @return longitude lines
	 */
	public double[] getLongitudeLines()
	{
		return _scaler.getLongitudeLines();
	}

	/**
	 * @param inIndex index of line, starting at 0
	 * @return scaled position of longitude line
	 */
	public double getScaledLongitudeLine(int inIndex)
	{
		return _scaler.getScaledLongitudeLines()[inIndex] * _scaleFactor;
	}

	/**
	 * @param inIndex index of point, starting at 0
	 * @return point type, either POINT_TYPE_WAYPOINT or POINT_TYPE_NORMAL_POINT
	 */
	public byte getPointType(int inIndex)
	{
		return _pointTypes[inIndex];
	}

	/**
	 * @param inIndex index of point, starting at 0
	 * @return point height code
	 */
	public byte getPointHeightCode(int inIndex)
	{
		return _pointHeights[inIndex];
	}

	/**
	 * @return the current model size
	 */
	public double getModelSize()
	{
		return _modelSize;
	}
}