我正在创建一个应用程序,它采用许多大小相等的矩形并将它们放在屏幕上的网格中。我有大部分逻辑用于调整单元格中矩形的大小和居中,但我遇到了定义矩形必须符合的网格的实际部分的问题。
理想情况下,最后我会有这样的函数(伪代码):
function getGridDimensions (rect surface, int numItems, float hwRatio) {
// do something to determine grid-height and grid-width
return gridDimensions;
}
我最初的抨击涉及到这样的事情:
gridHeight = surface.width / sqrt(numItems);
gridWidth = surface.height / sqrt(numItems);
如果我的项目都是完美的正方形,这可以很好地工作,但由于它们是矩形,每个单元格中都有很多未使用的空白区域。
对谷歌的任何想法或条款可能会指引我朝着正确的方向发展?
答案 0 :(得分:15)
我对你的一些输入参数有点不清楚,但我假设你有矩形的高度和宽度,矩形的数量和理想的高宽比(即首选的gridheight / gridwidth)。
如果是这种情况,那么我可能会从“标准化”您的尺寸开始,因此为了以下计算的目的,我们说宽度单位与矩形的宽度相同,同样对于单位高度。如果以实际单位表示的高度/宽度比为k,那么以Rectange为单位的高度/宽度比将为k * RectWidth / RectHeight。我会称之为K。
所以现在每个矩形的面积都是1,所以我们的总面积是N,其中N是项目数。然后我们可以通过说gridHeight * gridWidth = N和gridHeight / gridWidth = K
来近似我们的高度添加宽度来给自己提供我们首选的网格宽高比。通过这些,我们得到gridHeight = sqrt(KN)和gridWidth = sqrt(N / K)。
如果你将其中一个关闭到一个合适的整数(我不确定哪一个最接近整数舍入将给你最好的结果,或者如果它的任何四舍五入将给出该值的最小百分比变化是最好的 - 如果你非常在意的话,你可以随时尝试所有这四种方法。一旦你有一个整数值,你就可以通过找到可以乘以另一个并且仍然大于N的最小整数来计算另一个,以确保你适合网格中的所有矩形。)
然后,您可以通过将高度乘以rectHeight并将wdith乘以RectWidth来将整数值更改回实数值。
希望一切都有道理。 :)
编辑工作示例:
所需的最终网格宽高比= 1024/768(k)(假设768是宽度,1024是高度 - 我一直想把它作为标准屏幕分辨率反过来:))
“标准化”宽高比=(1024/768)*(300/109)= 3.6697(K)
网格高度因此是sqrt(KN)= sqrt(366.97)= 19.16
网格宽度为sqrt(N / K)= 5.22
观察这一点,我们可以直观地看到宽度5和高度20将是我们的最佳匹配。其他选项可能是6和19.但是这会浪费更多空间(我认为实际上可能实际上最小化宽度和高度的乘积,这是最好的计算,但我不确定)。
这是我们在单元格中的网格大小。然后将其缩放到1500乘以2180的像素尺寸。缩小到适合768x1024意味着将两者除以2.129(1500/768和2180/1024中的较大者)。所以你的图像将缩小2.129倍到141x51(ish),你使用的总面积实际上是705x1020,这应该给出最小的空白。
希望现在更有意义。我承认,我错了几次把真正的价值放进去,所以我完全理解为什么你想要一个有效的例子。 ; - )
答案 1 :(得分:0)
所以我认为我有一个可以通过蛮力获得最佳答案的算法。最多100-1000个项目仍应相当快。这是python中的算法。基本上,它会通过所有方式将项目分散到行和列中,然后选择效率最高的方法。
def calculate_best_screen_packing(N, img_resolution = (800,600), screen_resolution = (1920, 1080)):
screen_x = screen_resolution[0]
screen_y = screen_resolution[1]
screen_area = screen_x * screen_y
img_x = img_resolution[0]
img_y = img_resolution[1]
img_aspect = img_x / img_y
best_dims = (None,None)
best_eff = 0.0
for n_rows in range(1,N//2 +1):
#print(i)
n_cols = N // n_rows
if N % n_rows != 0: n_cols = n_cols+1
#print(n_rows, n_cols)
# Test by maximising image height
img_y_scaled = screen_y / n_rows
img_x_scaled = img_y_scaled * img_aspect
img_area_scaled = img_x_scaled * img_y_scaled
eff = img_area_scaled * N / screen_area
#print(img_x_scaled, img_y_scaled, eff)
if eff <= 1.0 and eff > best_eff:
best_eff = eff
best_dims = (n_rows, n_cols)
# Test by maximising image width
img_x_scaled = screen_x / n_cols
img_y_scaled = img_x_scaled / img_aspect
img_area_scaled = img_x_scaled * img_y_scaled
eff = img_area_scaled * N / screen_area
#print(img_x_scaled, img_y_scaled, eff)
if eff <= 1.0 and eff > best_eff:
best_eff = eff
best_dims = (n_rows, n_cols)
#print("Best dims:",best_dims,best_eff)
return best_dims