Диаметр множества точек (вращающиеся калиперы) — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
м (rollbackEdits.php mass rollback)
 
(не показано 8 промежуточных версий 3 участников)
Строка 1: Строка 1:
{{В разработке}}
 
 
Есть множество точек на плоскости. Нужно найти две самые удалённые из них.
 
Есть множество точек на плоскости. Нужно найти две самые удалённые из них.
  
 
[[Статические выпуклые оболочки: Джарвис, Грэхем, Эндрю, Чен, QuickHull|Найдём выпуклую оболочку]] исходного множества и получим более простую задачу: найти две наиболее удалённые вершины в выпуклом многоугольнике. Сделать это можно за линейное время с помощью метода, который называется '''вращающиеся калиперы''' (англ. ''rotating calipers'').
 
[[Статические выпуклые оболочки: Джарвис, Грэхем, Эндрю, Чен, QuickHull|Найдём выпуклую оболочку]] исходного множества и получим более простую задачу: найти две наиболее удалённые вершины в выпуклом многоугольнике. Сделать это можно за линейное время с помощью метода, который называется '''вращающиеся калиперы''' (англ. ''rotating calipers'').
 +
 +
''Обоснование: Пусть диаметр с одной стороны содержит точку, которая не принадлежит выпуклой оболочке. Тогда продлим диаметр в эту сторону до пересечения с выпуклой оболочкой. Очевидно, он станет длиннее. А потом заметим, что диаметр станет еще больше, если сдвинуть его к одному из концов ребра, в которое мы уперлись. Конец.''
  
 
== Постановка задачи ==
 
== Постановка задачи ==
Строка 8: Строка 9:
  
 
== Вращающиеся калиперы ==
 
== Вращающиеся калиперы ==
 +
=== Опорные прямые ===
 
{{Определение
 
{{Определение
 
|definition=
 
|definition=
Строка 34: Строка 36:
 
|[[Файл:max_parallel.png|170px|thumb|right]]
 
|[[Файл:max_parallel.png|170px|thumb|right]]
 
|}
 
|}
 
+
=== Алгоритм ===
 
Заметим, что параллельные опорные прямые можно провести не через любую пару точек.
 
Заметим, что параллельные опорные прямые можно провести не через любую пару точек.
  
 
{{Определение
 
{{Определение
 
|definition=
 
|definition=
Точки, через которые можно провести параллельные опорные прямые, будем называть '''противоположными''' (англ. ''antipodal'').
+
Точки, через которые можно провести параллельные опорные прямые, будем называть '''противолежащими''' (англ. ''antipodal'').
 
}}
 
}}
  
Благодаря предыдущей теореме нам нужно рассмотреть только противоположные точки. Задача в том, чтобы рассмотреть их, не перебирая все пары точек.
+
Благодаря предыдущей теореме нам нужно рассмотреть только противолежащие точки. Задача в том, чтобы рассмотреть их, не перебирая все пары точек.
  
 
{|border="0" width="100%"
 
{|border="0" width="100%"
  |Рассмотрим рисунок справа. <tex>L</tex> и <tex>M</tex> {{---}} опорные прямые, проходящие через вершины <tex>A</tex> и <tex>D</tex> соответственно. Значит, <tex>\langle A,D \rangle</tex> {{---}} противоположная пара точек. Если начать вращать прямые против часовой стрелки вокруг данных точек, они будут оставаться опорными прямыми, пока одна из прямых не станет накладываться на сторону многоугольника. В нашем примере, при вращении <tex>M</tex> к позиции <tex>M'</tex>, <tex>M</tex> коснётся точки <tex>E</tex> раньше, чем <tex>L</tex> коснётся <tex>B</tex>, поэтому <tex>\langle A,E \rangle</tex> становится новой парой противоположных точек.  
+
  |Рассмотрим рисунок справа. <tex>L</tex> и <tex>M</tex> {{---}} опорные прямые, проходящие через вершины <tex>A</tex> и <tex>D</tex> соответственно. Значит, <tex>\langle A,D \rangle</tex> {{---}} противолежащая пара точек. Если начать вращать прямые против часовой стрелки вокруг данных точек, они будут оставаться опорными прямыми, пока одна из прямых не станет накладываться на сторону многоугольника. В нашем примере, при вращении <tex>M</tex> к позиции <tex>M'</tex>, <tex>M</tex> коснётся точки <tex>E</tex> раньше, чем <tex>L</tex> коснётся <tex>B</tex>, поэтому <tex>\langle A,E \rangle</tex> становится новой парой противолежащих точек.  
  
Теперь <tex>M'</tex> будет вращаться вокруг <tex>E</tex>, а <tex>L'</tex> продолжит вращаться вокруг <tex>A</tex>, и следующей парой противоположных точек станет <tex>\langle B,E \rangle</tex>. Продолжая таким образом, мы сгенерируем все пары противоположных точек, так как параллельные линии пройдут под всеми возможными углами. Определение новой пары противоположных точек требует только одного сравнения углов, которое можно выполнить с помощью предиката поворота.
+
Теперь <tex>M'</tex> будет вращаться вокруг <tex>E</tex>, а <tex>L'</tex> продолжит вращаться вокруг <tex>A</tex>, и следующей парой противолежащих точек станет <tex>\langle B,E \rangle</tex>. Продолжая таким образом, мы сгенерируем все пары противолежащих точек, так как параллельные линии пройдут под всеми возможными углами. Определение новой пары противолежащих точек требует только одного сравнения углов, которое можно выполнить с помощью предиката поворота.
 
  |[[Файл:calipers.png|250px|thumb|right]]
 
  |[[Файл:calipers.png|250px|thumb|right]]
 
  |}
 
  |}
 +
=== Асимптотика ===
 +
{{Теорема
 +
|statement=
 +
Представленный выше алгоритм генерирует все пары противолежащих точек в многоугольнике <tex>P</tex>, состоящем из <tex>N</tex> вершин, за время <tex>O(N)</tex>.
 +
|proof=
 +
Данный алгоритм можно реализовать следующим образом: хранить указатели на противолежащие вершины, и на каждой итерации алгоритма увеличивать либо один из данных указателей, либо сразу оба (когда обе прямые проходят через сторону многоугольника), и заканчивать работу, когда опорные прямые сделают полный круг. Таким образом, каждая из вершин будет посещена каждой из прямых не более двух раз.
 +
}}
  
== Литература ==
+
== Ссылки ==
 
* ''M.I. Shamos'' Computational geometry, 1978 {{---}} С. 76.
 
* ''M.I. Shamos'' Computational geometry, 1978 {{---}} С. 76.
 
* ''Яглом И.М., Болтянский В.Г.'' Выпуклые фигуры, 1951 {{---}} С. 20, 144.
 
* ''Яглом И.М., Болтянский В.Г.'' Выпуклые фигуры, 1951 {{---}} С. 20, 144.
 +
* [https://github.com/Megabyte777/cg/blob/master/include/cg/operations/diameter.h Реализация - Github.com]
  
 
[[Категория: Вычислительная геометрия]]
 
[[Категория: Вычислительная геометрия]]

Текущая версия на 19:26, 4 сентября 2022

Есть множество точек на плоскости. Нужно найти две самые удалённые из них.

Найдём выпуклую оболочку исходного множества и получим более простую задачу: найти две наиболее удалённые вершины в выпуклом многоугольнике. Сделать это можно за линейное время с помощью метода, который называется вращающиеся калиперы (англ. rotating calipers).

Обоснование: Пусть диаметр с одной стороны содержит точку, которая не принадлежит выпуклой оболочке. Тогда продлим диаметр в эту сторону до пересечения с выпуклой оболочкой. Очевидно, он станет длиннее. А потом заметим, что диаметр станет еще больше, если сдвинуть его к одному из концов ребра, в которое мы уперлись. Конец.

Постановка задачи

Пусть [math]P = (p_1, p_2, ... ,p_n)[/math] — выпуклый многоугольник, в котором порядок обхода вершин направлен против часовой стрелки, и никакие три последовательные точки не лежат на одной прямой. Найти пару чисел [math]\langle i, j \rangle[/math], такие, что [math]d(p_i, p_j)[/math] максимально.

Вращающиеся калиперы

Опорные прямые

Определение:
Прямая [math]L[/math] называется опорной прямой (англ. line of support) для многоугольника [math]P[/math], если его внутренность лежит по одну сторону от [math]L[/math], при этом [math]L[/math] проходит хотя бы через одну из вершин [math]P[/math].


Теорема:
Пусть [math]L_1[/math] и [math]L_2[/math] — две параллельные опорные прямые фигуры [math]\Phi[/math], расстояние между которыми имеет максимальное значение. [math]A_1[/math] и [math]A_2[/math] — граничные точки фигуры [math]\Phi[/math], принадлежащие соответственно прямым [math]L_1[/math] и [math]L_2[/math]. Тогда отрезок [math]A_1A_2[/math] перпендикулярен обеим прямым [math]L_1[/math] и [math]L_2[/math].
Доказательство:
[math]\triangleright[/math]
Предположим, что это не так. Тогда расстояние между прямыми [math]L_1[/math] и [math]L_2[/math] было бы меньше, чем отрезок [math]A_1A_2[/math], и тем более меньше, чем расстояние между двумя опорными прямыми [math]L'_1[/math] и [math]L'_2[/math] фигуры [math]\Phi[/math], перпендикулярными к отрезку [math]A_1A_2[/math], что противоречит условию.
[math]\triangleleft[/math]
Perpendicular.png

Так как [math]A_1[/math] и [math]A_2[/math] — какие угодно граничные точки фигуры [math]\Phi[/math], принадлежащие соответственно прямым [math]L_1[/math] и [math]L_2[/math], то из перпендикулярности отрезка [math]A_1A_2[/math] к прямым [math]L_1[/math] и [math]L_2[/math] следует, что ни одна из прямых [math]L_1[/math], [math]L_2[/math] не может иметь с фигурой [math]\Phi[/math] целый общий отрезок. Другими словами, каждая из этих прямых содержит единственную граничную точку фигуры [math]\Phi[/math].

Теорема:
Диаметр выпуклого многоугольника равен максимальному расстоянию между параллельными опорными прямыми.
Доказательство:
[math]\triangleright[/math]
Пусть [math]\Phi[/math] — выпуклая фигура, [math]L_1[/math] и [math]L_2[/math] — параллельные опорные прямые, расстояние между которыми имеет наибольшее возможное значение [math]d[/math], [math]A_1[/math] и [math]A_2[/math] — общие точки фигуры [math]\Phi[/math] и прямых [math]L_1[/math] и [math]L_2[/math] соответственно. По предыдущей теореме [math]A_1A_2[/math] перпендикулярен к прямым [math]L_1[/math], [math]L_2[/math], следовательно, его длина равна [math]d[/math]. Докажем, что расстояние между любыми двумя точками фигуры [math]\Phi[/math] не преводходит [math]d[/math]. Действительно, если [math]B[/math] и [math]C[/math] — какие-либо две точки фигуры [math]\Phi[/math], а [math]m[/math] и [math]n[/math] — опорные прямые, перпендикулярные к отрезку [math]BC[/math], то отрезок [math]BC[/math] не превосходит расстояния между прямыми [math]m[/math] и [math]n[/math], которое в свою очередь не превосходит [math]d[/math]. Следовательно, длина [math]BC[/math] не может быть больше [math]d[/math].
[math]\triangleleft[/math]
Max parallel.png

Алгоритм

Заметим, что параллельные опорные прямые можно провести не через любую пару точек.


Определение:
Точки, через которые можно провести параллельные опорные прямые, будем называть противолежащими (англ. antipodal).


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

Рассмотрим рисунок справа. [math]L[/math] и [math]M[/math] — опорные прямые, проходящие через вершины [math]A[/math] и [math]D[/math] соответственно. Значит, [math]\langle A,D \rangle[/math] — противолежащая пара точек. Если начать вращать прямые против часовой стрелки вокруг данных точек, они будут оставаться опорными прямыми, пока одна из прямых не станет накладываться на сторону многоугольника. В нашем примере, при вращении [math]M[/math] к позиции [math]M'[/math], [math]M[/math] коснётся точки [math]E[/math] раньше, чем [math]L[/math] коснётся [math]B[/math], поэтому [math]\langle A,E \rangle[/math] становится новой парой противолежащих точек.

Теперь [math]M'[/math] будет вращаться вокруг [math]E[/math], а [math]L'[/math] продолжит вращаться вокруг [math]A[/math], и следующей парой противолежащих точек станет [math]\langle B,E \rangle[/math]. Продолжая таким образом, мы сгенерируем все пары противолежащих точек, так как параллельные линии пройдут под всеми возможными углами. Определение новой пары противолежащих точек требует только одного сравнения углов, которое можно выполнить с помощью предиката поворота.

Calipers.png

Асимптотика

Теорема:
Представленный выше алгоритм генерирует все пары противолежащих точек в многоугольнике [math]P[/math], состоящем из [math]N[/math] вершин, за время [math]O(N)[/math].
Доказательство:
[math]\triangleright[/math]
Данный алгоритм можно реализовать следующим образом: хранить указатели на противолежащие вершины, и на каждой итерации алгоритма увеличивать либо один из данных указателей, либо сразу оба (когда обе прямые проходят через сторону многоугольника), и заканчивать работу, когда опорные прямые сделают полный круг. Таким образом, каждая из вершин будет посещена каждой из прямых не более двух раз.
[math]\triangleleft[/math]

Ссылки

  • M.I. Shamos Computational geometry, 1978 — С. 76.
  • Яглом И.М., Болтянский В.Г. Выпуклые фигуры, 1951 — С. 20, 144.
  • Реализация - Github.com