Проверка правильности прямолинейной формы - PullRequest
4 голосов
/ 05 октября 2011

Учитывая прямолинейную форму, как мне эффективно проверить, является ли она действительной и указать ту часть, которая не является действительной?

Под валидностью здесь подразумевается ограничение ширины, т. Е. Каждая часть фигуры. должна иметь ширину не менее некоторого значения d. Формально, если вы проведете линию вертикально сверху вниз формы, все пересечения между линией и формой должны иметь длину не менее d. Вертикальная ситуация похожа. (Обратите внимание, что внутри фигуры могут быть отверстия. Но для простоты мы можем сначала проигнорировать это.)

Может кто-нибудь предложить эффективный алгоритм или показать мне указатель на эту проблему?

Ответы [ 2 ]

1 голос
/ 05 октября 2011

Я думаю, что вы можете атаковать это с помощью довольно типичного подхода линии сканирования.

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

Так что для горизонтальной линии сканирования вы можете игнорировать горизонтальные сегменты.Возьмите все конечные точки вертикальных сегментов и отсортируйте их по их вертикальному расположению.(Каждая конечная точка знает, является ли она «верхней» конечной точкой или «нижней» конечной точкой своего сегмента).

Обрабатывает этот отсортированный список для имитации линии сканирования.Поддерживать «активный набор» S, инициализированный как пустой.Когда вы достигнете «верхней» конечной точки, добавьте ее сегмент к S. Когда вы дойдете до «нижней» конечной точки, удалите ее сегмент из S. Убедитесь, что ширина активного набора всегда соответствует вашему ограничению, и все готово.

Используйте сбалансированное двоичное дерево (например, C ++ std::set) для представления активного набора, используя горизонтальную позицию для функции сравнения.Это позволяет O (1) извлечь самый левый и самый правый сегмент в наборе, поэтому вычисление ширины O (1).Он также позволяет вставлять и удалять O (log n), а поскольку вы вставляете и удаляете каждый вертикальный сегмент ровно один раз, весь цикл занимает O (n log n).

Повторите симметрично для вертикальной линии сканирования.

Каждая сортировка - O (n log n), каждое сканирование - O (n log n), умноженное на два для каждой ориентации ... Таким образом, общий алгоритм - O (n log n).

0 голосов
/ 05 октября 2011

Вот метод грубой силы, который примерно равен O (n ^ 2).

Сначала проверьте, нет ли каких-либо пересечений.Пересечение в многоугольнике имеет ширину 0, поэтому оно терпит неудачу автоматически.

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

Если ограничение является горизонтальным / вертикальным, проверьте каждый сегмент многоугольника, чтобы увидеть, пересекает ли он линию, проведенную через x или y точки.Если он пересекается, рассчитайте расстояние от пересечения до точки;если оно меньше, чем ограничение, у вас есть ошибка.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...