Участник:Liebeann/Принадлежность точки многоугольнику: различия между версиями

Материал из Алговики
Перейти к навигации Перейти к поиску
мНет описания правки
Нет описания правки
Строка 8: Строка 8:


'''Обозначения:'''
'''Обозначения:'''
* <math>int(P)</math> &mdash; множество строго внутренних точек многоугольника <math>P</math>
* <math>int(P)</math> &mdash; множество строго внутренних точек многоугольника <math>P</math>;
* <math>V(P) = \{v_0, v_2, \dots, v_{N - 1} \}</math> &mdash; упорядоченноый набор точек, являющихся вершинами многоугольника <math>P</math>
* <math>V(P) = \{v_0, v_2, \dots, v_{N - 1} \}</math> &mdash; упорядоченноый набор точек, являющихся вершинами многоугольника <math>P</math>;
* <math>D(P)</math> &mdash; множество граничных точек многоугольника <math>P</math>, без учета вершин многоугольника.
* <math>D(P)</math> &mdash; множество граничных точек многоугольника <math>P</math>, без учета вершин многоугольника;
* <math>out(P)</math> &mdash; множество строго внешних по отношению к <math>P</math> точек
* <math>out(P)</math> &mdash; множество строго внешних по отношению к <math>P</math> точек;
* <math>\delta_{\varepsilon}(X)</math> &mdash; <math>\varepsilon</math>-окрестность точки <math>X</math>, или это следующее множество точек: <math>\{x \in \mathbb{R}^2 | \rho(x, X) \leqslant \varepsilon \}</math>, где <math>\rho(A, B) = \sqrt{(A_x - B_x)^2 + (A_y - B_y) ^ 2}</math> &mdash; Евклидово расстояние между точками <math>A</math> и <math>B</math>, а <math>A = (A_x, A_y)</math> &mdash; точка, задающаяся своими координатами по осям.
* <math>\delta_{\varepsilon}(X)</math> &mdash; <math>\varepsilon</math>-окрестность точки <math>X</math>, или это следующее множество точек: <math>\{x \in \mathbb{R}^2 | \rho(x, X) \leqslant \varepsilon \}</math>, где <math>\rho(A, B) = \sqrt{(A_x - B_x)^2 + (A_y - B_y) ^ 2}</math> &mdash; Евклидово расстояние между точками <math>A</math> и <math>B</math>, а <math>A = (A_x, A_y)</math> &mdash; точка, задающаяся своими координатами по осям.


Строка 61: Строка 61:
== Вычислительное ядро алгоритма ==
== Вычислительное ядро алгоритма ==


Как нетрудно видеть, сложность выполнения каждого из шагов 1) &ndash; 3) равна <math>O(N)</math>. Но в данной задаче есть один нюанс &mdash; сложность чтения данных составляет также <math>O(N)</math>. Причем, скорость чтения данных с диска гораздо медленее, чем оперирование с данными в процессе выполненения программы, поэтому, если говорить честно, то основная сложность алгоритма приходится именно на чтение данных (что впоследствии и будет видно на графиках сильной масштабируемости). Но проблема в том, что чтение с диска, без специальной предобработки хранения данных, достаточно плохо параллелится (с точки зрения времени чтения), то есть является "узким местом" алгоритма.  
Как нетрудно видеть, сложность выполнения каждого из шагов 1) &ndash; 3) равна <math>O(N)</math>. Но в данной задаче есть один нюанс &mdash; сложность чтения данных составляет также <math>O(N)</math>. Причем, скорость чтения данных с диска гораздо медленее, чем оперирование с данными в процессе выполненения программы, поэтому, если говорить честно, то основная сложность алгоритма приходится именно на чтение данных (что впоследствии и будет видно на графиках сильной масштабируемости). Но проблема в том, что чтение с диска достаточно плохо параллелится (с точки зрения времени чтения), то есть является "узким местом" алгоритма.  


Поэтому, будем считать, что данные '''уже лежат в памяти программы''' (такое запросто может быть, так как выбранный алгоритм спокойно может быть подзадачей какой-то программы), и тогда, основная сложность алгоритма придется на шаги 1) &ndash; 3).  
Поэтому, будем считать, что данные '''уже лежат в памяти программы''' (такое запросто может быть, так как выбранный алгоритм спокойно может быть подзадачей какой-то программы), и тогда, основная сложность алгоритма придется на шаги 1) &ndash; 3).  


== Макроструктура алгоритма ==
== Макроструктура алгоритма ==
0) Чтение входных данных: точка <math>X</math> и многоугольник <math>P</math>;
1) Проверка принадлежности <math>X</math> набору <math>V(P)</math>;
2) Проверка принадлежности <math>X</math> множеству <math>D(P)</math>;
3) Проверка принадлежности <math>X</math> множеству <math>int(P)</math>.


== Схема реализации последовательного алгоритма ==
== Схема реализации последовательного алгоритма ==
Псевдокод алгоритма:
X = input_point()
P = input_polygon()
if is_one_of_vertex(X, P): # Если точка X является одной из вершин многоугольника
    print(2)
else if is_one_of_edge(X, P): # Если точка X лежит на одном из ребер многоульника
    print(0)
else if is_inside(X, P): # Если точка X строго внутри многоугольника
    print(1)
else: # Если точка X строго снаружи многоугольника
    print(-1)


== Последовательная сложность алгоритма ==
== Последовательная сложность алгоритма ==

Версия от 21:11, 29 ноября 2017

Автор статьи: Липкина Анна

Свойства и структура алгоритмов

Общее описание алгоритма

На плоскости дан произвольный многоугольник с [math]\displaystyle{ N }[/math] вершинами и точка [math]\displaystyle{ X }[/math]. Требуется определить положение точки относительно многоугольника: находится ли точка внутри многоугольника, на его границе, совпадает с вершиной или находится вне многоугольника.

Математическое описание алгоритма

Дано: Многоугольник [math]\displaystyle{ P }[/math]с [math]\displaystyle{ N }[/math] вершинами и точка [math]\displaystyle{ X }[/math]. Каждая вершина многоугольника и точка [math]\displaystyle{ X }[/math] описываются парой координат [math]\displaystyle{ (x, y) }[/math].

Обозначения:

  • [math]\displaystyle{ int(P) }[/math] — множество строго внутренних точек многоугольника [math]\displaystyle{ P }[/math];
  • [math]\displaystyle{ V(P) = \{v_0, v_2, \dots, v_{N - 1} \} }[/math] — упорядоченноый набор точек, являющихся вершинами многоугольника [math]\displaystyle{ P }[/math];
  • [math]\displaystyle{ D(P) }[/math] — множество граничных точек многоугольника [math]\displaystyle{ P }[/math], без учета вершин многоугольника;
  • [math]\displaystyle{ out(P) }[/math] — множество строго внешних по отношению к [math]\displaystyle{ P }[/math] точек;
  • [math]\displaystyle{ \delta_{\varepsilon}(X) }[/math] — [math]\displaystyle{ \varepsilon }[/math]-окрестность точки [math]\displaystyle{ X }[/math], или это следующее множество точек: [math]\displaystyle{ \{x \in \mathbb{R}^2 | \rho(x, X) \leqslant \varepsilon \} }[/math], где [math]\displaystyle{ \rho(A, B) = \sqrt{(A_x - B_x)^2 + (A_y - B_y) ^ 2} }[/math] — Евклидово расстояние между точками [math]\displaystyle{ A }[/math] и [math]\displaystyle{ B }[/math], а [math]\displaystyle{ A = (A_x, A_y) }[/math] — точка, задающаяся своими координатами по осям.

Выход: вывести:

  • 1, если [math]\displaystyle{ X \in int(P) }[/math]
  • 2, если [math]\displaystyle{ X \in V(P) }[/math]
  • 0, если [math]\displaystyle{ X \in D(P) }[/math]
  • -1, если [math]\displaystyle{ X \in out(P) }[/math]

Алгоритм:

1) Сначала проверим, принадлежит ли [math]\displaystyle{ X }[/math] множеству [math]\displaystyle{ V(P) }[/math]. Для этого достаточно перебрать все вершины [math]\displaystyle{ V(P) }[/math] и для каждой проверить, лежит ли [math]\displaystyle{ X }[/math] в маленькой [math]\displaystyle{ \varepsilon }[/math]-окрестности текущей вершины многоугольника. Более формально:

для всех v принадлежащих V(P):
   если X принадлежит епсилон-окрестности v:
        вернуть 2


2) Если точка не совпадает ни с одной вершиной, то проверим, принадлежит ли [math]\displaystyle{ X }[/math] множеству [math]\displaystyle{ D(P) }[/math]. Для этого переберем все ребра многоугольника [math]\displaystyle{ (v_i, v_{i + 1}) }[/math] и посчитаем следующие величины:

Пусть [math]\displaystyle{ v_i^l = v_i - X, v_i^r = v_{(i + 1) \% N} - X }[/math]

[math]\displaystyle{ s_i = \langle v_i^l, v_i^r \rangle }[/math] — скалярное произведение векторов [math]\displaystyle{ v_i^l, v_i^r }[/math]

[math]\displaystyle{ t_i = v_i^l \times v_i^r }[/math] — модуль вектора, полученного векторным произведением векторов [math]\displaystyle{ v_i^l, v_i^r }[/math]

Теоретически, точка лежит на ребре (строго, не совпадает ни с одной из вершин ребер), если [math]\displaystyle{ s_i \lt 0 }[/math] и [math]\displaystyle{ d_i = 0 }[/math].

Практически, равенство нулю нужно превратить в [math]\displaystyle{ |d_i| \leqslant \varepsilon }[/math].

Если все условия выполнены, то возвращаем 0.

3) Если [math]\displaystyle{ X \notin V(P) }[/math] и [math]\displaystyle{ X \notin D(P) }[/math]:

Посчитаем следующую сумму ориентированных углов:

[math]\displaystyle{ S = \sum_{i=0}^{N - 1} angle (v_i - X, v_{(i + 1) \% N} - X) }[/math]

где [math]\displaystyle{ angle(a, b) }[/math] — ориентированный угол между векторами [math]\displaystyle{ a }[/math] и [math]\displaystyle{ b }[/math].

Есть следующие два варианта:

  • [math]\displaystyle{ |S| \lt \varepsilon \Rightarrow X \in out(P) }[/math]
  • [math]\displaystyle{ |S| \in \delta_{\varepsilon}(2 \pi) \Rightarrow X \in int(P) }[/math]

Замечание: здесь вводятся [math]\displaystyle{ \varepsilon }[/math] - окрестности из-за того, что работа происходит с вещественными числами.

Вычислительное ядро алгоритма

Как нетрудно видеть, сложность выполнения каждого из шагов 1) – 3) равна [math]\displaystyle{ O(N) }[/math]. Но в данной задаче есть один нюанс — сложность чтения данных составляет также [math]\displaystyle{ O(N) }[/math]. Причем, скорость чтения данных с диска гораздо медленее, чем оперирование с данными в процессе выполненения программы, поэтому, если говорить честно, то основная сложность алгоритма приходится именно на чтение данных (что впоследствии и будет видно на графиках сильной масштабируемости). Но проблема в том, что чтение с диска достаточно плохо параллелится (с точки зрения времени чтения), то есть является "узким местом" алгоритма.

Поэтому, будем считать, что данные уже лежат в памяти программы (такое запросто может быть, так как выбранный алгоритм спокойно может быть подзадачей какой-то программы), и тогда, основная сложность алгоритма придется на шаги 1) – 3).

Макроструктура алгоритма

0) Чтение входных данных: точка [math]\displaystyle{ X }[/math] и многоугольник [math]\displaystyle{ P }[/math]; 1) Проверка принадлежности [math]\displaystyle{ X }[/math] набору [math]\displaystyle{ V(P) }[/math]; 2) Проверка принадлежности [math]\displaystyle{ X }[/math] множеству [math]\displaystyle{ D(P) }[/math]; 3) Проверка принадлежности [math]\displaystyle{ X }[/math] множеству [math]\displaystyle{ int(P) }[/math].

Схема реализации последовательного алгоритма

Псевдокод алгоритма:

X = input_point()
P = input_polygon()

if is_one_of_vertex(X, P): # Если точка X является одной из вершин многоугольника
   print(2)
else if is_one_of_edge(X, P): # Если точка X лежит на одном из ребер многоульника
   print(0)
else if is_inside(X, P): # Если точка X строго внутри многоугольника
   print(1)
else: # Если точка X строго снаружи многоугольника
   print(-1) 

Последовательная сложность алгоритма

Информационный граф

Ресурс параллелизма алгоритма

Входные и выходные данные алгоритма

Свойства алгоритма

Программная реализация алгоритма

Особенности реализации последовательного алгоритма

Локальность данных и вычислений

Возможные способы и особенности параллельной реализации алгоритма

Масштабируемость алгоритма и его реализации

Динамические характеристики и эффективность реализации алгоритма

Выводы для классов архитектур

Существующие реализации алгоритма

Литература

http://ru-wiki.org/wiki/Задача_о_принадлежности_точки_многоугольнику https://habrahabr.ru/post/301102/ http://neerc.ifmo.ru/wiki/index.php?title=Принадлежность_точки_выпуклому_и_невыпуклому_многоугольникам http://www.e-maxx-ru.1gb.ru/algo/pt_in_polygon