1 package tim.prune.function.compress;
4 import tim.prune.UpdateMessageBroker;
5 import tim.prune.data.DataPoint;
6 import tim.prune.data.Distance;
7 import tim.prune.data.RangeStats;
8 import tim.prune.data.Track;
9 import tim.prune.data.UnitSetLibrary;
12 * Function to mark all the points going uphill on ski lifts
14 public class MarkLiftsFunction extends MarkAndDeleteFunction
18 * @param inApp App object
20 public MarkLiftsFunction(App inApp)
25 /** @return name key */
26 public String getNameKey() {
27 return "function.marklifts";
30 /** this function _does_ require split at deleted points */
31 protected boolean getShouldSplitSegments() {
36 * Begin the function using the set parameters
40 // TODO: Might need to do this in a separate thread, it might take a while if the track is big
41 // Loop over all points in track
43 final Track track = _app.getTrackInfo().getTrack();
44 final int numPoints = track.getNumPoints();
45 boolean[] markFlags = new boolean[numPoints];
46 int previousStartIndex = -1;
47 for (int i=0; i<numPoints; i++)
49 DataPoint currPoint = track.getPoint(i);
50 if (currPoint != null && !currPoint.isWaypoint() && currPoint.hasAltitude() && currPoint.hasTimestamp())
53 DataPoint endPoint = track.getPoint(n);
54 while (endPoint != null && endPoint.hasAltitude() && endPoint.hasTimestamp() &&
55 !endPoint.isWaypoint() && endPoint.getTimestamp().getSecondsSince(currPoint.getTimestamp()) < 120)
58 endPoint = track.getPoint(n);
60 if (endPoint != null && endPoint.hasAltitude() && endPoint.hasTimestamp() && !endPoint.isWaypoint()
63 // Found a 2 minute range to test with at least 12 points
64 if (looksLikeLiftRange(track, i, n))
66 // Passes tests, so we want to mark all points between i and n
68 // First check if we can merge with the previous marked range
69 if (previousStartIndex >= 0
70 && (looksLikeLiftRange(track, previousStartIndex, i)
71 || looksLikeLiftRange(track, previousStartIndex, n)))
73 startIndex = previousStartIndex; // merge
75 for (int j=startIndex; j<=n; j++)
79 // Remember start point for next one
80 previousStartIndex = startIndex;
81 // skip forward half the range, don't need to test the same points again
88 // Copy mark flags to points
89 for (int i=0; i<numPoints; i++)
91 DataPoint point = track.getPoint(i);
92 if (!point.isWaypoint()) point.setMarkedForDeletion(markFlags[i]);
93 if (markFlags[i]) numMarked++;
95 // Inform subscribers to update display
96 UpdateMessageBroker.informSubscribers();
97 // Confirm message showing how many marked
100 optionallyDeleteMarkedPoints(numMarked);
104 // TODO: Show message that no lifts were found
110 * Check whether the specified range looks like an uphill lift section or not
111 * Must go at most a little bit downhill, much more uphill than down, and straight
112 * (speed isn't checked yet, but maybe could be?)
113 * @param inTrack track
114 * @param inStartIndex start index of range
115 * @param inEndIndex end index of range
116 * @return true if it looks like a lift
118 private boolean looksLikeLiftRange(Track inTrack, int inStartIndex, int inEndIndex)
120 RangeStats stats = new RangeStats(inTrack, inStartIndex, inEndIndex);
121 int descent = stats.getTotalAltitudeRange().getDescent(UnitSetLibrary.UNITS_METRES);
124 int ascent = stats.getTotalAltitudeRange().getClimb(UnitSetLibrary.UNITS_METRES);
125 if (ascent > (descent * 10))
127 // Now check distance and compare to distance between start and end
128 final DataPoint startPoint = inTrack.getPoint(inStartIndex);
129 final DataPoint endPoint = inTrack.getPoint(inEndIndex);
131 final double trackDist = stats.getTotalDistance();
132 final double endToEndDist = Distance.convertRadiansToDistance(
133 DataPoint.calculateRadiansBetween(startPoint, endPoint));
134 if ((trackDist / endToEndDist) < 1.02) // Straight(ish) line
138 //else System.out.println("Not straight enough: " + (trackDist / endToEndDist));