+
+ /**
+ * Do the collection and sorting of the waypoints
+ * @param inRearrangeOption beginning or end
+ * @param inSortOption optional sort criterion
+ * @return true on success
+ */
+ private boolean collectWaypoints(Rearrange inRearrangeOption, SortMode inSortOption)
+ {
+ // Check for mixed data, numbers of waypoints & nons
+ int numWaypoints = 0, numNonWaypoints = 0;
+ boolean wayAfterNon = false, nonAfterWay = false;
+ Track track = _app.getTrackInfo().getTrack();
+ final int numPoints = track.getNumPoints();
+ DataPoint[] waypoints = new DataPoint[numPoints];
+ DataPoint[] nonWaypoints = new DataPoint[numPoints];
+ DataPoint point = null;
+ for (int i=0; i<numPoints; i++)
+ {
+ point = track.getPoint(i);
+ if (point.isWaypoint())
+ {
+ waypoints[numWaypoints] = point;
+ numWaypoints++;
+ wayAfterNon |= (numNonWaypoints > 0);
+ }
+ else
+ {
+ nonWaypoints[numNonWaypoints] = point;
+ numNonWaypoints++;
+ nonAfterWay |= (numWaypoints > 0);
+ }
+ }
+
+ // Exit if the data is already in the specified order
+ final boolean wpsToStart = (inRearrangeOption == Rearrange.TO_START);
+ final boolean doSort = (inSortOption != SortMode.DONT_SORT);
+ if (numWaypoints == 0 || numNonWaypoints == 0
+ || (wpsToStart && !wayAfterNon && nonAfterWay && !doSort)
+ || (!wpsToStart && wayAfterNon && !nonAfterWay && !doSort)
+ || inRearrangeOption == Rearrange.TO_NEAREST)
+ {
+ return false;
+ }
+ // Note: it could still be that the rearrange and sort has no effect, but we don't know yet
+ // Make a copy of the waypoints array first so we can compare it with after the sort
+ DataPoint[] origWaypoints = new DataPoint[numPoints];
+ System.arraycopy(waypoints, 0, origWaypoints, 0, numPoints);
+
+ if (doSort && numWaypoints > 1)
+ {
+ // Sort the waypoints array
+ WaypointComparer comparer = new WaypointComparer(inSortOption);
+ Arrays.sort(waypoints, comparer);
+ final boolean sortDidNothing = areArraysSame(origWaypoints, waypoints);
+ if (sortDidNothing && (numNonWaypoints == 0
+ || (wpsToStart && !wayAfterNon && nonAfterWay)
+ || (!wpsToStart && wayAfterNon && !nonAfterWay)))
+ {
+ return false;
+ }
+ }
+
+ // Copy the arrays into an array in the specified order
+ DataPoint[] neworder = new DataPoint[numPoints];
+ if (wpsToStart)
+ {
+ System.arraycopy(waypoints, 0, neworder, 0, numWaypoints);
+ System.arraycopy(nonWaypoints, 0, neworder, numWaypoints, numNonWaypoints);
+ }
+ else
+ {
+ System.arraycopy(nonWaypoints, 0, neworder, 0, numNonWaypoints);
+ System.arraycopy(waypoints, 0, neworder, numNonWaypoints, numWaypoints);
+ }
+ // Give track the new point order
+ return track.replaceContents(neworder);
+ }
+
+ /**
+ * Compare two arrays of DataPoints and see if they're identical or not
+ * @param inOriginal original array of points
+ * @param inSorted array of points after sorting
+ * @return true if the two arrays have the same points in the same order
+ */
+ private static boolean areArraysSame(DataPoint[] inOriginal, DataPoint[] inSorted)
+ {
+ if (inOriginal == null && inSorted == null) return true; // both null
+ if (inOriginal == null || inSorted == null) return false; // only one of them null
+ if (inOriginal.length != inSorted.length) return false;
+ // Loop over all points
+ for (int i=0; i<inOriginal.length; i++)
+ {
+ DataPoint origPoint = inOriginal[i];
+ DataPoint sortedPoint = inSorted[i];
+ if ((origPoint != null || sortedPoint != null)
+ && (origPoint != sortedPoint))
+ {
+ return false; // points different
+ }
+ }
+ // Must be all the same
+ return true;
+ }