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