--- /dev/null
+package tim.prune.data;
+
+/**
+ * Class to hold the extents of a track, in 2d and in 3d,
+ * and to calculate a square area with a default border
+ */
+public class TrackExtents
+{
+ /** Track object */
+ private Track _track = null;
+ /** X and Y ranges */
+ private DoubleRange _xRange = null, _yRange = null;
+
+ /** Border multiplier */
+ private static final double BORDER_MULTIPLIER = 1.1; // 10% border
+
+ /**
+ * Constructor
+ * @param inTrack track object to take extents from
+ */
+ public TrackExtents(Track inTrack)
+ {
+ _track = inTrack;
+ _xRange = inTrack.getXRange().copy();
+ _yRange = inTrack.getYRange().copy();
+ }
+
+
+ /**
+ * Make the x and y ranges square with a default border around
+ */
+ public void applySquareBorder()
+ {
+ // Find the middle of the x and y
+ final double midXvalue = _xRange.getMidValue();
+ final double midYvalue = _yRange.getMidValue();
+ // Find x and y range, take maximum
+ double xyRange = Math.max(_xRange.getRange(), _yRange.getRange()) * BORDER_MULTIPLIER;
+ if (getHorizontalDistanceMetres() < 10.0)
+ {
+ // all the points are near enough on the same spot, expand scale to avoid dividing by zero
+ xyRange = 0.1;
+ }
+
+ // Apply these new min and max to the ranges
+ _xRange.addValue(midXvalue - xyRange / 2.0);
+ _xRange.addValue(midXvalue + xyRange / 2.0);
+ _yRange.addValue(midYvalue - xyRange / 2.0);
+ _yRange.addValue(midYvalue + xyRange / 2.0);
+ }
+
+ /** @return x range */
+ public DoubleRange getXRange() {
+ return _xRange;
+ }
+
+ /** @return y range */
+ public DoubleRange getYRange() {
+ return _yRange;
+ }
+
+ /** @return altitude range */
+ public DoubleRange getAltitudeRange()
+ {
+ final int numPoints = _track.getNumPoints();
+ DoubleRange altRange = new DoubleRange();
+ for (int i=0; i<numPoints; i++)
+ {
+ DataPoint p = _track.getPoint(i);
+ if (p != null && p.hasAltitude()) {
+ altRange.addValue(p.getAltitude().getMetricValue());
+ }
+ }
+ return altRange;
+ }
+
+ /**
+ * @return the greater of the N/S and E/W extent of the track, in metres (including border)
+ */
+ public double getHorizontalDistanceMetres()
+ {
+ DoubleRange lonRange = _track.getLonRange();
+ DoubleRange latRange = _track.getLatRange();
+
+ // Find horizontal and vertical extents of enclosing rectangle
+ DataPoint southPoint = new DataPoint(new Latitude(latRange.getMinimum(), Coordinate.FORMAT_DEG),
+ new Longitude(lonRange.getMidValue(), Coordinate.FORMAT_DEG), null);
+ DataPoint northPoint = new DataPoint(new Latitude(latRange.getMaximum(), Coordinate.FORMAT_DEG),
+ new Longitude(lonRange.getMidValue(), Coordinate.FORMAT_DEG), null);
+ double nsDist = Distance.convertRadiansToDistance(
+ DataPoint.calculateRadiansBetween(northPoint, southPoint), UnitSetLibrary.UNITS_METRES); // both in m
+ // Same again for bottom and top, take maximum
+ DataPoint westPoint = new DataPoint(new Latitude(latRange.getMidValue(), Coordinate.FORMAT_DEG),
+ new Longitude(lonRange.getMinimum(), Coordinate.FORMAT_DEG), null);
+ DataPoint eastPoint = new DataPoint(new Latitude(latRange.getMidValue(), Coordinate.FORMAT_DEG),
+ new Longitude(lonRange.getMinimum(), Coordinate.FORMAT_DEG), null);
+ double ewDist = Distance.convertRadiansToDistance(
+ DataPoint.calculateRadiansBetween(westPoint, eastPoint), UnitSetLibrary.UNITS_METRES); // both in m
+ final double horizDistance = Math.max(nsDist, ewDist) * BORDER_MULTIPLIER;
+
+ return horizDistance;
+ }
+}