Объединение и разбиение перекрывающихся прямоугольников для получения неперекрывающихся - PullRequest
3 голосов
/ 03 мая 2010

Я ищу алгоритм следующим образом:

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

На первый взгляд это кажется достаточно простым, но оказывается хитрым (по крайней мере, должно быть сделано эффективно).

Существуют ли известные методы для этого / ideas / pointers?

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

Ответы [ 2 ]

7 голосов
/ 03 мая 2010

Что-то, основанное на алгоритме строчной развертки, будет работать, я думаю:

  • Сортировка всех минимальных и максимальных x координат ваших прямоугольников в массив по событиям "start-rectangle" и "end-rectangle"
  • Шаг по массиву, добавление каждого нового встреченного прямоугольника (start-event) в текущий набор
  • Одновременно сохраняйте набор "неперекрывающихся прямоугольников", который будет вашим выходным набором
  • Каждый раз, когда вы сталкиваетесь с новым прямоугольником, вы можете проверить, полностью ли он уже содержится в текущем / выходном наборе (достаточно простого сравнения y -координат)
  • Если это не так, добавьте новый прямоугольник к выходному набору с y -координатами, установленными для части нового прямоугольника, которая еще не покрыта.
  • Каждый раз, когда вы достигаете конечного события прямоугольника, остановите все прямоугольники в выходном наборе, которые больше не покрывают ничего.

Я не совсем уверен, что это охватывает все, но я думаю, что с некоторыми изменениями это должно сделать работу. Или, по крайней мере, дать вам некоторые идеи ...:)

1 голос
/ 04 мая 2010

Итак, если бы я пытался это сделать, первое, что я бы сделал, это придумал единое пространство сетки. Найдите все уникальные координаты x и y и создайте отображение на индексное пространство. Поэтому, если у вас есть значения x {-1, 1.5, 3.1}, сопоставьте их с {0, 1, 2} и аналогично для y. Тогда каждый прямоугольник может быть точно представлен этими упакованными целочисленными координатами.

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

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

Давайте посмотрим на 4 соседних пикселя, маленький квадрат 2х2. Когда я пишу алгоритмы, подобные этим, я обычно думаю о вершинах, ребрах и гранях. Итак, это лица вокруг вершины. Если 3 из них включены, а 1 выключен, то у вас есть вогнутый угол. Это единственный недействительный случай. Например, если у меня нет вогнутых углов, я просто беру экстенты и выкидываю все это как один прямоугольник. Для каждого вогнутого угла вам нужно решить, следует ли разделять по горизонтали, вертикали или по обоим направлениям. Я думаю о разделении как о маркировке краев, чтобы не пересекаться при поиске экстентов. Вы также можете сделать это как раскраски в наборы, что вам проще. * +1007 *

Вогнутые углы и их разделенные направления - это ваше пространство поиска. Вы можете использовать любой алгоритм оптимизации, какой захотите. Ветвь / граница может хорошо работать. Могу поспорить, что вы могли бы найти простую эвристику, которая работает хорошо (например, если есть другой вогнутый угол прямо напротив того, который вы рассматриваете, всегда разделяйте в этом направлении. В противном случае делите в более коротком направлении). Вы можете просто пойти жадным. Или вы можете просто разделить каждый вогнутый вершин в обоих направлениях, что, как правило, даст вам меньше прямоугольников, чем выводить каждый «пиксель» в виде прямоугольника, и это будет довольно просто.

Читая это, я понимаю, что могут быть области, которые неясны. Дайте мне знать, если вы хотите, чтобы я что-то прояснил.

...