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