Русская Википедия:Многоугольник видимости

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Файл:Visibility polygon.svg
Многоугольник видимости показан жёлтым цветом. Четыре препятствия показаны синим цветом.

Многоугольник видимости или область видимости для точки p на плоскости среди препятствий — это (возможно неограниченная) многоугольная область всех точек плоскости, видимых из точки p. Многоугольник видимости можно определить для видимости из отрезка или многоугольника. Многоугольники видимости полезны в робототехнике, компьютерных играх и для определения позиций объектов, например, для определения наилучшего расположения охраны в картинных галереях.

Если многоугольник видимости ограничен, то он является звёздчатым многоугольником. Многоугольник видимости ограничен, если все лучи, проведённые из точки, в конце концов, обрываются на некотором препятствии. Это случается, например, когда препятствия являются рёбрами простого многоугольника, а точка p находится внутри многоугольника. В таком случае многоугольник видимости может быть найден за линейное времяШаблон:SfnШаблон:SfnШаблон:SfnШаблон:Sfn.

Определения

Формально мы можем определить задачу о планарном многоугольнике видимости следующим образом. Пусть <math>S</math> будет набором препятствий (отрезки, либо многоугольники) в <math>\mathbb{R}^2</math>. Пусть <math>p</math> будет точкой в <math>\mathbb{R}^2</math>, не находящейся внутри препятствия. Тогда многоугольник видимости точки <math>V</math> — это множество точек в <math>\mathbb{R}^2</math>, таких, что для любой точки <math>q</math> из <math>V</math> отрезок <math>pq</math> не пересекает какой-либо объект из набора <math>S</math>.

Аналогично, многоугольник видимости отрезка или многоугольник видимости ребра — это точки, видимые с любого места отрезка.

Приложения

Многоугольники видимости полезны в робототехнике. Например, в Шаблон:Не переведено 5 робот использует датчики, такие как лидар, которые обнаруживают препятствия, и область видимости аналогична многоугольнику видимостиШаблон:Sfn.

Они также полезны в компьютерных играх, и имеются многочисленные онлайновые учебные курсы, которые объясняют простые алгоритмы для реализации в играхШаблон:SfnШаблон:SfnШаблон:Sfn.

Алгоритмы для точек видимости многоугольников

Было предложено много алгоритмов вычисления многоугольника видимости для точки. Для различных вариантов задачи (то есть различных видов препятствий) алгоритмы могут отличаться по времени и сложности.

Наивные алгоритмы

Наивные алгоритмы легко понять и реализовать, но они не Шаблон:Не переведено 5, поскольку они могут быть существенно медленнее других алгоритмов.

«Физический» алгоритм равномерного проведения лучей

В реальной жизни светящаяся точка освещает область, видимую из точки, поскольку точка излучает свет во всех направлениях. Это можно смоделировать путём проведения лучей во многих направлениях. Предположим, что имеется точка <math>p</math> и набор препятствий <math>S</math>. Тогда псевдокод может быть выражен следующим образом:

Алгоритм простой_плохой_алгоритм(<math>p</math>, <math>S</math>)
 <math>V</math> := <math>\emptyset</math>
 для <math>\theta=0, \cdots, 2\pi</math>:
 // проводим луч с углом with angle <math>\theta</math>
   <math>r</math> := <math>\infty</math>
   для каждого препятствия из <math>S</math>:
     <math>r</math> := min(<math>r</math>, расстояние от <math>p</math> до препятствия в этом направлении)
   добавляем вершину <math>(\theta, r)</math> в <math>V</math>
 возвращаем <math>V</math>

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

Проведение луча в каждую вершину

Описанный выше алгоритм может быть существенно улучшен как по скорости, так и по корректности путём наблюдения, что достаточно проводить лучи только к вершинам препятствий. Это потому, что любое огибание угла препятствия вдоль границы многоугольника видимости должно быть в некоторой угловой вершине препятствия.

Алгоритм простой_улучшенный_алгоритм(<math>p</math>, <math>S</math>)
  <math>V</math> := <math>\emptyset</math>
  для каждого препятствия <math>b</math> из <math>S</math>:
    для каждой вершины <math>v</math> of <math>b</math>:
      // проводим луч из <math>p</math> в <math>v</math>
      <math>r</math> := расстояние от <math>p</math> до <math>v</math>
      <math>\theta</math> := угол of <math>v</math> с <math>p</math>
      для каждого препятствия <math>b'</math> из <math>S</math>:
        <math>r</math> := min(<math>r</math>, расстояние от <math>p</math> до <math>b'</math>)
      добавляем вершину <math>(\theta, r)</math> в <math>V</math>
  возвращаем <math>V</math>

Временная сложность алгоритма равна <math>O(n^2)</math>. Это потому, что алгоритм проводит луч в каждую из <math>n</math> вершин и проверяет, где обрывается луч. Алгоритм должен проверить пересечение с каждым из <math>O(n)</math> препятствий. Это достаточно для многих простых приложений, таких как компьютерные игры и многие онлайновые обучающие курсы учат этому методуШаблон:Sfn. Однако, как мы можем видеть далее, существуют более быстрые алгоритмы со скоростью работы <math>O(n\log n)</math> (или даже быстрее, если препятствие является простым многоугольником или имеется фиксированное число многоугольных дыр).

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

Файл:Visibility polygon for a point in a simple polygon 2.svg
Многоугольник видимости для точки в центре (показана белой точкой) в простом многоугольнике, показанным чёрным цветом.

Если дан простой многоугольник <math>\mathcal{P}</math> и точка <math>p</math>, алгоритм линейного времени является оптимальным для вычисления области <math>\mathcal{P}</math>, которая видна из точки <math>p</math>. Такой алгоритм был предложен в 1981Шаблон:Sfn. Однако он довольно сложен. В 1983 был предложен концептуально более простой алгоритмШаблон:Sfn, но он имел небольшую ошибку, которая была исправлена в 1987Шаблон:Sfn.

Последний упомянутый алгоритм будет кратко изложен здесь. Он просто проходит границу многоугольника <math>\mathcal{P}</math>, последовательно перебирая вершины, и хранит стек вершин <math>\mathcal{S}=s_0, s_1,\cdots, s_t</math>, где <math>s_t</math> — вершина стека. Стек состоит из вершин, видимых из <math>p</math>. Если потом обнаружатся вершины, которые закрывают часть <math>\mathcal{S}</math>, то закрытые вершины выталкиваются из стека <math>\mathcal{S}</math>. Алгоритм прекращает работу, когда <math>\mathcal{S}</math> состоит из всех видимых вершин, то есть из желаемого многоугольника видимости. Эффективная реализация была опубликована в 2014Шаблон:Sfn.

Оптимальные алгоритмы для точек многоугольника с дырами

Для точки в многоугольнике с <math>h</math> дырами и <math>n</math> вершинами (в сумме) можно показать, что в худшем случае алгоритм <math>\Theta(n + h\log h)</math> оптимален. Такой алгоритм был предложен в 1995 вместе с доказательством его оптимальностиШаблон:Sfn. Однако этот алгоритм опирается на алгоритм линейного времени триангуляризации многоугольника Чазелле, который крайне сложен.

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

Отрезки, которые могут пересекаться только на концах

Файл:Visibility polygon for a point among segments.svg
Многоугольник видимости для точки в центре (показана белым цветом) среди набора произвольных отрезков на плоскости, которые могут пересекаться только нa концах, выступающих в роли препятствий (показаны чёрным).

Для точки среди множества из <math>n</math> отрезков, которые могут пересекаться только на их концах, можно показать, что в худшем случае алгоритм со временем работы <math>\Theta(n\log n)</math> оптимален. Это потому, что алгоритм многоугольника видимости должен выводить вершины многоугольника видимости в отсортированном порядке, а следовательно, задача сортировки может быть сведена к вычислению многоугольника видимостиШаблон:Sfn.

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

Разделяй и властвуй

Алгоритм «Разделяй и властвуй» для вычисления многоугольника видимости был предложен в 1987Шаблон:Sfn.

Угловое выметание

Угловое выметание, то есть вращательный алгоритм выметающей прямой для вычисления многоугольника видимости был предложен в 1985Шаблон:Sfn и 1986Шаблон:Sfn. Идея заключается в начальной сортировке концов отрезков по углу, а затем просмотре отсортированных точек. Во время итерирования события обрабатываются как куча. Эффективная реализация была опубликована в 2014Шаблон:Sfn.

Произвольно пересекающиеся отрезки

Для точки среди отрезков, пересекающихся произвольным образом, задача о многоугольнике видимости сводится за линейное время к задаче о нижней огибающей. Согласно доводам Дэвенпорта — Шинцеля вычисление нижней огибающей в худшем случае имеет сложность <math>\Theta(n\alpha(n))</math> от числа вершин, где <math>\alpha(n)</math> — обратная функции Аккермана. Оптимальный в худшем случае алгоритм «разделяй и властвуй», работающий за время <math>\Theta(n\log n)</math>, создал Джон Хершбергер в 1989Шаблон:Sfn.

Ссылки

Программное обеспечение

  • VisiLibity: A free open source C++ library for visibility computations in planar polygonal environments.
  • visibility-polygon-js: A public domain Javascript library for computing многоугольник видимости for a point among segments using the Угловое выметание method.

Примечания

Шаблон:Примечания

Литература

Шаблон:Refbegin

Шаблон:Refend Шаблон:Rq