Как четно-нечетный алгоритм считает ребра полигонов?

Мне интересно, как работает четно-нечетный алгоритм для определения точки в сложном многоугольнике.

Что я знаю прямо сейчас, так это то, что он будет выполнять горизонтальный поиск от самого левого края до точки и подсчитывать количество затронутых ребер.

Однако что произойдет, если затронутые ребра находятся на пересечении двух ребер? как это считается?

Пример полигонов:

Примеры многоугольников


person Shing Chi Ng    schedule 10.10.2018    source источник
comment
Этот вопрос не по теме для SO.   -  person jmargolisvt    schedule 10.10.2018
comment
Не обязательно.   -  person m69 ''snarky and unwelcoming''    schedule 10.10.2018
comment
Это лучшее обсуждение многоугольник, о котором я знаю. Обсуждаются пограничные случаи и представлена ​​разработка эффективного алгоритма.   -  person RaffleBuffle    schedule 10.10.2018


Ответы (2)


Мне нравится делать это так, как для целых чисел, так и для координат с плавающей запятой:

  • для негоризонтальных сегментов каждый сегмент включает самую нижнюю точку, но не самую верхнюю точку.

  • вообще не включайте горизонтальные сегменты в подсчет четных-нечетных.

Это гарантирует, что подсчет четных-нечетных будет правильным для каждой точки внутри полигона и каждой точки снаружи, но он не совсем согласован в отношении точек точно на границе. Если это важно для вас, вы можете добавить правило, согласно которому любая точка, которая фактически находится на сегменте, включается в полигон.

person Matt Timmermans    schedule 10.10.2018

есть и другие способы решения этой проблемы, но самый безопасный, который я знаю, это

Слегка измените направление лучей

это численно безопасно, но реализация не так проста, как кажется. Либо измените весь луч и вычислите с самого начала, либо измените где-нибудь перед рассматриваемым попаданием.

изменить направление луча

Вы должны убедиться, что вы не образуете тесные петли, например, зигзагообразным рисунком (таким образом, вы чередуете повороты CW и CCW в пределах некоторого конуса от исходного направления).

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

Изменение направления луча всегда безопасно, поскольку позволяет избежать сингулярностей и численной нестабильности.

Кстати. Этот алгоритм внутри многоугольника, который вы используете, хорошо известен под названием Hit test.

person Spektre    schedule 10.10.2018
comment
Перенаправленный луч может попасть в другую вершину, это не пуленепробиваемо. - person Yves Daoust; 10.10.2018
comment
@YvesDaoust Да, в таком случае вы можете снова изменить направление ... Я учил, что это было очевидно (из шаблона ZIG ZAG). Я знаю, что реализация этого намного медленнее, чем другие методы, как в другом ответе, но это единственный безопасный способ, которым я знать о. Даже подход из другого ответа представляет собой риск численной стабильности и не работает с поплавками при определенных условиях. - person Spektre; 10.10.2018
comment
Подход, описанный @Matt Timmermans, доказуемо безопасен и не требует деградации данных. Также можно доказать, что при очень простых требованиях арифметики (по сути, монотонность) не возникает числовых проблем (нет смысла сходить с ума). - person Yves Daoust; 10.10.2018
comment
@YvesDaoust На бумаге может быть, но в реальной жизни иногда даже ошибка ulp может все испортить. Особенно, если масштабирование или любое другое преобразование присутствует не только в сырых данных. В таком случае иногда касание вершины может быть правильно обнаружено только в одном из ребер, а не в обоих, вызывая хаос. Эти случаи требуют специальной обработки и небезопасны, если рядом есть другие не соприкасающиеся вершины (очень близкие края к каждому, как почти соприкасающиеся винты спирали и т. д.), но такие многоугольники не являются обычными, которые используются, однако я имею дело с их иногда в моей работе, - person Spektre; 10.10.2018
comment
Нет, ulp ничего не испортит. - person Yves Daoust; 10.10.2018
comment
@YvesDaoust также другой ответ не касается точки касания зуба, а это касается. - person Spektre; 10.10.2018
comment
Я не думаю, что вы поняли это решение. - person Yves Daoust; 10.10.2018
comment
@YvesDaoust, скорее всего, поскольку я до сих пор не понимаю, как это может работать с зубами, касающимися лучей. - person Spektre; 10.10.2018