6

我有一个动态数量的等比例和大小的矩形对象,我想在屏幕上以最佳方式显示。我可以调整对象的大小,但需要保持比例。

我知道屏幕尺寸是多少。

如何计算将屏幕划分为所需的最佳行数和列数以及将对象缩放到什么大小?

谢谢,

杰米。

4

5 回答 5

5

假设所有矩形都具有相同的尺寸和方向,并且不应更改。

让我们玩!

// Proportion of the screen
// w,h width and height of your rectangles
// W,H width and height of the screen
// N number of your rectangles that you would like to fit in

// ratio
r = (w*H) / (h*W)

// This ratio is important since we can define the following relationship
// nbRows and nbColumns are what you are looking for
// nbColumns = nbRows * r (there will be problems of integers)
// we are looking for the minimum values of nbRows and nbColumns such that
// N <= nbRows * nbColumns = (nbRows ^ 2) * r
nbRows = ceil ( sqrt ( N / r ) ) // r is positive...
nbColumns = ceil ( N / nbRows )

我希望我的数学是正确的,但这与您正在寻找的东西相去甚远;)

编辑:有一个比率和宽度和高度之间没有太大区别......

// If ratio = w/h
r = ratio * (H/W)

// If ratio = h/w
r = H / (W * ratio)

然后你回来使用'r'来找出使用了多少行和列。

于 2009-10-05T14:56:46.243 回答
2

Jamie,我将“最佳行数和列数”解释为“多少行和列将提供最大的矩形,与所需的比例和屏幕尺寸一致”。这是该解释的简单方法。

每个可能的选择(矩形的行数和列数)都会导致指定比例的矩形的最大可能大小。循环可能的选择并计算结果大小实现了对可能解决方案空间的简单线性搜索。这是执行此操作的一些代码,使用 480 x 640 的示例屏幕和 3 x 5 比例的矩形。

def min (a, b)
  a < b ? a : b
end

screenh, screenw = 480, 640
recth, rectw = 3.0, 5.0
ratio = recth / rectw

puts ratio

nrect = 14

(1..nrect).each do |nhigh|
  nwide = ((nrect + nhigh - 1) / nhigh).truncate
  maxh, maxw = (screenh / nhigh).truncate, (screenw / nwide).truncate
  relh, relw = (maxw * ratio).truncate, (maxh / ratio).truncate
  acth, actw = min(maxh, relh), min(maxw, relw)
  area = acth * actw
  puts ([nhigh, nwide, maxh, maxw, relh, relw, acth, actw, area].join("\t"))
end

运行该代码提供以下跟踪:

1 14 480 45 27 800 27 45 1215
2 7 240 91 54 400 54 91 4914
3 5 160 128 76 266 76 128 9728
4 4 120 160 96 200 96 160 15360
5 3 96 213 127 160 96 160 15360
6 3 80 213 127 133 80 133 10640
7 2 68 320 192 113 68 113 7684
8 2 60 320 192 100 60 100 6000
9 2 53 320 192 88 53 88 4664
10 2 48 320 192 80 48 80 3840
11 2 43 320 192 71 43 71 3053
12 2 40 320 192 66 40 66 2640
13 2 36 320 192 60 36 60 2160
14 1 34 640 384 56 34 56 1904

由此可见,4x4 或 5x3 布局将产生最大的矩形。同样清楚的是,矩形大小(作为行数的函数)在极端情况下是最差的(最小的),在中间点是最好的(最大的)。假设矩形的数量适中,您可以简单地用您选择的语言对上面的计算进行编码,但是一旦结果面积在上升到最大值后开始减少,就立即退出。

这是一个快速而肮脏(但我希望相当明显)的解决方案。如果矩形的数量变得足够大,您可以通过多种方式调整性能:

  • 使用更复杂的搜索算法(划分空间并递归搜索最佳段),
  • 如果程序过程中矩形的数量在增长,保留之前的结果,只搜索附近的解决方案,
  • 应用一点微积分来获得更快、更精确但不太明显的公式。
于 2009-10-07T12:58:37.520 回答
2

这几乎与肯尼斯关于 SO的问题完全一样。他还在他的博客上写了它

如果您在一个维度上缩放比例以便包装正方形,这将成为同样的问题。

于 2009-10-11T05:46:57.507 回答
1

我喜欢这样做的一种方法是使用面积的平方根:

r = number of rectangles

w = width of display

h = height of display

然后,

A = (w * h) / r是每个矩形的面积

L = sqrt(A)是每个矩形的底边长度。

如果它们不是正方形,则只需相应地相乘以保持相同的比率。

另一种做类似事情的方法是只取矩形数量的平方根。这将为您提供网格的一维(即列数):

C = sqrt(n)是网格中的列数

R = n / C是行数。

请注意,其中一个必须这样做ceilingfloor否则您将截断数字并可能错过一行。

于 2009-10-05T14:36:38.037 回答
0

您提到的行和列表明您设想将矩形排列在网格中,可能有一些空格(例如,底部的一些行)未填充。假设是这种情况:

假设您缩放对象,使得它们中的(未知数量)n适合整个屏幕。然后

objectScale=screenWidth/(n*objectWidth)

现在假设有 N 个对象,所以会有

nRows = ceil(N/n)

对象行(其中 ceil 是Ceiling 函数),它将占用

nRows*objectScale*objectHeight

的垂直高度。我们需要找到n,并希望选择最小的n,使得这个距离小于screenHeight

由于天花板函数的存在,一个简单的数学表达式n变得更加棘手。如果列数将相当小,可能最简单的查找n方法就是循环增加n直到满足不等式。

编辑:我们可以从上限开始循环

floor(sqrt(N*objectHeight*screenWidth/(screenHeight*objectWidth)))

对于 n,然后向下工作:然后在 O(sqrt(N)) 中找到解决方案。O(1) 解决方案是假设

nRows = N/n + 1

或采取

n=ceil(sqrt(N*objectHeight*screenWidth/(screenHeight*objectWidth)))

(Matthieu M. 的解决方案),但它们的缺点是 的值n可能不是最优的。

边界情况发生在何时N=0、何时N=1以及对象的纵横比是这样的objectHeight/objectWidth > screenHeight/screenWidth——这两种情况都很容易处理。

于 2009-10-05T14:09:39.153 回答