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;
}
}
|