Вы можете использовать растровый подход. Прямоугольник представляет собой замкнутый выпуклый многоугольник, поэтому достаточно сохранить крайний левый и крайний правый пиксели для каждой горизонтальной строки развертки. (И верхняя, и нижняя строки развертки тоже.)
Алгоритм Брезенхема пытается нарисовать тонкую, визуально приятную линию без соседних ячеек в меньшем измерении. Нам нужен алгоритм, который посещает каждую ячейку, через которую проходят края многоугольника. Основная идея состоит в том, чтобы найти начальную ячейку (x, y)
для каждого края, а затем настроить x
всякий раз, когда край пересекает вертикальную границу, и корректировать y
, когда он пересекает горизонтальную границу.
Мы можем представить пересечения с помощью нормализованной координаты s
, которая движется вдоль края и равна 0,0 в первом узле n1
и 1,0 во втором узле n2
.
var x = Math.floor(n1.x / cellsize);
var y = Math.floor(n1.y / cellsize);
var s = 0;
Вертикальные вставки могут быть представлены как эквидистантные шаги с dsx
от начального sx
.
var dx = n2.x - n1.x;
var sx = 10; // default value > 1.0
// first intersection
if (dx < 0) sx = (cellsize * x - n1.x) / dx;
if (dx > 0) sx = (cellsize * (x + 1) - n1.x) / dx;
var dsx = (dx != 0) ? grid / Math.abs(dx) : 0;
То же самое и с горизонтальными перекрестками. Значение по умолчанию больше 1.0 учитывает случаи горизонтальных и вертикальных линий. Добавьте первую точку к данным развертки:
add(scan, x, y);
Затем мы можем посетить следующую соседнюю ячейку, посмотрев на следующее пересечение с наименьшим s
.
while (sx <= 1 || sy <= 1) {
if (sx < sy) {
sx += dsx;
if (dx > 0) x++; else x--;
} else {
sy += dsy;
if (dy > 0) y++; else y--;
}
add(scan, x, y);
}
Сделайте это для всех четырех краев и с одними и теми же данными развертки. Затем заполните все ячейки:
for (var y in scan) {
var x = scan[y].min;
var xend = scan[y].max + 1;
while (x < xend) {
// do something with cell (x, y)
x++;
}
}
(Я только просмотрел ссылки, предоставленные MBo. Кажется, что подход, представленный в этой статье, по сути такой же, как и мой. Если так, извините, пожалуйста, за повторяющийся ответ, но после работы над этим я подумал, что могу также опубликовать его.)
10.05.2014