Ответ Джеймса довольно крутой, но, как он прокомментировал, он немного искажает линию. Другая простая модификация оригинального Брезенхэма рисует линию без диагональных шагов, которая ближе к «реальной» линии.
Это реализация оригинального алгоритма Брезенхэма:
public void line(int x0, int y0, int x1, int y1, int value) {
int xDist = Math.abs(x1 - x0);
int yDist = -Math.abs(y1 - y0);
int xStep = (x0 < x1 ? +1 : -1);
int yStep = (y0 < y1 ? +1 : -1);
int error = xDist + yDist;
plot(x0, y0, value);
while (x0 != x1 || y0 != y1) {
if (2*error > yDist) {
// horizontal step
error += yDist;
x0 += xStep;
}
if (2*error < xDist) {
// vertical step
error += xDist;
y0 += yStep;
}
plot(x0, y0, value);
}
}
Модификация заключается в простом выполнении либо горизонтального или вертикального шага, но не обоих, в зависимости от того, ближе ли индикатор ошибки к горизонтальному или вертикальному шагу:
public void lineNoDiag(int x0, int y0, int x1, int y1, int value) {
int xDist = Math.abs(x1 - x0);
int yDist = -Math.abs(y1 - y0);
int xStep = (x0 < x1 ? +1 : -1);
int yStep = (y0 < y1 ? +1 : -1);
int error = xDist + yDist;
plot(x0, y0, value);
while (x0 != x1 || y0 != y1) {
if (2*error - yDist > xDist - 2*error) {
// horizontal step
error += yDist;
x0 += xStep;
} else {
// vertical step
error += xDist;
y0 += yStep;
}
plot(x0, y0, value);
}
}
Это эффективно выбирает тип шага, который минимизирует ошибку, в результате чего получается линия, которая ближе к реальной линии.
Код написан на Java, но он должен быть легко переносим на PHP. Я не проверил его полностью, но он должен работать так же хорошо, как и оригинальный Брезенхем. Это может быть даже немного быстрее.