]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/threedee/ThreeDModel.java
Version 2, March 2007
[GpsPrune.git] / tim / prune / threedee / ThreeDModel.java
1 package tim.prune.threedee;
2
3 import tim.prune.data.Altitude;
4 import tim.prune.data.DataPoint;
5 import tim.prune.data.PointScaler;
6 import tim.prune.data.Track;
7
8 /**
9  * Class to hold a 3d model of the track data,
10  * including all points and scaling operations.
11  * Used by java3d and also Pov export functions
12  */
13 public class ThreeDModel
14 {
15         private Track _track = null;
16         private PointScaler _scaler = null;
17         private double _modelSize;
18         private int _altitudeCap = -1;
19         private double _scaleFactor = 1.0;
20         private double _altFactor = 1.0;
21         // TODO: How to store rods (lifts) in data?
22         private byte[] _pointTypes = null;
23         private byte[] _pointHeights = null;
24
25         private static final double DEFAULT_MODEL_SIZE = 10.0;
26         public static final int MINIMUM_ALTITUDE_CAP = 100;
27
28         // Constants for point types
29         public static final byte POINT_TYPE_WAYPOINT = 1;
30         public static final byte POINT_TYPE_NORMAL_POINT = 2;
31
32
33         /**
34          * Constructor
35          * @param inTrack Track object
36          */
37         public ThreeDModel(Track inTrack)
38         {
39                 this(inTrack, DEFAULT_MODEL_SIZE);
40         }
41
42
43         /**
44          * Constructor
45          * @param inTrack Track object
46          * @param inSize model size
47          */
48         public ThreeDModel(Track inTrack, double inSize)
49         {
50                 _track = inTrack;
51                 _modelSize = inSize;
52                 if (_modelSize <= 0.0) _modelSize = DEFAULT_MODEL_SIZE;
53         }
54
55
56         /**
57          * @return the number of points in the model
58          */
59         public int getNumPoints()
60         {
61                 if (_track == null) return 0;
62                 return _track.getNumPoints();
63         }
64
65
66         /**
67          * Set the altitude cap
68          * @param inAltitudeCap altitude range to cap to (ignored if less than data range)
69          */
70         public void setAltitudeCap(int inAltitudeCap)
71         {
72                 _altitudeCap = inAltitudeCap;
73                 if (_altitudeCap < MINIMUM_ALTITUDE_CAP)
74                 {
75                         _altitudeCap = MINIMUM_ALTITUDE_CAP;
76                 }
77         }
78
79
80         /**
81          * Scale all points and calculate factors
82          */
83         public void scale()
84         {
85                 // Use PointScaler to sort out x and y values
86                 _scaler = new PointScaler(_track);
87                 _scaler.scale();
88                 // Calculate scale factor to fit within box
89                 _scaleFactor = 1.0;
90                 if (_scaler.getMaximumHoriz() > 0.0 || _scaler.getMaximumVert() > 0.0)
91                 {
92                         if (_scaler.getMaximumHoriz() > _scaler.getMaximumVert())
93                         {
94                                 // scale limited by longitude
95                                 _scaleFactor = _modelSize / _scaler.getMaximumHoriz();
96                         }
97                         else
98                         {
99                                 // scale limited by latitude
100                                 _scaleFactor = _modelSize / _scaler.getMaximumVert();
101                         }
102                 }
103                 // calculate altitude scale factor
104                 _altFactor = 1.0;
105                 if (_scaler.getMaximumAlt() >= 0)
106                 {
107                         // limit by altitude cap or by data range?
108                         if (_scaler.getMaximumAlt() > _altitudeCap)
109                         {
110                                 // data is bigger than cap
111                                 _altFactor = _modelSize / _scaler.getMaximumAlt();
112                         }
113                         else
114                         {
115                                 // capped
116                                 _altFactor = _modelSize / _altitudeCap;
117                         }
118                 }
119                 // calculate lat/long lines
120                 _scaler.calculateLatLongLines();
121
122                 // calculate point types and height codes
123                 calculatePointTypes();
124         }
125
126
127         /**
128          * Calculate the point types and height codes
129          */
130         private void calculatePointTypes()
131         {
132                 int numPoints = getNumPoints();
133                 _pointTypes = new byte[numPoints];
134                 _pointHeights = new byte[numPoints];
135                 // Loop over points in track
136                 for (int i=0; i<numPoints; i++)
137                 {
138                         DataPoint point = _track.getPoint(i);
139                         _pointTypes[i] = (point.isWaypoint()?POINT_TYPE_WAYPOINT:POINT_TYPE_NORMAL_POINT);
140                         _pointHeights[i] = (byte) (point.getAltitude().getValue(Altitude.FORMAT_METRES) / 500);
141                 }
142         }
143
144
145         /**
146          * Get the scaled horizontal value for the specified point
147          * @param inIndex index of point
148          * @return scaled horizontal value
149          */
150         public double getScaledHorizValue(int inIndex)
151         {
152                 return _scaler.getHorizValue(inIndex) * _scaleFactor;
153         }
154
155         /**
156          * Get the scaled vertical value for the specified point
157          * @param inIndex index of point
158          * @return scaled vertical value
159          */
160         public double getScaledVertValue(int inIndex)
161         {
162                 return _scaler.getVertValue(inIndex) * _scaleFactor;
163         }
164
165         /**
166          * Get the scaled altitude value for the specified point
167          * @param inIndex index of point
168          * @return scaled altitude value
169          */
170         public double getScaledAltValue(int inIndex)
171         {
172                 // if no altitude, just return 0
173                 int altVal = _scaler.getAltValue(inIndex);
174                 if (altVal < 0) return 0;
175                 // scale according to altitude cap
176                 return altVal * _altFactor;
177         }
178
179
180         /**
181          * @return number of latitude lines
182          */
183         public int getNumLatitudeLines()
184         {
185                 return _scaler.getLatitudeLines().length;
186         }
187
188         /**
189          * @param inIndex index of line, starting at 0
190          * @return scaled position of latitude line
191          */
192         public double getScaledLatitudeLine(int inIndex)
193         {
194                 return _scaler.getScaledLatitudeLines()[inIndex] * _scaleFactor;
195         }
196
197         /**
198          * @return number of longitude lines
199          */
200         public int getNumLongitudeLines()
201         {
202                 return _scaler.getLongitudeLines().length;
203         }
204
205         /**
206          * @param inIndex index of line, starting at 0
207          * @return scaled position of longitude line
208          */
209         public double getScaledLongitudeLine(int inIndex)
210         {
211                 return _scaler.getScaledLongitudeLines()[inIndex] * _scaleFactor;
212         }
213
214         /**
215          * @param inIndex index of point, starting at 0
216          * @return point type, either POINT_TYPE_WAYPOINT or POINT_TYPE_NORMAL_POINT
217          */
218         public byte getPointType(int inIndex)
219         {
220                 return _pointTypes[inIndex];
221         }
222
223         /**
224          * @param inIndex index of point, starting at 0
225          * @return point height code
226          */
227         public byte getPointHeightCode(int inIndex)
228         {
229                 return _pointHeights[inIndex];
230         }
231
232         /**
233          * @return the current model size
234          */
235         public double getModelSize()
236         {
237                 return _modelSize;
238         }
239 }