]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/data/PointScaler.java
Version 16, February 2014
[GpsPrune.git] / tim / prune / data / PointScaler.java
index 4d2290f0b5e0f6b26f9dea13850efcf9d9db585d..446c0a204758b0b9c940d6462b8f686aad6030ee 100644 (file)
@@ -1,42 +1,28 @@
 package tim.prune.data;
 
 /**
- * Class to manage the scaling of points
+ * Class to manage the scaling of points, used by the ThreeDModel
  */
 public class PointScaler
 {
-       // Original data
+       /** Original data */
        private Track _track = null;
-       // Range information
-       private AltitudeRange _altRange = null;
-       private DoubleRange _latRange = null;
-       private DoubleRange _lonRange = null;
-       private double _latMedian = 0.0;
-       private double _lonMedian = 0.0;
-       private int _minAltitude = 0;
-       private int _maxAltitude = 0;
-       // Scaling information
-       private double _longFactor = 0.0;
-       // Scaled points
+       /** Secondary data for terrain grid */
+       private Track _terrainTrack = null;
+       // Scaled values for data track
        private double[] _xValues = null;
        private double[] _yValues = null;
-       private int[] _altValues = null;
-       private double _maxX = 0.0;
-       private double _maxY = 0.0;
-       // lat/long lines
-       private double[] _latLinesDegs = null;
-       private double[] _lonLinesDegs = null;
-       private double[] _latLinesScaled = null;
-       private double[] _lonLinesScaled = null;
+       private double[] _altValues = null;
+       // Scaled values for terrain track, if any
+       private double[] _terrainxValues = null;
+       private double[] _terrainyValues = null;
+       private double[] _terrainAltValues = null;
+       // Altitude range
+       private double _altitudeRange = 0.0;
+       private double _minAltitudeMetres = 0.0;
+       // Horizontal distance
+       private double _horizDistanceMetres = 0.0;
 
-       // Constants
-       private static final double[] COORD_SEPARATIONS = {
-               1.0,                      // 1deg
-               30.0/60.0, 20.0/60.0,     // 30min, 20min
-               10.0/60.0, 5.0/60.0,      // 10min, 5min
-               3.0/60.0, 2.0/60.0, 1.0/60.0   // 3min, 2min, 1min
-       };
-       private static final int MAX_COORD_SEPARATION_INDEX = COORD_SEPARATIONS.length - 1;
 
        /**
         * Constructor
@@ -45,82 +31,76 @@ public class PointScaler
        public PointScaler(Track inTrack)
        {
                _track = inTrack;
-               _altRange = new AltitudeRange();
-               _latRange = new DoubleRange();
-               _lonRange = new DoubleRange();
        }
 
+       /**
+        * @param inTrack terrain track to add
+        */
+       public void addTerrain(Track inTrack)
+       {
+               _terrainTrack = inTrack;
+       }
 
        /**
         * Scale the points
         */
        public void scale()
        {
-               // Clear data
-               _altRange.clear();
-               _latRange.clear();
-               _lonRange.clear();
-               int numPoints = 0;
-               int p = 0;
-               DataPoint point = null;
-               // Find limits of data
-               if (_track != null && (numPoints = _track.getNumPoints()) > 0)
+               // Work out extents
+               TrackExtents extents = new TrackExtents(_track);
+               extents.applySquareBorder();
+               _horizDistanceMetres = Math.max(extents.getHorizontalDistanceMetres(), 1.0);
+               final int numPoints = _track.getNumPoints();
+
+               // Find altitude range (including terrain)
+               DoubleRange altRangeMetres = extents.getAltitudeRange();
+               if (_terrainTrack != null) {
+                       altRangeMetres.combine(new TrackExtents(_terrainTrack).getAltitudeRange());
+               }
+               _altitudeRange = altRangeMetres.getRange() / _horizDistanceMetres;
+               _minAltitudeMetres = altRangeMetres.getMinimum();
+
+               // create new arrays for scaled values
+               if (_xValues == null || _xValues.length != numPoints)
                {
-                       for (p=0; p<numPoints; p++)
+                       _xValues = new double[numPoints];
+                       _yValues = new double[numPoints];
+                       _altValues = new double[numPoints];
+                       if (_terrainTrack != null)
                        {
-                               point = _track.getPoint(p);
-                               if (point != null)
-                               {
-                                       _latRange.addValue(point.getLatitude().getDouble());
-                                       _lonRange.addValue(point.getLongitude().getDouble());
-                                       _altRange.addValue(point.getAltitude());
-                               }
+                               _terrainxValues = new double[_terrainTrack.getNumPoints()];
+                               _terrainyValues = new double[_terrainTrack.getNumPoints()];
+                               _terrainAltValues = new double[_terrainTrack.getNumPoints()];
                        }
+               }
 
-                       // Find median latitude and calculate factor
-                       _latMedian = (_latRange.getMinimum() + _latRange.getMaximum()) / 2;
-                       _lonMedian = (_lonRange.getMinimum() + _lonRange.getMaximum()) / 2;
-                       _minAltitude = _altRange.getMinimum();
-                       _longFactor = Math.cos(_latMedian / 180.0 * Math.PI); // quite rough
+               final double midXvalue = extents.getXRange().getMidValue();
+               final double midYvalue = extents.getYRange().getMidValue();
+               final double xyRange   = extents.getXRange().getRange();
 
-                       // create new arrays for scaled values
-                       if (_xValues == null || _xValues.length != numPoints)
+               // Calculate scaled values
+               for (int p=0; p<numPoints; p++)
+               {
+                       DataPoint point = _track.getPoint(p);
+                       if (point != null)
                        {
-                               _xValues = new double[numPoints];
-                               _yValues = new double[numPoints];
-                               _altValues = new int[numPoints];
+                               _xValues[p] = (_track.getX(p) - midXvalue) / xyRange;
+                               _yValues[p] = (midYvalue - _track.getY(p)) / xyRange; // y values have to be inverted
+                               _altValues[p] = (point.getAltitude().getMetricValue() - _minAltitudeMetres) / _horizDistanceMetres;
                        }
-                       // Calculate scaled values
-                       for (p=0; p<numPoints; p++)
+               }
+               if (_terrainTrack != null)
+               {
+                       for (int p=0; p<_terrainTrack.getNumPoints(); p++)
                        {
-                               point = _track.getPoint(p);
-                               if (point != null)
-                               {
-                                       _xValues[p] = getScaledLongitude(point.getLongitude().getDouble());
-                                       _yValues[p] = getScaledLatitude(point.getLatitude().getDouble());
-                                       _altValues[p] = getScaledAltitude(point.getAltitude());
-                               }
+                               _terrainxValues[p] = (_terrainTrack.getX(p) - midXvalue) / xyRange;
+                               _terrainyValues[p] = (midYvalue - _terrainTrack.getY(p)) / xyRange; // y values have to be inverted
+                               _terrainAltValues[p] = (_terrainTrack.getPoint(p).getAltitude().getMetricValue() - _minAltitudeMetres) / _horizDistanceMetres;
                        }
-                       // Calculate x and y range
-                       _maxX = getScaledLongitude(_lonRange.getMaximum());
-                       _maxY = getScaledLatitude(_latRange.getMaximum());
-                       _maxAltitude = _altRange.getMaximum() - _altRange.getMinimum();
                }
        }
 
 
-       /**
-        * @return maximum horiz value
-        */
-       public double getMaximumHoriz() { return _maxX; }
-       /**
-        * @return maximum vert value
-        */
-       public double getMaximumVert() { return _maxY; }
-       /**
-        * @return maximum alt value
-        */
-       public int getMaximumAlt() { return _maxAltitude; }
 
        /**
         * Get the horizontal value for the specified point
@@ -131,6 +111,7 @@ public class PointScaler
        {
                return _xValues[inIndex];
        }
+
        /**
         * Get the vertical value for the specified point
         * @param inIndex index of point, starting at 0
@@ -140,176 +121,54 @@ public class PointScaler
        {
                return _yValues[inIndex];
        }
+
        /**
         * Get the altitude value for the specified point
         * @param inIndex index of point, starting at 0
         * @return scaled altitude value
         */
-       public int getAltValue(int inIndex)
+       public double getAltValue(int inIndex)
        {
                return _altValues[inIndex];
        }
 
        /**
-        * Scale the given latitude value
-        * @param inLatitude latitude in degrees
-        * @return scaled latitude
-        */
-       public double getScaledLatitude(double inLatitude)
-       {
-               return inLatitude - _latMedian;
-       }
-       /**
-        * Scale the given longitude value
-        * @param inLongitude longitude in degrees
-        * @return scaled longitude
-        */
-       public double getScaledLongitude(double inLongitude)
-       {
-               return (inLongitude - _lonMedian) * _longFactor;
-       }
-       /**
-        * Scale the given altitude value
-        * @param inAltitude Altitude object
-        * @return scaled altitude
-        */
-       public int getScaledAltitude(Altitude inAltitude)
-       {
-               if (inAltitude == null) return -1;
-               return inAltitude.getValue(_altRange.getFormat()) - _minAltitude;
-       }
-
-       /**
-        * Unscale the given latitude value
-        * @param inScaledLatitude scaled latitude
-        * @return latitude in degrees
-        */
-       public double getUnscaledLatitude(double inScaledLatitude)
-       {
-               return inScaledLatitude + _latMedian;
-       }
-       /**
-        * Unscale the given longitude value
-        * @param inScaledLongitude scaled longitude
-        * @return longitude in degrees
+        * @return altitude range as fraction of horizontal range
         */
-       public double getUnscaledLongitude(double inScaledLongitude)
+       public double getAltitudeRange()
        {
-               return inScaledLongitude / _longFactor + _lonMedian;
+               return _altitudeRange;
        }
 
        /**
-        * Calculate the latitude and longitude lines
+        * Get the horizontal value for the specified point
+        * @param inIndex index of point, starting at 0
+        * @return scaled horizontal value
         */
-       public void calculateLatLongLines()
+       public double getTerrainHorizValue(int inIndex)
        {
-               double maxValue = getMaximumHoriz() > getMaximumVert() ?
-                       getMaximumHoriz():getMaximumVert();
-               // calculate boundaries in degrees
-               double minLong = getUnscaledLongitude(-maxValue);
-               double maxLong = getUnscaledLongitude(maxValue);
-               double minLat = getUnscaledLatitude(-maxValue);
-               double maxLat = getUnscaledLatitude(maxValue);
-               // work out what line separation to use to give at least two lines
-               int sepIndex = -1;
-               double separation;
-               int numLatLines = 0, numLonLines = 0;
-               do
-               {
-                       sepIndex++;
-                       separation = COORD_SEPARATIONS[sepIndex];
-                       numLatLines = getNumLinesBetween(minLat, maxLat, separation);
-                       numLonLines = getNumLinesBetween(minLong, maxLong, separation);
-               }
-               while ((numLonLines <= 1 || numLatLines <= 1) && sepIndex < MAX_COORD_SEPARATION_INDEX);
-               // create lines based on this separation
-               _latLinesDegs = getLines(minLat, maxLat, separation, numLatLines);
-               _lonLinesDegs = getLines(minLong, maxLong, separation, numLonLines);
-               // scale lines also
-               _latLinesScaled = new double[numLatLines];
-               for (int i=0; i<numLatLines; i++) _latLinesScaled[i] = getScaledLatitude(_latLinesDegs[i]);
-               _lonLinesScaled = new double[numLonLines];
-               for (int i=0; i<numLonLines; i++) _lonLinesScaled[i] = getScaledLongitude(_lonLinesDegs[i]);
+               return _terrainxValues[inIndex];
        }
 
-
        /**
-        * Calculate the number of lines in the given range using the specified separation
-        * @param inMin minimum value
-        * @param inMax maximum value
-        * @param inSeparation line separation
-        * @return number of lines
+        * Get the vertical value for the specified point
+        * @param inIndex index of point, starting at 0
+        * @return scaled vertical value
         */
-       private static int getNumLinesBetween(double inMin, double inMax, double inSeparation)
+       public double getTerrainVertValue(int inIndex)
        {
-               // Start looking from round number of degrees below minimum
-               double value = (int) inMin;
-               if (inMin < 0.0) value = value - 1.0;
-               // Loop until bigger than maximum
-               int numLines = 0;
-               while (value < inMax)
-               {
-                       if (value >= inMin) numLines++;
-                       value += inSeparation;
-               }
-               return numLines;
+               return _terrainyValues[inIndex];
        }
 
-
        /**
-        * Get the line values in the given range using the specified separation
-        * @param inMin minimum value
-        * @param inMax maximum value
-        * @param inSeparation line separation
-        * @param inCount number of lines already counted
-        * @return array of line values
+        * @param inIndex index of point in terrain track
+        * @return scaled altitude value for the specified terrain point
         */
-       private static double[] getLines(double inMin, double inMax, double inSeparation, int inCount)
+       public double getTerrainAltValue(int inIndex)
        {
-               double[] values = new double[inCount];
-               // Start looking from round number of degrees below minimum
-               double value = (int) inMin;
-               if (inMin < 0.0) value = value - 1.0;
-               // Loop until bigger than maximum
-               int numLines = 0;
-               while (value < inMax)
-               {
-                       if (value >= inMin)
-                       {
-                               values[numLines] = value;
-                               numLines++;
-                       }
-                       value += inSeparation;
+               if (_terrainAltValues != null) {
+                       return _terrainAltValues[inIndex];
                }
-               return values;
-       }
-
-       /**
-        * @return array of latitude lines in degrees
-        */
-       public double[] getLatitudeLines()
-       {
-               return _latLinesDegs;
-       }
-       /**
-        * @return array of longitude lines in degrees
-        */
-       public double[] getLongitudeLines()
-       {
-               return _lonLinesDegs;
-       }
-       /**
-        * @return array of latitude lines in scaled units
-        */
-       public double[] getScaledLatitudeLines()
-       {
-               return _latLinesScaled;
-       }
-       /**
-        * @return array of longitude lines in scaled units
-        */
-       public double[] getScaledLongitudeLines()
-       {
-               return _lonLinesScaled;
+               return 0.0;
        }
 }