Я делаю что-то похожее на то, что Mac OS X делает с окнами в Exposé.Он адаптируется к соотношению сторон элементов и соотношению сторон доступной области.
В основном, доступная область разделена на строки и столбцы.Элемент помещается в каждую ячейку (пересечение строки и столбца).Элементы должны сохранять свое соотношение сторон (здесь width / height
), несмотря на соотношение сторон ячейки.Количество ячеек должно быть больше или равно количеству предметов.В случае, когда количество ячеек превышает количество элементов, последняя строка будет использована не полностью. Цель состоит в том, чтобы как можно больше предметов использовалось предметами. Я уверен, что чем ближе соотношение сторон каждой ячейки к соотношению сторон предмета, тем лучше.
Следующее хорошо работает, когда соотношение сторон доступной области равно соотношениям элементов:
rows := round(sqrt(count));
columns := ceiling(sqrt(count));
Где: count
- количество элементов;round(x)
округляет x
до ближайшего целого значения, округляя значения на полпути от нуля;и ceiling(x)
возвращает наименьшее целочисленное значение не менее чем x
.
Я знаю, что Compiz использует следующий аналогичный алгоритм, но он не учитывает пропорции элементов и доступную область:
rows := floor(sqrt(count + 1));
columns := ceiling(count / rows);
Где: floor(x)
возвращает наибольшее целое значение, не превышающее x
.
Я собрал следующий алгоритм O (n), который проверяет каждую комбинацию строк и столбцов иищет наилучшее соответствие, но, безусловно, есть алгоритм O (1), поскольку он дает те же результаты, что и первый (O (1)) алгоритм, когда пропорции элементов и доступной области одинаковы:
fit (itemCount, itemRatio, availableRatio)
{
bestRows := infinity;
bestColumns := infinity;
bestDiff := infinity;
for (rows := 1; rows <= count; rows += 1)
{
columns := ceiling(count / rows);
cellWidth := availableRatio / columns;
cellHeight := 1.0 / rows;
cellRatio := cellWidth / cellHeight;
diff := abs(cellRatio - itemRatio);
if (diff < bestDiff)
{
bestRows := rows;
bestColumns := columns;
bestDiff := diff;
if (diff = 0)
break;
}
}
return (bestRows, bestColumns);
}
Где: abs(x)
возвращает абсолютное значение x
.
ПРИМЕЧАНИЕ. Вы можете заметить, что это не оптимизировано вообще
Итак, как лучше всего использовать максимально доступную площадь предметами?(Другими словами, как мне найти наилучший вариант?)