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