]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/data/PointScaler.java
Version 15, March 2013
[GpsPrune.git] / tim / prune / data / PointScaler.java
index 180f3a5aef74e131d0c9bab9649310b4e840ef5e..a1338857e0c509acc6a3d6227f4044080e3f2914 100644 (file)
@@ -1,41 +1,19 @@
 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
        private Track _track = null;
-       // Range information
-       private double _latMedian = 0.0;
-       private double _lonMedian = 0.0;
-       private int _minAltitude = 0;
-       // Scaling information
-       private double _longFactor = 0.0;
-       private double _altFactor = 0.0;
-       // Scaled points
+       // Scaled values
        private double[] _xValues = null;
        private double[] _yValues = null;
        private double[] _altValues = null;
-       // max values
-       private double _maxX = 0.0;
-       private double _maxY = 0.0;
-       private double _maxScaledAlt = 0.0;
-       // lat/long lines
-       private double[] _latLinesDegs = null;
-       private double[] _lonLinesDegs = null;
-       private double[] _latLinesScaled = null;
-       private double[] _lonLinesScaled = null;
+       // Altitude range
+       private double _altitudeRange = 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
@@ -52,78 +30,42 @@ public class PointScaler
         */
        public void scale()
        {
-               // Clear data
-               DoubleRange latRange = new DoubleRange();
-               DoubleRange lonRange = new DoubleRange();
-               DoubleRange altRange = new DoubleRange();
-               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();
+               final double horizDistance = Math.max(extents.getHorizontalDistanceMetres(), 1.0);
+               final int numPoints = _track.getNumPoints();
+
+               // Find altitude range
+               _altitudeRange = extents.getAltitudeRange().getRange() / horizDistance;
+               final double minAltitude = extents.getAltitudeRange().getMinimum();
+
+               // create new arrays for scaled values
+               if (_xValues == null || _xValues.length != numPoints)
                {
-                       for (p=0; p<numPoints; p++)
-                       {
-                               point = _track.getPoint(p);
-                               if (point != null)
-                               {
-                                       latRange.addValue(point.getLatitude().getDouble());
-                                       lonRange.addValue(point.getLongitude().getDouble());
-                                       altRange.addValue(point.getAltitude().getValue(Altitude.Format.METRES));
-                               }
-                       }
+                       _xValues = new double[numPoints];
+                       _yValues = new double[numPoints];
+                       _altValues = new double[numPoints];
+               }
 
-                       // Find median latitude and calculate factor
-                       _latMedian = (latRange.getMinimum() + latRange.getMaximum()) / 2;
-                       _lonMedian = (lonRange.getMinimum() + lonRange.getMaximum()) / 2;
-                       _minAltitude = (int) altRange.getMinimum();
-                       _longFactor = Math.cos(_latMedian / 180.0 * Math.PI); // quite rough
-                       // Find altitude scale factor using distance
-                       DataPoint p1 = new DataPoint(new Latitude(latRange.getMinimum(), Coordinate.FORMAT_DEG),
-                               new Longitude(_lonMedian, Coordinate.FORMAT_DEG), null);
-                       DataPoint p2 = new DataPoint(new Latitude(latRange.getMaximum(), Coordinate.FORMAT_DEG),
-                               new Longitude(_lonMedian, Coordinate.FORMAT_DEG), null);
-                       double horizDist = Distance.convertRadiansToDistance(
-                               DataPoint.calculateRadiansBetween(p1, p2), UnitSetLibrary.UNITS_METRES); // both in m
-                       _altFactor = 1.0 / horizDist;
+               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)
-                       {
-                               _xValues = new double[numPoints];
-                               _yValues = new double[numPoints];
-                               _altValues = new double[numPoints];
-                       }
-                       // Calculate scaled values
-                       for (p=0; p<numPoints; p++)
+               // Calculate scaled values
+               for (int p=0; p<numPoints; p++)
+               {
+                       DataPoint point = _track.getPoint(p);
+                       if (point != null)
                        {
-                               point = _track.getPoint(p);
-                               if (point != null)
-                               {
-                                       _xValues[p] = getScaledLongitude(point.getLongitude().getDouble());
-                                       _yValues[p] = getScaledLatitude(point.getLatitude().getDouble());
-                                       _altValues[p] = getScaledAltitude(point.getAltitude());
-                                       if (_altValues[p] > _maxScaledAlt) {_maxScaledAlt = _altValues[p];}
-                               }
+                               _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() - minAltitude) / horizDistance;
                        }
-                       // Calculate x and y range
-                       _maxX = getScaledLongitude(lonRange.getMaximum());
-                       _maxY = getScaledLatitude(latRange.getMaximum());
                }
        }
 
 
-       /**
-        * @return maximum horiz value
-        */
-       public double getMaximumHoriz() { return _maxX; }
-       /**
-        * @return maximum vert value
-        */
-       public double getMaximumVert() { return _maxY; }
-
-       /** @return maximum scaled altitude value */
-       public double getMaxScaledAlt() { return _maxScaledAlt; }
 
        /**
         * Get the horizontal value for the specified point
@@ -134,6 +76,7 @@ public class PointScaler
        {
                return _xValues[inIndex];
        }
+
        /**
         * Get the vertical value for the specified point
         * @param inIndex index of point, starting at 0
@@ -143,6 +86,7 @@ public class PointScaler
        {
                return _yValues[inIndex];
        }
+
        /**
         * Get the altitude value for the specified point
         * @param inIndex index of point, starting at 0
@@ -154,165 +98,10 @@ public class PointScaler
        }
 
        /**
-        * Scale the given latitude value
-        * @param inLatitude latitude in degrees
-        * @return scaled latitude
-        */
-       private double getScaledLatitude(double inLatitude)
-       {
-               return inLatitude - _latMedian;
-       }
-       /**
-        * Scale the given longitude value
-        * @param inLongitude longitude in degrees
-        * @return scaled longitude
-        */
-       private double getScaledLongitude(double inLongitude)
-       {
-               return (inLongitude - _lonMedian) * _longFactor;
-       }
-       /**
-        * Scale the given altitude value
-        * @param inAltitude Altitude object
-        * @return scaled altitude
-        */
-       private double getScaledAltitude(Altitude inAltitude)
-       {
-               if (inAltitude == null) return -1;
-               return (inAltitude.getValue(Altitude.Format.METRES) - _minAltitude) * _altFactor;
-       }
-
-       /**
-        * Unscale the given latitude value
-        * @param inScaledLatitude scaled latitude
-        * @return latitude in degrees
-        */
-       private double getUnscaledLatitude(double inScaledLatitude)
-       {
-               return inScaledLatitude + _latMedian;
-       }
-       /**
-        * Unscale the given longitude value
-        * @param inScaledLongitude scaled longitude
-        * @return longitude in degrees
-        */
-       private double getUnscaledLongitude(double inScaledLongitude)
-       {
-               return inScaledLongitude / _longFactor + _lonMedian;
-       }
-
-       /**
-        * Calculate the latitude and longitude lines
-        */
-       public void calculateLatLongLines()
-       {
-               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]);
-       }
-
-
-       /**
-        * 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
-        */
-       private static int getNumLinesBetween(double inMin, double inMax, double inSeparation)
-       {
-               // 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;
-       }
-
-
-       /**
-        * 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
-        */
-       private static double[] getLines(double inMin, double inMax, double inSeparation, int inCount)
-       {
-               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;
-               }
-               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
+        * @return altitude range, in metres
         */
-       public double[] getScaledLongitudeLines()
+       public double getAltitudeRange()
        {
-               return _lonLinesScaled;
+               return _altitudeRange;
        }
 }