Принадлежность точки выпуклому и невыпуклому многоугольникам — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Выпуклый многоугольник)
Строка 1: Строка 1:
 
{{ready}}
 
{{ready}}
 
== Выпуклый многоугольник ==
 
== Выпуклый многоугольник ==
Начнём с того, что выпуклый многоугольник нам задан как замкнутая полилиния. Поэтому для любой вершины этого многоугольника все остальные точки будут отсортированы по углу. Возьмём первую точку многоугольника и мысленно проведём от неё все лучи, содержащие диагонали. За логарифм можно пройтись бинпоиском по углам и {{Acronym|понять, в каком из них лежит точка|Для альтернативно одарённых: повороты должны различаться. А ещё кому-то может показаться неочевидным тот факт, что точка может лежать левее самой левой грани или правее самой правой. Это тоже надо сразу проверить}}. Когда мы нашли угол, за константное время {{Acronym|проверяем, с какой стороны от противолежащего первой точке ребра многоугольника лежит точка|для альтернативно одарённых: это проверяется поворотом}}. Итоговое время работы: <tex>O(\log n)</tex>.
+
Выпуклый многоугольник задан как замкнутая полилиния, поэтому для любой вершины этого многоугольника все остальные точки будут отсортированы по углу. Возьмём первую точку многоугольника и мысленно проведём от неё все лучи, содержащие диагонали. Бинпоиском за логарифм можно пройтись по углам и понять, в каком из них лежит точка. Когда найден угол, за константное время можно проверить, с какой стороны от противолежащего первой точке ребра многоугольника лежит точка.
 +
 
 +
Итоговый алгоритм:
 +
 
 +
* если искомая точка <tex>q</tex> лежит левее самой левой грани или правее самой правой, сразу возвращаем false
 +
* бинпоиском ищем такое ребро <tex>a_i a_{i+1}</tex>, не инцидентное самой первой точке <tex>a_0</tex> заданного многоугольника, что повороты точек <tex>a_0, a_i, q</tex> и <tex>a_0, a_{i+1}, q</tex> различаются
 +
* проверяем поворот точек <tex>a_i, a_{i+1}, q</tex>, если он левый — точка лежит внутри, если правый — снаружи
 +
 
 +
Итоговое время работы: <tex>O(\log n)</tex>.
  
 
== Невыпуклый многоугольник ==
 
== Невыпуклый многоугольник ==

Версия 14:29, 22 февраля 2014

Конспект готов к прочтению.

Выпуклый многоугольник

Выпуклый многоугольник задан как замкнутая полилиния, поэтому для любой вершины этого многоугольника все остальные точки будут отсортированы по углу. Возьмём первую точку многоугольника и мысленно проведём от неё все лучи, содержащие диагонали. Бинпоиском за логарифм можно пройтись по углам и понять, в каком из них лежит точка. Когда найден угол, за константное время можно проверить, с какой стороны от противолежащего первой точке ребра многоугольника лежит точка.

Итоговый алгоритм:

  • если искомая точка [math]q[/math] лежит левее самой левой грани или правее самой правой, сразу возвращаем false
  • бинпоиском ищем такое ребро [math]a_i a_{i+1}[/math], не инцидентное самой первой точке [math]a_0[/math] заданного многоугольника, что повороты точек [math]a_0, a_i, q[/math] и [math]a_0, a_{i+1}, q[/math] различаются
  • проверяем поворот точек [math]a_i, a_{i+1}, q[/math], если он левый — точка лежит внутри, если правый — снаружи

Итоговое время работы: [math]O(\log n)[/math].

Невыпуклый многоугольник

Если точка лежит на ребре, сразу вернём true.

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

Пустим луч, например, по иксу и за [math]O(n)[/math] переберём все рёбра и проверим их на пересечение с лучом. Как проверять: сначала проверим, что ордината точки лежит между ординатами концов ребра, затем посмотрим, до ребра или после него начался луч.

Луч может попасть в точку, при этом прохождение через точку учтётся два раза (по разу для каждого отрезка, к которым принадлежит точка). Иногда это и есть то, чего нам хочется (когда фигура находится выше или ниже луча), но иногда нам хочется учесть только один раз. Для этого делаем такую штуку: для каждого отрезка учитываем только верхнюю точку. Дальше всё очевидно.

Реализация