Collections.reverse(path);
// Perform diagonal optimization
for (int i = 0; i < path.size() - 1; i++) {
// Can only optimize straight paths so ignore diagonal ones
GridCoordinate lineDir = path.get(i + 1).subtract(path.get(i));
if (lineDir.isDiagonal()) continue;
// Look ahead for the last diagonal in the next run of diagonals
boolean inRun = false;
boolean found = false;
int j = i + 1;
GridCoordinate diagDir = null;
while (j < path.size() - 1) {
GridCoordinate jDir = path.get(j + 1).subtract(path.get(j));
// Start following a diagonal run
if (jDir.isDiagonal() && !inRun) {
inRun = true;
found = true;
diagDir = jDir;
// Ensure we can go diagonally from i
if (!diagMove(path.get(i), diagDir)) {
found = false;
break;
}
// Stop following a diagonal run
} else if (inRun && !jDir.equals(diagDir)) {
break;
// Only go in straight lines
} else if ((jDir.isDiagonal() && !jDir.equals(diagDir)) || (!jDir.isDiagonal() && !jDir.equals(lineDir))) {
found = false;
break;
}
j++;
}
// If a possible optimization has been found
if (found) {
// Get distance
GridCoordinate dist = path.get(j).subtract(path.get(i));
// Get perpendicular and parallel distance
int u; // Perpendicular
int v; // Parallel
if (Math.abs(lineDir.x()) == 1) {
u = Math.abs(dist.y());
v = Math.abs(dist.x());
} else {
u = Math.abs(dist.x());
v = Math.abs(dist.y());
}
ArrayList<GridCoordinate> segment = new ArrayList<GridCoordinate>();
// Found
boolean segFound = true;
// Iterate over columns to find an optimal path segment
for (int m = u; m > 0; m--) {
GridCoordinate tile = path.get(i).add(diagDir);
// Try to draw a better path
segment.clear();
segFound = true;
// Iterate over rows
for (int n = 1; n < v + m - u; n++) {
if (!fMap.isValid(tile) || !passable(tile)) {
segFound = false;
break;
}
segment.add(tile);
if (n < m) {
// Ensure that we can move diagonally
if (!diagMove(tile, diagDir)) {
segFound = false;
break;
}
tile = tile.add(diagDir);
}
else tile = tile.add(lineDir);
}
if (segFound) break;
// Reduce j, the possible end point
j--;
}