File: DedupeWaypointsFunction.java

package info (click to toggle)
gpsprune 26.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,824 kB
  • sloc: java: 52,154; sh: 25; makefile: 21; python: 15
file content (142 lines) | stat: -rw-r--r-- 4,190 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package tim.prune.function;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import tim.prune.App;
import tim.prune.GenericFunction;
import tim.prune.cmd.ShuffleAndCropCmd;
import tim.prune.data.DataPoint;
import tim.prune.data.Track;
import tim.prune.function.compress.WaypointComparer;
import tim.prune.function.compress.WaypointComparer.CompareResult;


/**
 * Class to provide the function for removing duplicate waypoints
 */
public class DedupeWaypointsFunction extends GenericFunction
{
	/**
	 * Constructor
	 * @param inApp app object
	 */
	public DedupeWaypointsFunction(App inApp) {
		super(inApp);
	}

	/** Get the name key */
	public String getNameKey() {
		return "function.dedupewaypoints";
	}

	@Override
	public void begin()
	{
		Track track = _app.getTrackInfo().getTrack();
		// Compare the waypoints with each other to find which ones should be ignored
		Map<String, List<Integer>> waypoints = new HashMap<>();
		for (int i=0; i<track.getNumPoints(); i++)
		{
			DataPoint point = track.getPoint(i);
			if (point.isWaypoint())
			{
				String key = getWaypointKey(point);
				waypoints.put(key, reduceWaypoints(waypoints.get(key), track, i));
			}
		}
		// Make lists of indexes to keep and ignore
		ArrayList<Integer> indexesToKeep = new ArrayList<>();
		ArrayList<Integer> indexesToDelete = new ArrayList<>();
		for (int i=0; i<track.getNumPoints(); i++)
		{
			DataPoint point = track.getPoint(i);
			if (!point.isWaypoint()) {
				indexesToKeep.add(i);
			}
			else
			{
				String key = getWaypointKey(point);
				List<Integer> shouldKeep = waypoints.get(key);
				if (shouldKeep.contains(i)) {
					indexesToKeep.add(i);
				}
				else {
					indexesToDelete.add(i);
				}
			}
		}
		if (indexesToDelete.isEmpty()) {
			_app.showErrorMessage(getNameKey(), "dialog.dedupewaypoints.nonefound");
		}
		else
		{
			// Use these lists to create a command
			_app.execute(new ShuffleAndCropCmd(indexesToKeep, indexesToDelete, null));
		}
	}

	/**
	 * Combine the points found so far with the newly received one
	 * @param inFoundPoints indexes of points found so far
	 * @param inTrack track to get points from
	 * @param inCurrIndex index of newly received point
	 * @return combined list of indexes
	 */
	static List<Integer> reduceWaypoints(List<Integer> inFoundPoints, Track inTrack, int inCurrIndex)
	{
		if (inFoundPoints == null || inFoundPoints.isEmpty()) {
			return List.of(inCurrIndex);
		}
		DataPoint nextPoint = inTrack.getPoint(inCurrIndex);
		ArrayList<CompareResult> compareResults = new ArrayList<>();
		if (shouldIgnorePoint(nextPoint, inFoundPoints, inTrack, compareResults)) {
			return inFoundPoints;
		}
		// Should keep this one, so make new list containing inCurrIndex but maybe removing some others
		ArrayList<Integer> newList = new ArrayList<>();
		for (int i=0; i<inFoundPoints.size(); i++)
		{
			CompareResult result = compareResults.get(i);
			if (result != CompareResult.SECOND_BETTER) {
				newList.add(inFoundPoints.get(i));
			}
		}
		newList.add(inCurrIndex);
		return newList;
	}

	/**
	 * Determine whether or not to ignore this next point
	 * @param nextPoint point to consider
	 * @param inFoundPoints indexes of points found until now
	 * @param inTrack track to get points from
	 * @param compareResults array of results to fill
	 * @return true if it's identical to or worse than any existing point, false to keep it
	 */
	static boolean shouldIgnorePoint(DataPoint nextPoint, List<Integer> inFoundPoints, Track inTrack,
			ArrayList<CompareResult> compareResults)
	{
		compareResults.clear();
		for (int pointIndex : inFoundPoints)
		{
			CompareResult result = WaypointComparer.compare(inTrack.getPoint(pointIndex), nextPoint);
			if (result == CompareResult.FIRST_BETTER || result == CompareResult.IDENTICAL) {
				return true; // ignore this point
			}
			compareResults.add(result);
		}
		return false;
	}

	/**
	 * @return key to use for referencing waypoint position and name
	 */
	private static String getWaypointKey(DataPoint inPoint)
	{
		return inPoint.getLatitude().toString() + "*" + inPoint.getLongitude().toString()
		 + "*" + inPoint.getWaypointName();
	}
}