Algorithm 如何优化矩形的布局
我有一个动态的数量相等的比例和大小的矩形对象,我想最好地显示在屏幕上。我可以调整对象的大小,但需要保持比例Algorithm 如何优化矩形的布局,algorithm,math,layout,screen,rectangles,Algorithm,Math,Layout,Screen,Rectangles,我有一个动态的数量相等的比例和大小的矩形对象,我想最好地显示在屏幕上。我可以调整对象的大小,但需要保持比例 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)
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
我知道屏幕尺寸是多少
如何计算屏幕分割所需的最佳行数和列数,以及缩放对象所需的大小
谢谢
Jamie.您提到的行和列表明您设想将矩形排列在网格中,可能会有一些空格(例如底部的一些空格)未填充。假设情况如此: 假设您缩放对象,使其(一个未知数字)
n
适合整个屏幕。然后
objectScale=screenWidth/(n*objectWidth)
现在假设有N个对象,那么将有
nRows = ceil(N/n)
对象行(其中ceil是
nRows*objectScale*objectHeight
垂直高度的。我们需要找到n
,并希望选择最小的n
,以便此距离小于屏幕高度
由于上限函数的存在,使得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
时,会出现边界情况-这两种情况都很容易处理。我喜欢的一种方法是使用面积的平方根:
让
r=矩形数
w=显示宽度
h=显示高度
那么
A=(w*h)/r
是每个矩形的面积
及
L=sqrt(A)
是每个矩形的基本长度
如果它们不是平方的,那么只需相应地相乘以保持相同的比率
另一种做类似事情的方法是只取矩形数的平方根。这将为您提供网格的一个维度(即列数):
C=sqrt(n)
是网格中的列数
及
R=n/C
是行数
请注意,其中一个必须是天花板
,另一个是地板
,否则您将截断数字并可能丢失一行。假设所有矩形具有相同的尺寸和方向,并且不应更改
我们来玩吧
// 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 )
然后再使用“r”来找出行和列的使用量。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
由此可知,无论是4x4还是5x3布局都会产生最大的矩形。同样清楚的是,矩形大小(作为行数的函数)在极值处最差(最小),在中间点处最好(最大)。假设矩形的数量适中,您可以简单地用您选择的语言编写上面的计算代码,但一旦生成的面积在上升到最大值后开始减少,就可以退出
这是一个快速而肮脏的(但我希望是相当明显的)解决方案。如果矩形的数量变得足够大而麻烦,您可以通过多种方式调整性能:
- 使用更复杂的搜索算法(划分空间并递归搜索最佳分段)
- 如果在编程过程中矩形的数量不断增加,请保留以前的结果,只搜索附近的解决方案
- 应用一点微积分,得到一个更快,精确,但不太明显的公式
这几乎和这里一模一样。他也
如果您在一维中缩放比例,以便填充正方形,则会出现相同的问题。它们是否都具有相同的大小和方向?你能转动它们吗?或者它们应该保持比例和方向?我很确定这是一个NP完全问题。@John:这个NPC怎么样?我认为它在最坏的情况下是线性的(在可能的列数上迭代一次,即[1,N])。问题是如何优化计算'N'。当然,如果我知道要在屏幕上放置多少个对象,那么就很容易计算出其他所有内容,但这是个未知数。问题是如何计算最佳“n”,从而计算所需的行数,然后计算得到的对象宽度和高度。。。干杯,杰米。绝对-看编辑:我不认为最佳n的解析表达式是可能的,但可以最小化搜索。这篇博客文章很棒,而且对于一致的布局更有用。Kenneth问题中的答案对于理论最大化(即旋转正方形以最小化矩形中的空间)有更有用的答案。
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