Вы можете взять ограничивающий прямоугольник многоугольника (min-max x, y координаты) и построить сетку внутри прямоугольника. Затем для каждой ячейки запомните все линии, которые пересекают ячейку.
Найдите пересечение, подобное этому:
- Узнайте, в какую ячейку луч попадает первым (O (1))
- Используйте Алгоритм обхода сетки , чтобы "нарисовать" луч через сетку. Когда вы нажмете на непустую ячейку, проверьте все ее линии, проверьте, находится ли пересечение внутри ячейки, и выберите самое близкое пересечение. Если все пересечения находятся за пределами ячейки, продолжайте (это O (длина сетки)).
Вы также можете сделать иерархическую сетку (т. Е. quadtree - дерево, о котором вы просили) и пройти по нему, используя тот же алгоритм. Это делается при трассировке лучей в 3D , а временная сложность составляет O (sqrt (N)).
Или используйте подход, который я использовал в моем raytracer:
- Построение quadtree , содержащего строки (построение quadtree описано в статье) - вы разделяете узлы (= области), если они содержат слишком много объектов, на 4 подузла (подобласти)
Соберите все листовые узлы дерева квадратов, на которые попал луч:
Вычислить пересечение луча с прямоугольником (не сложно) для корня. Если луч попал в корень, рекурсивно продолжите работу с его потомками.
Крутая вещь в этом заключается в том, что когда узел дерева не ударил, вы пропустили обработку всего поддерева (потенциально большой прямоугольной области).
В конце концов, это эквивалентно обходу сетки - вы собираете наименьшие ячейки на пути луча, а затем проверяете все объекты в них на предмет пересечения. Вам просто нужно протестировать все из них и выбрать ближайший перекресток (чтобы вы исследовали все линии на пути луча).
Это O (sqrt (N)).
При обходе сетки, когда вы найдете пересечение, вы можете остановить поиск. Чтобы достичь этого с помощью обхода дерева квадрантов, вам нужно будет найти детей в правильном порядке - либо отсортировать 4 прямоугольных пересечения по расстоянию, либо хитро пересечь сетку из 4 ячеек (и мы вернулись к обходу).
Это просто другой подход, сравнительно такой же сложный для реализации, как мне кажется, и хорошо работающий (я проверил его на реальных данных - O (sqrt (N))). Опять же, вы только выиграете от этого подхода, если у вас будет хотя бы пара линий, когда у многоугольника 10 ребер, выигрыш по сравнению с простым тестированием всех из них будет небольшим, я думаю.