2011-02-02 3 views
16

У меня есть объект System.Windows.Shapes.Polygon, макет которого полностью определяется рядом точек. Мне нужно определить, является ли этот многоугольник самопересекающимся; т. е. если какая-либо из сторон многоугольника пересекает любую из сторон в точке, не являющейся вершиной. Есть ли простой/быстрый способ вычислить это?Проверьте, не является ли многоугольник самопересекающимся

ответ

27
  • Легкие, медленный, низкий объем памяти: сравнить каждый сегмент от всех остальных и проверить наличие пересечений. Сложность O (n).

  • Немного быстрее, область памяти средней памяти (модифицированная версия выше): храните края в пространственных «ведрах», а затем выполняйте выше алгоритм на основе каждого ковша. Сложность O (n/m) для m ведра (при условии равномерного распределения).

  • Быстрого & высокой память след: использовать пространственную хэш-функцию для разделения края в ведро. Проверьте наличие столкновений. Сложность O (n).

  • Быстрый & низкая память след: использовать алгоритм развертки строки, такие, как один описанный here (или here). Сложность O (п журнал п)

Последняя моя любимая, как это имеет хорошую скорость - баланс памяти, особенно Bentley-Ottmann algorithm. Реализация также не слишком сложна.

+1

Я пытаюсь разгадать последний алгоритм, когда мы говорим; особенно, у меня возникают проблемы с отслеживанием значения/цели структуры T. – GWLlosa

+0

* T * - это структура, которая содержит отрезки линий, пересекающие линию развертки * L *. Наиболее эффективной структурой будет двоичное дерево поиска (см. Также [алгоритм Бентли-Оттмана] (http://en.wikipedia.org/wiki/Bentley%E2%80%93Ottmann_algorithm)). –

+1

Я добавил еще одну [ссылку, где алгоритм Бентли-Оттмана] (http://softsurfer.com/Archive/algorithm_0108/algorithm_0108.htm) описывается иллюстрациями. –

3

Проверьте, не пересекаются ли какие-либо пары непересекающихся сегментов линии.

+0

Все они должны пересекаться в вершинах; вопрос тогда становится тем, что самый быстрый способ проверить не вершинное пересечение между произвольным набором отрезков линии. – GWLlosa

+0

Хорошая точка, отредактированная, чтобы проверить, пересекаются ли непересекающиеся сегменты. Я не думаю, что есть встроенный метод, вам придется написать метод. Начните с получения Polygon.Points –

+0

Вы не имеете в виду ** открытые ** сегменты линии? Я никогда не слышал о несмежных сегментах линии. –

2

Для полноты я добавлю еще один алгоритм для этого обсуждения.

Предполагая, что читатель знает о выровненных по горизонтали ограничительных прямоугольниках (это Google, если нет). Быстро найти пары ребер, столкнувшихся с AABB, можно с помощью «Sweep and Prune Algorithm». (погугли это). Затем на этих парах вызывается процедура пересечения.

Преимущество в том, что вы можете даже пересечь не прямолинейный край (круги и сплайны), а подход является более общим, хотя и почти таким же эффективным.

Смежные вопросы