сведение к минимуму перекрытия в случайных прямоугольниках - PullRequest
8 голосов
/ 11 февраля 2010

У меня есть несколько перекрывающихся прямоугольников случайного размера и положения в фиксированной плоскости. Поскольку эти прямоугольники являются случайными, некоторые могут не перекрываться:

|-----
|    |    |----|
|----|    |    |
          |----|

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

|-----|
|  |--|--|
|--|--|  |
   |-----|

Некоторые могут содержаться внутри другого прямоугольника:

|----------------|
|                |
|   |-----|      |
|   |     |      |
|   |-----|      |
|----------------|

Некоторые могут проходить через другой прямоугольник:

   |----------------|
   |                |
|--|-------------------|
|  |                |  |
|--|-------------------|
   |----------------|

и т.д.

Я пытаюсь найти алгоритм, который дает мне набор прямоугольников, которые представляют ту же область, что и входной набор, но без наложения. Некоторые случаи очевидны - прямоугольники, содержащиеся в большем прямоугольнике, могут быть отброшены, и прямоугольники, которые перекрывают угол, могут быть разделены на три прямоугольника, как и прямоугольники, которые проходят через другой прямоугольник. То, что я ищу, это общий алгоритм, который имеет дело со всеми этими случаями. Меня не волнует, не слишком ли это эффективно - входной набор довольно мал (максимум 25 прямоугольников)

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

Это заставляет меня задуматься. Есть предложения?

Обновление:

Я только что понял еще одну вещь:

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

Ответы [ 5 ]

3 голосов
/ 11 февраля 2010

Прямоугольники параллельны осям x & y? Я полагаю, что они.

Вы можете попробовать использовать KD-Trees .

Или, если вы хотите что-то доморощенное и не обязательно эффективное, вы можете «прямоугольнить», а затем при необходимости объединить прямоугольники обратно.

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

Теперь вытяните все края прямоугольников, чтобы разрезать большой прямоугольник. Теперь у вас есть «прямоугольность». По сути, все это означает, что вы сортируете вертикальные края и горизонтальные края и выбираете соседние пары, чтобы сформировать небольшой прямоугольник. Для каждого маленького прямоугольника вы можете теперь проверить, является ли это частью интересной области или нет, и отклонить ее, если это не так (она либо полностью внутри, либо полностью снаружи).

Теперь у вас есть список маленьких прямоугольников (возможно, O (n ^ 2), в вашем случае, возможно, ~ 2500), которые составляют область вашего интереса. Если число достаточно мало для вашей дальнейшей обработки, вы можете просто использовать их или объединить их вместе, чтобы уменьшить количество прямоугольников.

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

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

1 голос
/ 12 февраля 2010

Если у вас нет каких-либо ограничений на количество прямоугольников, которые должен генерировать ваш алгоритм, вы определенно можете быть опрометчивыми в вашем лечении!

1. Самое простое решение из всех

Создать набор всех квадратов (области 1), которые покрыты прямоугольниками входного набора. Квадрат, являющийся прямоугольником ... вот ты где!

2. Минималистское решение?

Хорошо, это было опрометчиво, однако я не думаю, что вам стоит беспокоиться о наборе ввода. Ваша проблема на самом деле другая:

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

Конечно, ваша область может быть не смежной, но это просто означает, что у вас есть несколько смежных областей, с которыми вы можете работать независимо.

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

1 голос
/ 11 февраля 2010

Очень интересный вопрос - я думаю, что лучше всего решить проблему парой прямоугольников за раз, а не смотреть на 3 или более одновременно.Начните с отбрасывания тех, что в других прямоугольниках.Теперь у вас есть только 3 вида пересечений - угловое перекрытие и прохождение через перекрытие и частичное перекрытие (где прямоугольник не проходит полностью).Каждый из них создает новый набор прямоугольников, верно?

Пронумеруйте свои начальные прямоугольники от 1 до N. Начиная с прямоугольника 1, проходите циклически, пока не найдете пересекающийся прямоугольник.Создайте новые прямоугольники.Удалите два пересекающихся прямоугольника и добавьте 3 или более вновь созданных прямоугольника в ваш набор и начните заново.

Результатом будет целый набор непересекающихся прямоугольников.Создает ли это наименьшее количество прямоугольников?Возможно, нет, но вы не указали, что минимизация количества прямоугольников важна.Требуется ли время o (n ^ 2)?Возможно.

1 голос
/ 11 февраля 2010

Сначала создайте набор всех «атомарных» прямоугольников в композиции, то есть областей, образованных пересечениями прямоугольников и не подразделяющихся между собой. Каждый фактический прямоугольник охватывает 1 или более атомных прямоугольников. Затем запустите комбинаторный алгоритм оптимизации, например, SETCOVER, чтобы рассчитать минимальное количество прямоугольников, необходимое для их покрытия.

Вот иллюстрация подхода. У вас есть три прямоугольника (A, B, C). Они создают 5 атомных областей (1-5):

 +---------+A
 |       1 |
 |    +----+-----+B
 |    |  2 | 3   |
 |    |  +-+---+C|
 |    |  |4|   | |
 +----+--+-+ 5 | |
      |  +-----+ |
      +--+-------+

Прямоугольники охватывают атомные области в соответствии с этой таблицей:

 A  {1,2,4}
 B  {2,3,4,5}
 C  {4,5}

Задача SETCOVER теперь состоит в том, чтобы выбрать минимальное подмножество прямоугольников {A, B, C} так, чтобы все атомные области были покрыты, когда вы соединяете атомные области, покрытые прямоугольниками. Минимальное решение (очевидно)

 A {1,2,4} + B {2,3,4,5} = {1,2,3,4,5}

Обратите внимание, что здесь области не прямоугольные, например, участок 3 имеет сложную форму. Вы можете избавиться от этой проблемы следующим способом: возьмите все различные X-координаты угловых точек исходных прямоугольников и рассмотрите их как X-координаты сетки и сделайте то же самое для Y-координат; тогда каждый прямоугольник покрывает набор квадратов сетки, которые никогда не подразделяются, т. е .:

 +---------+A       -
 |       1 |
 |    +----+-----+B -
 |    |  2 | 3   |
 |    |  +-+---+C|  -
 |    |  |4|   | | 
 +----+--+-+ 5 | |  -
      |  +-----+ |  -
      +--+-------+  -

 |    |  | |   | |

Что дает следующую сетку 5x5:

 AAA      A = rectangle A only
 A**BB    B = rectangle B only
 A*#CB    * = A and B
  BCCB    C = rectangles C and B
  BBBB    # = All

Из этого вы можете легко извлечь 5 регионов; на самом деле они уже отмечены :) (A, B, C, *, #)

0 голосов
/ 11 февраля 2010

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

Начните с целого прямоугольника

--------
|      |
|      |
|      |
|      |
|      |
--------

Разделите в случайной точке и сохраните два прямоугольника.

--------
|      |
|------|
|      |
|      |
|      |
--------

Разбить случайный прямоугольник на случайную точку

--------
|      |
|------|
| |    |
| |    |
| |    |
--------

повторить. , .

--------
|      |
|------|
| |    |
| |----|
| |    |
--------

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

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

...