1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
package tim.prune.function;
import javax.swing.JOptionPane;
import tim.prune.App;
import tim.prune.I18nManager;
import tim.prune.data.DataPoint;
import tim.prune.data.Track;
import tim.prune.undo.UndoInterpolate;
/**
* Function to interpolate between the points in a range
*/
public class InterpolateFunction extends SingleNumericParameterFunction
{
/**
* Constructor
* @param inApp app object
*/
public InterpolateFunction(App inApp) {
super(inApp, 1, 1000);
}
/** @return name key */
public String getNameKey() {
return "function.interpolate";
}
/** @return description key for input parameter */
public String getDescriptionKey() {
return "dialog.interpolate.parameter.text";
}
/** @return current (or default) parameter value */
public int getCurrentParamValue() {
return 0;
}
/**
* Perform the operation
*/
public void begin()
{
// not needed, we just use the completeFunction method instead
}
/**
* Complete the function after the input parameter has been chosen
*/
public void completeFunction(int inParam)
{
// Firstly, work out whether the selected range only contains waypoints or not
final int startIndex = _app.getTrackInfo().getSelection().getStart();
final int endIndex = _app.getTrackInfo().getSelection().getEnd();
boolean betweenWaypoints = false;
// if there are only waypoints, then ask whether to interpolate them
if (!selectedRangeHasTrackpoints(_app.getTrackInfo().getTrack(), startIndex, endIndex))
{
int answer = JOptionPane.showConfirmDialog(_parentFrame,
I18nManager.getText("dialog.interpolate.betweenwaypoints"),
I18nManager.getText(getNameKey()), JOptionPane.YES_NO_OPTION);
if (answer == JOptionPane.NO_OPTION) {
// user said no, so nothing to do
return;
}
betweenWaypoints = true;
}
if (startIndex < 0 || endIndex < 0 || endIndex <= startIndex) {
return;
}
// construct new point array with the interpolated points
final int numToAdd = inParam;
final Track track = _app.getTrackInfo().getTrack();
final int maxToAdd = (endIndex-startIndex) * numToAdd;
final int extendedSize = track.getNumPoints() + maxToAdd;
DataPoint[] oldPoints = track.cloneContents();
DataPoint[] newPoints = new DataPoint[extendedSize];
// Copy points before
System.arraycopy(oldPoints, 0, newPoints, 0, startIndex);
// Loop, copying points and interpolating
int destIndex = startIndex;
DataPoint prevPoint = null;
for (int i=startIndex; i<= endIndex; i++)
{
DataPoint p = _app.getTrackInfo().getTrack().getPoint(i);
if (prevPoint != null && ((p.isWaypoint() && betweenWaypoints) || (!p.isWaypoint() && !p.getSegmentStart())))
{
// interpolate between the previous point and this one
DataPoint[] addition = prevPoint.interpolate(p, numToAdd);
System.arraycopy(addition, 0, newPoints, destIndex, numToAdd);
destIndex += numToAdd;
}
// copy point
newPoints[destIndex] = p;
destIndex++;
if (!p.isWaypoint() || betweenWaypoints)
{
prevPoint = p;
}
else if (!p.isWaypoint()) {
prevPoint = null;
}
// If it's a waypoint, then keep the old prevPoint
}
final int totalInserted = destIndex - endIndex - 1;
// Copy the points after the selected range
System.arraycopy(oldPoints, endIndex, newPoints, destIndex-1, track.getNumPoints()-endIndex);
// If necessary, make a new array of the correct size and do another arraycopy into it
final int newTotalPoints = track.getNumPoints() + totalInserted;
if (newTotalPoints != newPoints.length)
{
DataPoint[] croppedPoints = new DataPoint[newTotalPoints];
System.arraycopy(newPoints, 0, croppedPoints, 0, newTotalPoints);
newPoints = croppedPoints;
}
// Make undo object
UndoInterpolate undo = new UndoInterpolate(_app.getTrackInfo(), totalInserted);
// Replace track with new points array
if (track.replaceContents(newPoints))
{
_app.completeFunction(undo, I18nManager.getText("confirm.interpolate"));
// Alter selection
_app.getTrackInfo().getSelection().selectRange(startIndex, endIndex + totalInserted);
}
}
/**
* Check if the given Track has trackpoints in the specified range
* @param inTrack track object
* @param inStart start index
* @param inEnd end index
* @return true if there are any non-waypoints in the range
*/
private static boolean selectedRangeHasTrackpoints(Track inTrack, int inStart, int inEnd)
{
for (int i=inStart; i<= inEnd; i++)
{
DataPoint p = inTrack.getPoint(i);
if (p != null && !p.isWaypoint()) {
return true;
}
}
return false;
}
}
|