заполнение прямолинейного многоугольника прямоугольниками

Дан многоугольник, созданный полностью из прямоугольников и определенный массивом точек, где края всегда выровнены по оси:

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

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

EDIT: Вот простой код обработки для создания этой формы (ну, близко к этому).

float[] xpts = {0,    50,  50,  100, 100, 150, 150, 250, 250, 300, 300, 325, 325, 300, 300, 250, 250, 210, 210, 250, 250, 125, 125, 25, 25,   50,  50,  0 };
float[] ypts = {100, 100,  80,   80, 10,   10,  80, 80,  75,  75, 80,   80,  200, 200, 300, 300, 275, 275, 260, 260, 200, 200, 270, 270, 165, 165, 125, 125};


void setup( )
{
  size( 350, 350 );
}

void draw( )
{

stroke( 0 );
strokeWeight( 1.5 );

float px = xpts[0];
float py = ypts[0];
for (int i=1; i < xpts.length; i++)
{
  float nx = xpts[i];
  float ny = ypts[i];
  line( px, py, nx, ny );


  px = xpts[i];
  py = ypts[i];
}
float nx = xpts[0];
float ny = ypts[0];

line( px, py, nx, ny );
}

person jedierikb    schedule 03.05.2011    source источник
comment
Края всегда выровнены по оси? вы можете использовать линии сканирования, чтобы легко найти наибольшую площадь, если они есть.   -  person Flexo    schedule 04.05.2011
comment
Да, края всегда выровнены по оси (я обновлю пост). Не могли бы вы дать более подробную информацию о подходе линии сканирования? Спасибо.   -  person jedierikb    schedule 04.05.2011
comment
@finnw - я думаю, что это достаточно отличается от этого вопроса - здесь ввод представляет собой список краев.   -  person Flexo    schedule 04.05.2011


Ответы (2)


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

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

Вот некоторый псевдокод:

function makeRects(Rect r, Polygon p)

  if p is empty
    if r is inside your original polygon
      add r to results

  else
    choose good splitter s

    makeRects(left part of r relative to s, left part of p relative to s)
    makeRects(right part of r relative to s, right part of p relative to s)

Разделители для декомпозиции образцов ОП

person ltjax    schedule 06.05.2011
comment
Не могли бы вы привести пример? Я не совсем понимаю, как определяются дети каждого разделения. - person Null Set; 06.05.2011
comment
Сделано - надеюсь поможет. Дети каждого разделения — это просто оставшиеся подпространства. т.е. две половины плоскости разделения пересекаются с подпространством, связанным с родительским узлом. - person ltjax; 08.05.2011
comment
Некоторый псевдокод (может быть очень высокого уровня) был бы полезен, чтобы понять, как реализовать ваше предложение. Большое спасибо. - person jedierikb; 20.05.2011
comment
Добавил немного псевдокода, как вы и просили. Это оставляет много свободы, хотя. Например, вам не нужно явно проверять, находится ли r внутри исходного многоугольника, чтобы прервать рекурсию: обычно вы можете получить это из плоскости разделения на один уровень выше! - person ltjax; 20.05.2011
comment
Я понимаю. Спасибо. Но не является ли левая часть p относительно s довольно затратной операцией? Я понимаю, что чем больше p обрезается, тем дешевле становится, но это все равно много точечных проверок, не так ли? - person jedierikb; 20.05.2011
comment
Он должен быть линейным, если вы реализуете его наивно. Но даже тогда это должно быть довольно быстро, поэтому я бы не слишком беспокоился об этом. - person ltjax; 20.05.2011

Для меня это очень похоже на проблему NP. Это означает, что определенно есть несколько алгоритмов, которые могут быстро заполнить вашу фигуру прямоугольниками, если количество прямоугольников для вас не имеет большого значения, но если вы настаиваете на наименьшем числе , то вам лучше забыть о слове "быстро". На самом деле вам следует даже забыть о слове "наименьший" и вместо этого использовать "наименьший", поскольку определение того, является ли набор наименьшим, уже может быть огромной проблемой для алгоритма.

person Mecki    schedule 04.05.2011
comment
Наименьшее изменилось на маленькое. Спасибо! - person jedierikb; 06.05.2011
comment
Можете ли вы набросать доказательство, почему это NP? - person citykid; 19.06.2014
comment
@citykid Теперь, когда в вопросе говорится «маленький», это больше не проблема NP, но изначально он читался как «наименьший». Покажите мне математический тест, подтверждающий, что решение является наименьшим и выполняется за полиномиальное время. Я не знаю ни одного, поэтому проверка наименьшего решения уже является проблемой NP, и поэтому поиск наименьшего решения также является NP. Это похоже на задачу коммивояжера или рюкзака — найти хорошее решение за короткое время возможно, но найти идеальное решение — это NP. - person Mecki; 20.06.2014
comment
молодец, согласен, вполне ранец. - person citykid; 21.06.2014
comment
Привет, спасибо за этот вопрос. Я сделал прямоугольники графа и уменьшил его алгоритмами hopcork и karp. Вы даже можете сократить этот шаг, нарисовав только линии разреза, чтобы преобразовать многоугольник (ортогон) в набор прямоугольников. В результате вы получите больше прямоугольников, чем наименьшее количество прямоугольников, но часто это не будет большой проблемой. Ну, если вы относитесь к тысячам маленьких ортогонов в странном приложении, может быть. Проблема сейчас для меня в том, что я не могу заполнить прямоугольники после того, как я их нарисовал. Я изо всех сил пытаюсь понять предложенный алгоритм. Примеры где-то? Благодарность. - person Jean-Yves DANIEL; 06.04.2021