X-Git-Url: https://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=tim%2Fprune%2Fdata%2FTrack.java;h=df51e8f27e3c8963189b664adefc7534861188ea;hp=eeb5b626bb484e59750b605849d653d77ca2a25b;hb=54b9d8bc8f0025ccf97a67d9dd217ef1f9cf082f;hpb=52bf9e8686c916be37a26a0b75340393d4478b05 diff --git a/tim/prune/data/Track.java b/tim/prune/data/Track.java index eeb5b62..df51e8f 100644 --- a/tim/prune/data/Track.java +++ b/tim/prune/data/Track.java @@ -2,9 +2,10 @@ package tim.prune.data; import java.util.List; +import tim.prune.Config; import tim.prune.UpdateMessageBroker; -import tim.prune.edit.FieldEdit; -import tim.prune.edit.FieldEditList; +import tim.prune.function.edit.FieldEdit; +import tim.prune.function.edit.FieldEditList; import tim.prune.gui.map.MapUtils; @@ -19,8 +20,6 @@ public class Track // Scaled x, y values private double[] _xValues = null; private double[] _yValues = null; - private double[] _xValuesNew = null; - private double[] _yValuesNew = null; private boolean _scaled = false; private int _numPoints = 0; private boolean _mixedData = false; @@ -53,7 +52,7 @@ public class Track * @param inPointArray 2d object array containing data * @param inAltFormat altitude format */ - public void load(Field[] inFieldArray, Object[][] inPointArray, int inAltFormat) + public void load(Field[] inFieldArray, Object[][] inPointArray, Altitude.Format inAltFormat) { if (inFieldArray == null || inPointArray == null) { @@ -88,6 +87,19 @@ public class Track } + /** + * Load the track by transferring the contents from a loaded Track object + * @param inOther Track object containing loaded data + */ + public void load(Track inOther) + { + _numPoints = inOther._numPoints; + _masterFieldList = inOther._masterFieldList; + _dataPoints = inOther._dataPoints; + // needs to be scaled + _scaled = false; + } + ////////////////// Modification methods ////////////////////// @@ -131,64 +143,22 @@ public class Track /** - * Compress the track to the given resolution - * @param inResolution resolution + * Delete the points marked for deletion * @return number of points deleted */ - public int compress(int inResolution) + public int deleteMarkedPoints() { - // (maybe should be separate thread?) - // (maybe should be in separate class?) - // (maybe should be based on subtended angles instead of distances?) - // Suggestion: Find last track point, don't delete it (or maybe preserve first and last of each segment?) - - if (inResolution <= 0) return 0; int numCopied = 0; - // Establish range of track and minimum range between points - scalePoints(); - double wholeScale = _xRange.getMaximum() - _xRange.getMinimum(); - double yscale = _yRange.getMaximum() - _yRange.getMinimum(); - if (yscale > wholeScale) wholeScale = yscale; - double minDist = wholeScale / inResolution; - - // Keep track of segment start flags of the deleted points - boolean setSegment = false; // Copy selected points DataPoint[] newPointArray = new DataPoint[_numPoints]; - int[] pointIndices = new int[_numPoints]; for (int i=0; i<_numPoints; i++) { DataPoint point = _dataPoints[i]; - boolean keepPoint = true; // Don't delete waypoints or photo points - if (!point.isWaypoint() && point.getPhoto() == null) - { - // go through newPointArray to check for range - for (int j=0; j 0) - { - // Make new resized array and copy DataPoints over - DataPoint[] newPointArray = new DataPoint[_numPoints - numDupes]; - j = 0; - for (i=0; i<_numPoints; i++) - { - if (!dupes[i]) - { - newPointArray[j] = _dataPoints[i]; - j++; - } - } - // Copy array references - _dataPoints = newPointArray; - _numPoints = _dataPoints.length; - _scaled = false; - } - return numDupes; - } - - /** * Reverse the specified range of points * @param inStart start index @@ -613,6 +515,53 @@ public class Track } + /** + * Average selected points + * @param inStartIndex start index of selection + * @param inEndIndex end index of selection + * @return true if successful + */ + public boolean average(int inStartIndex, int inEndIndex) + { + // check parameters + if (inStartIndex < 0 || inStartIndex >= _numPoints || inEndIndex <= inStartIndex) + return false; + + DataPoint startPoint = getPoint(inStartIndex); + double firstLatitude = startPoint.getLatitude().getDouble(); + double firstLongitude = startPoint.getLongitude().getDouble(); + double latitudeDiff = 0.0, longitudeDiff = 0.0; + double totalAltitude = 0; + int numAltitudes = 0; + Altitude.Format altFormat = Config.getUseMetricUnits()?Altitude.Format.METRES:Altitude.Format.FEET; + // loop between start and end points + for (int i=inStartIndex; i<= inEndIndex; i++) + { + DataPoint currPoint = getPoint(i); + latitudeDiff += (currPoint.getLatitude().getDouble() - firstLatitude); + longitudeDiff += (currPoint.getLongitude().getDouble() - firstLongitude); + if (currPoint.hasAltitude()) { + totalAltitude += currPoint.getAltitude().getValue(altFormat); + numAltitudes++; + } + } + int numPoints = inEndIndex - inStartIndex + 1; + double meanLatitude = firstLatitude + (latitudeDiff / numPoints); + double meanLongitude = firstLongitude + (longitudeDiff / numPoints); + Altitude meanAltitude = null; + if (numAltitudes > 0) {meanAltitude = new Altitude((int) (totalAltitude / numAltitudes), altFormat);} + + DataPoint insertedPoint = new DataPoint(new Latitude(meanLatitude, Coordinate.FORMAT_NONE), + new Longitude(meanLongitude, Coordinate.FORMAT_NONE), meanAltitude); + // Make into singleton + insertedPoint.setSegmentStart(true); + DataPoint nextPoint = getNextTrackPoint(inEndIndex+1); + if (nextPoint != null) {nextPoint.setSegmentStart(true);} + // Insert points into track + return insertRange(new DataPoint[] {insertedPoint}, inEndIndex + 1); + } + + /** * Append the specified points to the end of the track * @param inPoints DataPoint objects to add @@ -719,26 +668,6 @@ public class Track return _yValues[inPointNum]; } - /** - * @param inPointNum point index, starting at 0 - * @return scaled x value of specified point - */ - public double getXNew(int inPointNum) - { - if (!_scaled) scalePoints(); - return _xValuesNew[inPointNum]; - } - - /** - * @param inPointNum point index, starting at 0 - * @return scaled y value of specified point - */ - public double getYNew(int inPointNum) - { - if (!_scaled) scalePoints(); - return _yValuesNew[inPointNum]; - } - /** * @return the master field list */ @@ -768,11 +697,17 @@ public class Track */ public boolean hasData(Field inField, int inStart, int inEnd) { + // Loop over selected point range for (int i=inStart; i<=inEnd; i++) { if (_dataPoints[i].getFieldValue(inField) != null) { - return true; + // Check altitudes and timestamps + if ((inField != Field.ALTITUDE || _dataPoints[i].getAltitude().isValid()) + && (inField != Field.TIMESTAMP || _dataPoints[i].getTimestamp().isValid())) + { + return true; + } } } return false; @@ -788,12 +723,41 @@ public class Track return _mixedData; } + /** + * @return true if track contains any points marked for deletion + */ + public boolean hasMarkedPoints() + { + if (_numPoints < 1) { + return false; + } + // Loop over points looking for any marked for deletion + for (int i=0; i<=_numPoints-1; i++) + { + if (_dataPoints[i] != null && _dataPoints[i].getDeleteFlag()) { + return true; + } + } + // None found + return false; + } + + /** + * Clear all the deletion markers + */ + public void clearDeletionMarkers() + { + for (int i=0; i<_numPoints; i++) + { + _dataPoints[i].setMarkedForDeletion(false); + } + } /** * Collect all the waypoints into the given List * @param inList List to fill with waypoints */ - public void getWaypoints(List inList) + public void getWaypoints(List inList) { // clear list inList.clear(); @@ -865,16 +829,9 @@ public class Track } _mixedData = hasWaypoint && hasTrackpoint; - // Use medians to centre at 0 - double longMedian = (_longRange.getMaximum() + _longRange.getMinimum()) / 2.0; - double latMedian = (_latRange.getMaximum() + _latRange.getMinimum()) / 2.0; - double longFactor = Math.cos(latMedian / 180.0 * Math.PI); // Function of median latitude - // Loop over points and calculate scales _xValues = new double[getNumPoints()]; _yValues = new double[getNumPoints()]; - _xValuesNew = new double[getNumPoints()]; - _yValuesNew = new double[getNumPoints()]; _xRange = new DoubleRange(); _yRange = new DoubleRange(); for (p=0; p < getNumPoints(); p++) @@ -882,12 +839,10 @@ public class Track DataPoint point = getPoint(p); if (point != null) { - _xValues[p] = (point.getLongitude().getDouble() - longMedian) * longFactor; + _xValues[p] = MapUtils.getXFromLongitude(point.getLongitude().getDouble()); _xRange.addValue(_xValues[p]); - _xValuesNew[p] = MapUtils.getXFromLongitude(point.getLongitude().getDouble()); - _yValues[p] = (point.getLatitude().getDouble() - latMedian); + _yValues[p] = MapUtils.getYFromLatitude(point.getLatitude().getDouble()); _yRange.addValue(_yValues[p]); - _yValuesNew[p] = MapUtils.getYFromLatitude(point.getLatitude().getDouble()); } } _scaled = true; @@ -928,41 +883,6 @@ public class Track return nearestPoint; } - - /** - * Find the nearest point to the specified x and y coordinates - * or -1 if no point is within the specified max distance - * @param inX x coordinate - * @param inY y coordinate - * @param inMaxDist maximum distance from selected coordinates - * @param inJustTrackPoints true if waypoints should be ignored - * @return index of nearest point or -1 if not found - */ - public int getNearestPointIndexNew(double inX, double inY, double inMaxDist, boolean inJustTrackPoints) - { - int nearestPoint = 0; - double nearestDist = -1.0; - double currDist; - for (int i=0; i < getNumPoints(); i++) - { - if (!inJustTrackPoints || !_dataPoints[i].isWaypoint()) - { - currDist = Math.abs(_xValuesNew[i] - inX) + Math.abs(_yValuesNew[i] - inY); - if (currDist < nearestDist || nearestDist < 0.0) - { - nearestPoint = i; - nearestDist = currDist; - } - } - } - // Check whether it's within required distance - if (nearestDist > inMaxDist && inMaxDist > 0.0) - { - return -1; - } - return nearestPoint; - } - /** * Get the next track point starting from the given index * @param inStartIndex index to start looking from @@ -1187,7 +1107,7 @@ public class Track // set photo status if coordinates have changed if (inPoint.getPhoto() != null && coordsChanged) { - inPoint.getPhoto().setCurrentStatus(PhotoStatus.CONNECTED); + inPoint.getPhoto().setCurrentStatus(Photo.Status.CONNECTED); } // point possibly needs to be scaled again _scaled = false;