package squidpony.squidmath;
import java.util.LinkedList;
import java.util.List;
/**
* A simple line-drawing algorithm that only takes orthogonal steps; may be useful for LOS in games that use Manhattan
* distances for measurements.
* Algorithm is from http://www.redblobgames.com/grids/line-drawing.html#stepping , thanks Amit!
* Created by Tommy Ettinger on 1/10/2016.
*/
public class OrthoLine {
/**
* Draws a line from (startX, startY) to (endX, endY) using only N/S/E/W movement. Returns a List of Coord in order.
*
* @param startX x of starting point
* @param startY y of starting point
* @param endX x of ending point
* @param endY y of ending point
* @return List of Coord, including (startX, startY) and (endX, endY) and all points walked between
*/
public static List<Coord> line(int startX, int startY, int endX, int endY) {
int dx = endX - startX, dy = endY - startY, nx = Math.abs(dx), ny = Math.abs(dy);
int signX = (dx > 0) ? 1 : -1, signY = (dy > 0) ? 1 : -1, workX = startX, workY = startY;
LinkedList<Coord> drawn = new LinkedList<>();
drawn.add(Coord.get(startX, startY));
for (int ix = 0, iy = 0; ix < nx || iy < ny; ) {
if ((0.5f + ix) / nx < (0.5 + iy) / ny) {
workX += signX;
ix++;
} else {
workY += signY;
iy++;
}
drawn.add(Coord.get(workX, workY));
}
return drawn;
}
/**
* Draws a line from start to end using only N/S/E/W movement. Returns a List of Coord in order.
* @param start starting point
* @param end ending point
* @return List of Coord, including start and end and all points walked between
*/
public static List<Coord> line(Coord start, Coord end)
{
return line(start.x, start.y, end.x, end.y);
}
/**
* Draws a line from (startX, startY) to (endX, endY) using only N/S/E/W movement. Returns an array of Coord in order.
*
* @param startX x of starting point
* @param startY y of starting point
* @param endX x of ending point
* @param endY y of ending point
* @return array of Coord, including (startX, startY) and (endX, endY) and all points walked between
*/
public static Coord[] line_(int startX, int startY, int endX, int endY) {
int dx = endX - startX, dy = endY - startY, nx = Math.abs(dx), ny = Math.abs(dy);
int signX = (dx > 0) ? 1 : -1, signY = (dy > 0) ? 1 : -1, workX = startX, workY = startY;
Coord[] drawn = new Coord[nx + ny + 1];
drawn[0] = Coord.get(startX, startY);
for (int i = 1, ix = 0, iy = 0; ix < nx || iy < ny; i++) {
if ((0.5f + ix) / nx < (0.5 + iy) / ny) {
workX += signX;
ix++;
} else {
workY += signY;
iy++;
}
drawn[i] = Coord.get(workX, workY);
}
return drawn;
}
/**
* Draws a line from start to end using only N/S/E/W movement. Returns a List of Coord in order.
* @param start starting point
* @param end ending point
* @return List of Coord, including start and end and all points walked between
*/
public static Coord[] line_(Coord start, Coord end)
{
return line_(start.x, start.y, end.x, end.y);
}
}