1 package tim.prune.function;
3 import javax.swing.JOptionPane;
6 import tim.prune.I18nManager;
7 import tim.prune.data.DataPoint;
8 import tim.prune.data.Track;
9 import tim.prune.undo.UndoInterpolate;
12 * Function to interpolate between the points in a range
14 public class InterpolateFunction extends SingleNumericParameterFunction
18 * @param inApp app object
20 public InterpolateFunction(App inApp) {
21 super(inApp, 1, 1000);
24 /** @return name key */
25 public String getNameKey() {
26 return "function.interpolate";
29 /** @return description key for input parameter */
30 public String getDescriptionKey() {
31 return "dialog.interpolate.parameter.text";
34 /** @return current (or default) parameter value */
35 public int getCurrentParamValue() {
40 * Perform the operation
44 // not needed, we just use the completeFunction method instead
48 * Complete the function after the input parameter has been chosen
50 public void completeFunction(int inParam)
52 // Firstly, work out whether the selected range only contains waypoints or not
53 final int startIndex = _app.getTrackInfo().getSelection().getStart();
54 final int endIndex = _app.getTrackInfo().getSelection().getEnd();
55 boolean betweenWaypoints = false;
56 // if there are only waypoints, then ask whether to interpolate them
57 if (!selectedRangeHasTrackpoints(_app.getTrackInfo().getTrack(), startIndex, endIndex))
59 int answer = JOptionPane.showConfirmDialog(_parentFrame,
60 I18nManager.getText("dialog.interpolate.betweenwaypoints"),
61 I18nManager.getText(getNameKey()), JOptionPane.YES_NO_OPTION);
62 if (answer == JOptionPane.NO_OPTION) {
63 // user said no, so nothing to do
66 betweenWaypoints = true;
69 if (startIndex < 0 || endIndex < 0 || endIndex <= startIndex) {
73 // construct new point array with the interpolated points
74 final int numToAdd = inParam;
75 final Track track = _app.getTrackInfo().getTrack();
76 final int maxToAdd = (endIndex-startIndex) * numToAdd;
77 final int extendedSize = track.getNumPoints() + maxToAdd;
78 DataPoint[] oldPoints = track.cloneContents();
79 DataPoint[] newPoints = new DataPoint[extendedSize];
81 System.arraycopy(oldPoints, 0, newPoints, 0, startIndex);
82 // Loop, copying points and interpolating
83 int destIndex = startIndex;
84 DataPoint prevPoint = null;
85 for (int i=startIndex; i<= endIndex; i++)
87 DataPoint p = _app.getTrackInfo().getTrack().getPoint(i);
88 if (prevPoint != null && ((p.isWaypoint() && betweenWaypoints) || (!p.isWaypoint() && !p.getSegmentStart())))
90 // interpolate between the previous point and this one
91 DataPoint[] addition = prevPoint.interpolate(p, numToAdd);
92 System.arraycopy(addition, 0, newPoints, destIndex, numToAdd);
93 destIndex += numToAdd;
96 newPoints[destIndex] = p;
98 if (!p.isWaypoint() || betweenWaypoints)
102 else if (!p.isWaypoint()) {
105 // If it's a waypoint, then keep the old prevPoint
107 final int totalInserted = destIndex - endIndex - 1;
108 // Copy the points after the selected range
109 System.arraycopy(oldPoints, endIndex, newPoints, destIndex-1, track.getNumPoints()-endIndex);
111 // If necessary, make a new array of the correct size and do another arraycopy into it
112 final int newTotalPoints = track.getNumPoints() + totalInserted;
113 if (newTotalPoints != newPoints.length)
115 DataPoint[] croppedPoints = new DataPoint[newTotalPoints];
116 System.arraycopy(newPoints, 0, croppedPoints, 0, newTotalPoints);
117 newPoints = croppedPoints;
121 UndoInterpolate undo = new UndoInterpolate(_app.getTrackInfo(), totalInserted);
122 // Replace track with new points array
123 if (track.replaceContents(newPoints))
125 _app.completeFunction(undo, I18nManager.getText("confirm.interpolate"));
127 _app.getTrackInfo().getSelection().selectRange(startIndex, endIndex + totalInserted);
132 * Check if the given Track has trackpoints in the specified range
133 * @param inTrack track object
134 * @param inStart start index
135 * @param inEnd end index
136 * @return true if there are any non-waypoints in the range
138 private static boolean selectedRangeHasTrackpoints(Track inTrack, int inStart, int inEnd)
140 for (int i=inStart; i<= inEnd; i++)
142 DataPoint p = inTrack.getPoint(i);
143 if (p != null && !p.isWaypoint()) {