Разбить прямоугольник на равные прямоугольники?

Мне нужно разделить прямоугольник (структура CGRect, которая равна {{float x,float y},{float w,float h}}) на несколько меньших прямоугольников/структур, создав своего рода сетку. Я пишу диспетчер компоновки окон, и мне нужна опция предварительного просмотра окна.

введите здесь описание изображения

Я видел похожие вопросы, но ни один из алгоритмов, которые я видел (с участием ceil и floor), не работал. Я также пробовал:

float widthOfNewRect = total.size.width / floor(sqrt(n));
float heightOfNewRect = total.size.height / ceil(sqrt(n));

Может ли кто-нибудь привести пример того, как это сделать с моей структурой на C?


person Kristina Brooks    schedule 31.05.2011    source источник
comment
Вы ожидаете, что n будет степенью двойки? Если нет, то как должен выглядеть результат, например. n = 3 или n = 11?   -  person Aasmund Eldhuset    schedule 31.05.2011
comment
Если n не является степенью двойки, я просто центрирую прямоугольники по нижнему ряду. Мне просто нужно определить оптимальный размер, чтобы все они поместились на экране.   -  person Kristina Brooks    schedule 31.05.2011


Ответы (4)


Основываясь на вашем последнем комментарии, я предполагаю, что вы хотите разбить свой прямоугольник на n подпрямоугольников одинакового размера и что они должны быть выровнены таким образом, чтобы количество строк и количество столбцов были равны. (последняя строка, возможно, не заполнена полностью). Если это так, вы можете использовать ceil(sqrt(n)) для вычисления количества столбцов (поскольку это, как вы, очевидно, догадались, наименьшее количество столбцов, которое вам нужно, чтобы не было больше строк, чем столбцов). Тогда количество строк, необходимое для размещения n элементов, распределенных по столбцам numColumns, будет равно ceil(n / (double)numColumns).

Что касается кода, который вы показали: причина, по которой он не работает, заключается в том (как вы, вероятно, сами обнаружили), что floor(sqrt(n)) * ceil(sqrt(n)) вполне может быть меньше, чем n; например, это имеет место для n = 7. Расчет, который я предлагаю, является более безопасным способом (косвенно) определить, должно ли количество строк быть ceil(sqrt(n)) или floor(sqrt(n)).

person Aasmund Eldhuset    schedule 31.05.2011

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

std:vector<CGRect> arrange(CGRect &original, int numWindows)
{
  int columns = ceil(sqrt(numWindows));
  int fullRows = numWindows / columns;
  int orphans = numWindows % columns;   // how many 'odd-sized' ones on our bottom row.

  int width =  original.width/ columns;
  int height = original.height / (orphans == 0 ? fullRows : (fullRows+1)); // reduce height if there are orphans

  std:vector<CGRect> output;

  //Calculate rectangles
  for (int y = 0; y < fullRows; ++y)
    for (int x = 0; x < columns; ++x)
      output.push_back(CGRect(x * width, y * height, width, height));

  if (orphans > 0)
  {
    int orphanWidth = original.width / orphans);
    for (int x = 0; y < orphans; ++x)
      output.push_back(CGRect(x * orphanWidth , y * height, orphanWidth , height));
  }

  return output;
}
person Roddy    schedule 31.05.2011

Вы хотите найти факторы n, которые ближе всего к sqrt (n).

factorMax = floor(sqrt(n));
factorY = 1;
for (x = factorMax; x > 0; x--) {
if ( (n % x) == 0 ) {
    factorY = x;
    break;
}

factorX = floor(n/factorX)

Это должно дать вам равное распределение строк и столбцов. Это не удастся, если вы выберете простое число, поскольку наибольший фактор ‹ sqrt (n) будет равен 1.

person JamesT    schedule 31.05.2011
comment
factorX = floor(n/factorX), не должно быть n/factorY? - person Alejandro Sazo; 24.06.2016

Попробуй это:

CGRect rect = myView.bounds;
    CGRect slice;
    CGRect remainder;
    /*enum CGRectEdge {
     CGRectMinXEdge,
     CGRectMinYEdge,
     CGRectMaxXEdge,
     CGRectMaxYEdge
     };*/

    //CGRectDivide(<#CGRect rect#>, <#CGRect *slice#>, <#CGRect *remainder#>, <#CGFloat amount#>, <#CGRectEdge edge#>)
    CGRectDivide(rect, &slice, &remainder, rect.size.width/2, CGRectMinXEdge);

    LOG_DBUG(@"%@", NSStringFromCGRect(rect));
    LOG_DBUG(@"%@", NSStringFromCGRect(slice));
    LOG_DBUG(@"%@", NSStringFromCGRect(remainder));
person Raunak    schedule 16.08.2013