Я убираю старый проект. Одна из вещей, которые он должен был сделать, - это иметь декартовую сетку и два квадрата на сетке, найти список всех квадратов, через которые пройдет линия, соединяющая центр этих двух квадратов.
Частным случаем здесь является то, что все начальные и конечные точки ограничены точным центром квадратов/ячеек.
Вот несколько примеров - с парами начальных и конечных точек выборки. Затененные квадраты - это те, которые должны быть возвращены соответствующим вызовом функции
удалена мертвая ссылка ImageShack - пример
Исходные и конечные точки обозначаются квадратами, в которых они находятся. На приведенном выше рисунке, считая, что нижний левый [1,1]
, строка в правом нижнем углу будет обозначена как [6,2]
до [9,5]
.
То есть, из (центра) квадрата на шестом столбце слева, на втором ряду от дна до (центра) квадрата на девятом столбце слева, в пятом ряду от внизу
Что действительно не кажется таким сложным. Тем не менее, я как-то, казалось, нашел сложный алгоритм онлайн и реализовал его.
Я действительно помню, что это было очень, очень быстро. Как, оптимизированный для сотен или тысяч раз за кадры быстро.
В основном, он прыгал с границы на границу квадратов вдоль линии (точки, где линия пересекает линии сетки). Он знал, где следующая точка пересечения, видя, какая точка пересечения была ближе - горизонтальная или вертикальная - и переместилась на следующую следующую.
Какой вид в порядке, но фактическая реализация оказалась довольно не очень красивой, и я боюсь, что уровень оптимизации может быть слишком высоким для того, что мне практически нужно (я вызывая этот алгоритм обхода, возможно, пять или шесть раз в минуту).
Существует ли простой, понятный и прозрачный алгоритм прямого трассировки сетки?
В программных терминах:
def traverse(start_point,end_point)
# returns a list of all squares that this line would pass through
end
где заданные координаты идентифицируют сами квадраты.
Некоторые примеры:
traverse([0,0],[0,4])
# => [0,0], [0,1], [0,2], [0,3], [0,4]
traverse([0,0],[3,2])
# => [0,0], [0,1], [1,1], [2,1], [2,2], [3,2]
traverse([0,0],[3,3])
# => [0,0], [1,1], [2,2], [3,3]
Обратите внимание, что линии, которые перемещаются непосредственно через углы, не должны содержать квадратов на "крыле" линии.
(Хороший ol 'Bresenham может работать здесь, но он немного отстает от того, что я хочу. Насколько я знаю, чтобы использовать его, мне в основном пришлось бы применить его к линии, а затем сканировать каждый квадрат на сетке для истины или false. Невозможно - или, по крайней мере, неэлегантно - для больших сеток)
(Я пересматриваю алгоритмы Bresenham и Bresenham, из-за неправильного понимания).
Для пояснения одно из возможных применений этого было бы, если бы я хранили все мои объекты в игре внутри зон (сетка), и у меня есть луч, и я хочу посмотреть, к каким объектам попадает луч. Используя этот алгоритм, я мог бы проверить луч только на объекты, находящиеся внутри заданных зон, вместо каждого объекта на карте.
фактическое использование этого в моем приложении заключается в том, что каждый элемент имеет связанный с ним эффект, и объект перемещается по данному сегменту линии за каждый ход. На каждом шагу необходимо проверить, с какими квадратами проходит объект, и, следовательно, какие эффекты влияют на объект.
Обратите внимание, что на данный момент текущая реализация у меня работает. Этот вопрос в основном предназначен для любопытства. Должен быть более простой способ... как-то... для такой простой проблемы.
Что именно я ищу? Что-то концептуально/аккуратно и чисто. Кроме того, я понял, что из-за того, что я точно указываю, все начальные и конечные точки всегда будут находиться в центре квадратов/ячеек; так что, возможно, что-то, что воспользуется этим, также будет опрятным.