Ниже приведен алгоритм типа Брезенхема, который рисует 4-соединенные линии.Код написан на Python, но я думаю, что его легко понять, даже если вы не знаете язык.
def line(x0, y0, x1, y1, color):
dx = abs(x1 - x0) # distance to travel in X
dy = abs(y1 - y0) # distance to travel in Y
if x0 < x1:
ix = 1 # x will increase at each step
else:
ix = -1 # x will decrease at each step
if y0 < y1:
iy = 1 # y will increase at each step
else:
iy = -1 # y will decrease at each step
e = 0 # Current error
for i in range(dx + dy):
draw_pixel(x0, y0, color)
e1 = e + dy
e2 = e - dx
if abs(e1) < abs(e2):
# Error will be smaller moving on X
x0 += ix
e = e1
else:
# Error will be smaller moving on Y
y0 += iy
e = e2
Идея состоит в том, что для рисования линии вы должны увеличивать X и Y с соотношением, которое соответствуетDX / DY теоретической линии.Для этого я начинаю с error variable e
, инициализируемого 0 (мы находимся на линии), и на каждом шаге я проверяю, является ли ошибка ниже, если я только увеличиваю X или если я только увеличиваюY (проверка Брезенхэма - выбор между изменением только X или X и Y).
Наивной версией для этой проверки будет добавление 1/dy
или 1/dx
, но умножение всех приращений на dx*dy
позволяет использовать только целочисленные значения, что улучшает как скорость, так и точность, а также устраняет необходимость в особых случаях для dx==0
или dy==0
, что упрощает логику.Конечно, поскольку мы ищем ошибку пропорции, использование масштабированного приращения не влияет на результат.
Независимо от того, является ли линейный квадрант, две возможности приращения всегда будут иметь различный эффект знака ошибки... поэтому мой произвольный выбор заключался в увеличении ошибки для шага X и уменьшении ошибки для шага Y.
Переменные ix
и iy
являются реальными направлениями, необходимыми для линии (либо+1 или -1) в зависимости от того, являются ли начальные координаты ниже или выше, чем конечные координаты.
Число пикселей, которые нужно нарисовать в 4-соединенной линии, очевидно, равно dx+dy
, поэтому я просто делаюповторяйте это много раз, чтобы нарисовать линию, вместо того, чтобы проверять, добрался ли я до конечной точки.Обратите внимание, что этот алгоритм рисует все пиксели, кроме последнего;если вам также нужен этот последний пиксель, то после окончания цикла необходимо добавить дополнительный вызов draw_pixel
.
Пример результата вышеописанной реализации можно увидеть на следующем рисунке