我有一个动态数量的同等比例和大小的矩形物体,我想在屏幕上最佳地显示。我可以调整对象的大小,但需要保持比例。
我知道屏幕尺寸是什么。
如何计算分割屏幕所需的最佳行数和列数以及将对象缩放到需要的大小?
谢谢,
杰米。
答案 0 :(得分:3)
假设所有矩形都具有相同的尺寸和方向,并且不应更改这些矩形。
让我们玩吧!
// 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'来找出行和列的使用量。
答案 1 :(得分:2)
这几乎与SO kenneth's question完全相同。他还wrote it up on his blog。
如果您在一个维度中缩放比例以便打包方块,则会出现同样的问题。
答案 2 :(得分: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
是行数。
请注意,其中一个必须ceiling
而另一个floor
,否则您将截断数字,可能会错过一行。
答案 3 :(得分:1)
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布局会产生最大的矩形。同样清楚的是,矩形大小(作为行计数的函数)在极值处最差(最小),在中间点处最佳(最大)。假设矩形的数量是适度的,你可以用你选择的语言简单地编写上面的计算,但是一旦结果区域在上升到最大值后开始减少就会挽救。
这是一个快速而肮脏(但我希望,相当明显)的解决方案。如果矩形的数量变得足够大,可以通过各种方式调整性能:
答案 4 :(得分:0)
您提到的行和列表明您设想将矩形排列在网格中,可能有几个空格(例如一些底行)未填充。假设情况如此:
假设您缩放对象,使得(一个尚未知的数字)n
对象适合整个屏幕。然后
objectScale=screenWidth/(n*objectWidth)
现在假设有N个对象,所以会有
nRows = ceil(N/n)
对象行(其中ceil是Ceiling function),将占用
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
时 - 这两种情况都很容易处理。