1 package tim.prune.function;
3 import java.util.ArrayList;
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;
15 * Function to create waypoints marking either
16 * at regular distance intervals or time intervals
18 public class CreateMarkerWaypointsFunction extends DistanceTimeLimitFunction
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;
29 public CreateMarkerWaypointsFunction(App inApp) {
36 public String getNameKey() {
37 return "function.createmarkerwaypoints";
41 * Init the state to start collecting a new set of points
43 private void initMemory()
46 _previousMultiple = 0;
50 * The dialog has been completed and OK pressed, so do the point creation
52 protected void performFunction()
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
64 final int numPoints = _app.getTrackInfo().getTrack().getNumPoints();
65 UndoAppendPoints undo = new UndoAppendPoints(numPoints);
67 // set up the memory from scratch to collect the created points
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++)
75 currPoint = _app.getTrackInfo().getTrack().getPoint(i);
76 if (!currPoint.isWaypoint())
78 if (!currPoint.getSegmentStart() && prevPoint != null)
80 // Calculate current value
83 if (currPoint.hasTimestamp() && prevPoint.hasTimestamp())
85 currValue += (currPoint.getTimestamp().getMillisecondsSince(prevPoint.getTimestamp()) / 1000.0);
86 processValue(prevPoint, prevValue, timeLimitSeconds, currPoint, currValue);
89 else if (createByDistance)
91 currValue += DataPoint.calculateRadiansBetween(prevPoint, currPoint);
92 processValue(prevPoint, prevValue, distLimitRadians, currPoint, currValue);
95 prevPoint = currPoint;
96 prevValue = currValue;
100 // System.out.println(_pointsToAdd.size() + " markers to add...");
101 if (!_pointsToAdd.isEmpty())
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);
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();
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
127 private void processValue(DataPoint inPrevPoint, double inPrevValue, double inLimit,
128 DataPoint inCurrPoint, double inCurrValue)
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++)
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);
143 _previousMultiple = currMultiple;