--- /dev/null
+package tim.prune.function.compress;
+
+import java.awt.Component;
+import java.awt.event.ActionListener;
+
+import tim.prune.data.DataPoint;
+import tim.prune.data.Track;
+
+/**
+ * Algorithm for detecting close points to compress
+ * Only checks distance to previous point, not any earlier point
+ */
+public class ClosePointsAlgorithm extends SingleParameterAlgorithm
+{
+
+ /**
+ * Constructor
+ * @param inTrack track object
+ * @param inDetails track details object
+ * @param inListener listener to attach to activation control
+ */
+ public ClosePointsAlgorithm(Track inTrack, TrackDetails inDetails, ActionListener inListener)
+ {
+ super(inTrack, inDetails, inListener);
+ }
+
+ /**
+ * Perform the compression and work out which points should be deleted
+ * @param inFlags deletion flags from previous algorithms
+ * @return number of points deleted
+ */
+ protected int compress(boolean[] inFlags)
+ {
+ // Parse parameter
+ double param = getParameter();
+ // Use 1/x if x greater than 1
+ if (param > 1.0) param = 1.0 / param;
+ if (param <= 0.0 || param >= 1.0) {
+ // Parameter isn't valid, don't delete any
+ return 0;
+ }
+ double threshold = _trackDetails.getTrackSpan() * param;
+
+ // Loop over all points checking distances to previous point
+ // TODO: Maybe this should also check distance to _next_ point as well!
+ int numPoints = _track.getNumPoints();
+ int prevPointIndex = 0;
+ int prevTrackPointIndex = 0;
+ double pointDist = 0.0;
+ int numDeleted = 0;
+ for (int i=1; i<numPoints; i++)
+ {
+ // don't delete points already deleted
+ if (!inFlags[i])
+ {
+ DataPoint currPoint = _track.getPoint(i);
+ // Don't consider waypoints
+ if (!currPoint.isWaypoint())
+ {
+ // Don't delete any photo points or start/end of segments
+ if (!currPoint.hasMedia()
+ && !_trackDetails.isSegmentStart(i) && !_trackDetails.isSegmentEnd(i))
+ {
+ // Check current point against prevPoint
+ pointDist = Math.abs(_track.getX(i) - _track.getX(prevPointIndex))
+ + Math.abs(_track.getY(i) - _track.getY(prevPointIndex));
+ if (pointDist < threshold) {
+ inFlags[i] = true;
+ numDeleted++;
+ }
+ else if (prevTrackPointIndex != prevPointIndex)
+ {
+ // Check current point against prevTrackPoint
+ pointDist = Math.abs(_track.getX(i) - _track.getX(prevTrackPointIndex))
+ + Math.abs(_track.getY(i) - _track.getY(prevTrackPointIndex));
+ if (pointDist < threshold) {
+ inFlags[i] = true;
+ numDeleted++;
+ }
+ }
+ }
+ if (!inFlags[i]) {prevTrackPointIndex = i;}
+ }
+ if (!inFlags[i]) {prevPointIndex = i;}
+ }
+ }
+ return numDeleted;
+ }
+
+
+ /**
+ * @return specific gui components for dialog
+ */
+ protected Component getSpecificGuiComponents()
+ {
+ return getSpecificGuiComponents("dialog.compress.closepoints.paramdesc", "200");
+ }
+
+ /**
+ * @return title key for box
+ */
+ protected String getTitleTextKey()
+ {
+ return "dialog.compress.closepoints.title";
+ }
+
+}