ответ Джеймса довольно прохладно, но, как он отметил, что перекосы линию немного. Другая простая модификация оригинального Bresenham рисует линию без диагональных шагов, которая ближе к «реальной» линии.
Это реализация оригинального алгоритма Bresenham:
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. Я не тестировал его полностью, но он должен работать так же хорошо, как оригинальный Bresenham. Это может быть даже немного быстрее.
Фактически, это немного исказило бы вашу линию. Очевидный центр будет в среднем на полтора пикселя выше того, что вы ожидаете. Если это имеет значение, возможно, вам придется изменить расчет ошибок. – James
Работы perfekt. Спасибо!! – MorbZ