Разбиение большого прямоугольника на маленькие (2D упаковка)

#c #algorithm #space-partitioning

#c #алгоритм #разделение пробелом

Вопрос:

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

 struct RECT
{
  int l,t,r,b;
};

class BigRect
{
public:
  // width and height of big rect
  BigRect( unsigned width, unsigned height );

  // returns -1 if rect cannot be allocated, otherwise returns id of found rect
  int GetRect( unsigned width, unsigned height, RECT amp;out );

  // returns allocated rect to big rectangle
  void FreeRect( int id );
};

void test()
{
  BigRect r( 10, 10 );

  RECT out;
  r.GetRect( 4, 4, out ); // rect found ({0,0,4,4} for example), returns 1
  r.GetRect( 5, 5, out ); // rect found ({4,0,9,5} for example), returns 2

  r.GetRect( 6, 6, out ); // no place found for rect, returns -1
  r.FreeRect( 2 );        // add {4,0,9,5} back to rect

  r.GetRect( 6, 6, out ); // rect found (4,0,10,6)
}
  

Итак, мне нужен алгоритм для GetRect и FreeRect методов. Любые идеи и ссылки будут оценены.

Комментарии:

1. Существуют ли какие-либо ограничения на то, как должны быть выделены подпрямоугольники? Например. есть ли цель эффективно упаковывать прямоугольники или вы можете просто прикрепить их везде, где они подойдут?

2. @Эмиль Кормье, они означают «слева, сверху, справа, снизу». Нет, они не могут перекрываться. Как сказал Кирилл В. Лядвинский, это своего рода распределитель в 2D куче.

3. Что ж, я думаю, лучше объяснить предысторию проблемы. Мне нужно разместить маленькие картинки внутри большой текстуры. Вот почему мне нужно разбить его на маленькие прямоугольники.

4. Я нашел некоторую информацию здесь: csc.liv.ac.uk /~epa/surveyhtml.html . Хотя это довольно теоретически.

5. @pure cuteness: Если вы выполните поиск по «упаковке текстур», вы также найдете некоторую полезную информацию. У людей в игровом мире та же проблема, что и у вас. Этот парень опубликовал несколько примеров кода: codesuppository.blogspot.com/2009/04 /…

Ответ №1:

То, что вы пытаетесь сделать, — это оперативная упаковка 2D-ячеек. Это доступно онлайн, потому что у вас нет всех ваших маленьких картинок под рукой, прежде чем вы попытаетесь упаковать их в большую картинку. Кроме того, некоторые маленькие картинки будут «освобождены», и их пространство будет освобождено. С другой стороны, автономный алгоритм позволяет вам выполнять такие действия, как сортировка ваших маленьких изображений от самых больших к самым маленьким, прежде чем упаковывать их.

Вот статья, в которой рассматривается современное состояние 2D-упаковки: Обзор двумерной упаковки. Это довольно теоретически.

В этой статье Новая верхняя граница для 2D-онлайн-упаковки ячеек приводятся другие статьи, описывающие онлайн-алгоритмы 2D-упаковки.

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

Джон Рэтклифф опубликовал в блоге статью об упаковке текстур.

Смотрите также этот связанный вопрос на gamedev: https://gamedev.stackexchange.com/questions/2829/texture-packing-algorithm

Комментарии:

1. Насколько я понял, в автономной упаковке я не могу добавить немного свободного пространства обратно в rectangle ( BigRect::FreeRect в моем примере)? Теперь я действительно в замешательстве.

2. Упс, тогда это онлайн-упаковка. Отредактированный ответ.

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

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

5. В любом случае спасибо. По крайней мере, теперь я знаю, в каком направлении копать.