Разделить прямоугольник на прямоугольники одинакового размера? - PullRequest
11 голосов
/ 31 мая 2011

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

enter image description here

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

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

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

Ответы [ 4 ]

10 голосов
/ 31 мая 2011

Исходя из вашего последнего комментария, я предполагаю, что вы хотите разбить прямоугольник на 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)).

4 голосов
/ 31 мая 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;
}
0 голосов
/ 16 августа 2013

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

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));
0 голосов
/ 31 мая 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)

Это должно дать вам равное распределение строк и столбцов. Если вы выберете простое число, произойдет сбой, поскольку наибольший коэффициент

...