]> gitweb.fperrin.net Git - GpsPrune.git/blob - src/tim/prune/function/CreateMarkerWaypointsFunction.java
f3dd1f1d9bca2eba8f78f42a3a136294363543e9
[GpsPrune.git] / src / tim / prune / function / CreateMarkerWaypointsFunction.java
1 package tim.prune.function;
2
3 import java.util.ArrayList;
4
5 import tim.prune.App;
6 import tim.prune.I18nManager;
7 import tim.prune.UpdateMessageBroker;
8 import tim.prune.data.DataPoint;
9 import tim.prune.data.Field;
10 import tim.prune.data.FieldList;
11 import tim.prune.data.Track;
12 import tim.prune.undo.UndoAppendPoints;
13
14 /**
15  * Function to create waypoints marking either
16  * at regular distance intervals or time intervals
17  */
18 public class CreateMarkerWaypointsFunction extends DistanceTimeLimitFunction
19 {
20         /** ArrayList of points to append to the track */
21         private ArrayList<DataPoint> _pointsToAdd = new ArrayList<DataPoint>();
22         /** Counter of previously used multiple */
23         private int _previousMultiple = 0;
24
25
26         /**
27          * Constructor
28          */
29         public CreateMarkerWaypointsFunction(App inApp) {
30                 super(inApp);
31         }
32
33         /**
34          * @return name key
35          */
36         public String getNameKey() {
37                 return "function.createmarkerwaypoints";
38         }
39
40         /**
41          * Init the state to start collecting a new set of points
42          */
43         private void initMemory()
44         {
45                 _pointsToAdd.clear();
46                 _previousMultiple = 0;
47         }
48
49         /**
50          * The dialog has been completed and OK pressed, so do the point creation
51          */
52         protected void performFunction()
53         {
54                 // Distribute either by distance or time
55                 final int timeLimitSeconds = getTimeLimitInSeconds();
56                 final boolean createByTime = (timeLimitSeconds > 0);
57                 final double distLimitRadians = getDistanceLimitRadians();
58                 final boolean createByDistance = (distLimitRadians > 0.0);
59                 if (!createByTime && !createByDistance) {
60                         return; // neither option selected
61                 }
62
63                 // Make undo object
64                 final int numPoints = _app.getTrackInfo().getTrack().getNumPoints();
65                 UndoAppendPoints undo = new UndoAppendPoints(numPoints);
66
67                 // set up the memory from scratch to collect the created points
68                 initMemory();
69
70                 // Make new waypoints, looping through the points in the track
71                 DataPoint currPoint = null, prevPoint = null;
72                 double currValue = 0.0, prevValue = 0.0;
73                 for (int i=0; i<numPoints; i++)
74                 {
75                         currPoint = _app.getTrackInfo().getTrack().getPoint(i);
76                         if (!currPoint.isWaypoint())
77                         {
78                                 if (!currPoint.getSegmentStart() && prevPoint != null)
79                                 {
80                                         // Calculate current value
81                                         if (createByTime)
82                                         {
83                                                 if (currPoint.hasTimestamp() && prevPoint.hasTimestamp())
84                                                 {
85                                                         currValue += (currPoint.getTimestamp().getMillisecondsSince(prevPoint.getTimestamp()) / 1000.0);
86                                                         processValue(prevPoint, prevValue, timeLimitSeconds, currPoint, currValue);
87                                                 }
88                                         }
89                                         else if (createByDistance)
90                                         {
91                                                 currValue += DataPoint.calculateRadiansBetween(prevPoint, currPoint);
92                                                 processValue(prevPoint, prevValue, distLimitRadians, currPoint, currValue);
93                                         }
94                                 }
95                                 prevPoint = currPoint;
96                                 prevValue = currValue;
97                         }
98                 }
99
100                 // System.out.println(_pointsToAdd.size() + " markers to add...");
101                 if (!_pointsToAdd.isEmpty())
102                 {
103                         // Append created points to Track
104                         Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.ALTITUDE, Field.WAYPT_NAME};
105                         final int numPointsToAdd = _pointsToAdd.size();
106                         DataPoint[] waypoints = new DataPoint[numPointsToAdd];
107                         _pointsToAdd.toArray(waypoints);
108                         Track wpTrack = new Track(new FieldList(fields), waypoints);
109                         _app.getTrackInfo().getTrack().combine(wpTrack);
110
111                         undo.setNumPointsAppended(numPointsToAdd);
112                         _app.completeFunction(undo, I18nManager.getText("confirm.interpolate"));
113                         // TODO: Maybe add new token including number of points added/created
114                         UpdateMessageBroker.informSubscribers();
115                 }
116                 _dialog.dispose();
117         }
118
119         /**
120          * Consider a pair of points in the track to see if a new marker should be inserted between them
121          * @param inPrevPoint previous point
122          * @param inPrevValue value of function at this previous point
123          * @param inLimit user-specified limit for marker values
124          * @param inCurrPoint current point
125          * @param inCurrValue value of function at this current point
126          */
127         private void processValue(DataPoint inPrevPoint, double inPrevValue, double inLimit,
128                 DataPoint inCurrPoint, double inCurrValue)
129         {
130                 // Check the current multiple and compare with previously used one
131                 final int currMultiple = (int) Math.floor(inCurrValue / inLimit);
132                 for (int m=_previousMultiple+1; m<=currMultiple; m++)
133                 {
134                         // Calculate position of limit between the two points
135                         final double valueBeforeBreak = (m * inLimit) - inPrevValue;
136                         final double valueAfterBreak = inCurrValue - (m * inLimit);
137                         final double fractionFromPrev = valueBeforeBreak / (valueBeforeBreak + valueAfterBreak);
138                         DataPoint marker = DataPoint.interpolate(inPrevPoint, inCurrPoint, fractionFromPrev);
139                         marker.setFieldValue(Field.WAYPT_NAME, createLimitDescription(m), false);
140                         _pointsToAdd.add(marker);
141                         // System.out.println("I would add a point here with values " + inPrevValue + " and " + inCurrValue);
142                 }
143                 _previousMultiple = currMultiple;
144         }
145 }