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 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; // 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(); } /** * @param inFactor altitude exaggeration factor (default 1.0) */ public void setAltitudeFactor(double inFactor) { if (inFactor >= 1.0) { _altFactor = inFactor; } } /** * 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(); } } // cap altitude scale factor if it's too big double maxScaledAlt = _scaler.getMaxScaledAlt() * _altFactor; if (maxScaledAlt > _modelSize) { // capped _altFactor = _altFactor * _modelSize / maxScaledAlt; } // 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