]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/function/compress/MarkLiftsFunction.java
5e3986621c73e46083373b6d30ed806d277faa21
[GpsPrune.git] / tim / prune / function / compress / MarkLiftsFunction.java
1 package tim.prune.function.compress;
2
3 import tim.prune.App;
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;
10
11 /**
12  * Function to mark all the points going uphill on ski lifts
13  */
14 public class MarkLiftsFunction extends MarkAndDeleteFunction
15 {
16         /**
17          * Constructor
18          * @param inApp App object
19          */
20         public MarkLiftsFunction(App inApp)
21         {
22                 super(inApp);
23         }
24
25         /** @return name key */
26         public String getNameKey() {
27                 return "function.marklifts";
28         }
29
30         /** this function _does_ require split at deleted points */
31         protected boolean getShouldSplitSegments() {
32                 return true;
33         }
34
35         /**
36          * Begin the function using the set parameters
37          */
38         public void begin()
39         {
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
42                 int numMarked = 0;
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++)
48                 {
49                         DataPoint currPoint = track.getPoint(i);
50                         if (currPoint != null && !currPoint.isWaypoint() && currPoint.hasAltitude() && currPoint.hasTimestamp())
51                         {
52                                 int n = i+1;
53                                 DataPoint endPoint = track.getPoint(n);
54                                 while (endPoint != null && endPoint.hasAltitude() && endPoint.hasTimestamp() &&
55                                         !endPoint.isWaypoint() && endPoint.getTimestamp().getSecondsSince(currPoint.getTimestamp()) < 120)
56                                 {
57                                         n++;
58                                         endPoint = track.getPoint(n);
59                                 }
60                                 if (endPoint != null && endPoint.hasAltitude() && endPoint.hasTimestamp() && !endPoint.isWaypoint()
61                                         && n > (i+10))
62                                 {
63                                         // Found a 2 minute range to test with at least 12 points
64                                         if (looksLikeLiftRange(track, i, n))
65                                         {
66                                                 // Passes tests, so we want to mark all points between i and n
67                                                 int startIndex = i;
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)))
72                                                 {
73                                                         startIndex = previousStartIndex; // merge
74                                                 }
75                                                 for (int j=startIndex; j<=n; j++)
76                                                 {
77                                                         markFlags[j] = true;
78                                                 }
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
82                                                 i = (i+n)/2;
83                                         }
84                                 }
85                         }
86                 }
87
88                 // Copy mark flags to points
89                 for (int i=0; i<numPoints; i++)
90                 {
91                         DataPoint point = track.getPoint(i);
92                         if (!point.isWaypoint()) point.setMarkedForDeletion(markFlags[i]);
93                         if (markFlags[i]) numMarked++;
94                 }
95                 // Inform subscribers to update display
96                 UpdateMessageBroker.informSubscribers();
97                 // Confirm message showing how many marked
98                 if (numMarked > 0)
99                 {
100                         optionallyDeleteMarkedPoints(numMarked);
101                 }
102                 else
103                 {
104                         // TODO: Show message that no lifts were found
105                 }
106         }
107
108
109         /**
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
117          */
118         private boolean looksLikeLiftRange(Track inTrack, int inStartIndex, int inEndIndex)
119         {
120                 RangeStats stats = new RangeStats(inTrack, inStartIndex, inEndIndex);
121                 int descent = stats.getTotalAltitudeRange().getDescent(UnitSetLibrary.UNITS_METRES);
122                 if (descent < 20)
123                 {
124                         int ascent = stats.getTotalAltitudeRange().getClimb(UnitSetLibrary.UNITS_METRES);
125                         if (ascent > (descent * 10))
126                         {
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);
130
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
135                                 {
136                                         return true;
137                                 }
138                                 //else System.out.println("Not straight enough: " + (trackDist / endToEndDist));
139                         }
140                 }
141                 return false;
142         }
143 }