避免碰撞的矩形排列(算法帮助)

9
我有一个(大)横向滚动的视图,还有一堆矩形需要放置在上面。每个矩形都有一个期望的水平位置,但如果需要的话,它可以在一定范围内(一个常数K)变化。这些矩形不能重叠。矩形的垂直位置是任意的(当然要限制在视图的高度内)。
理想情况下,我希望这些矩形的大小是可变的……如果不可能的话,我可以只让它们在一个维度上变化。
现在,这种布局可能会出现无法实现的情况:由于垂直空间是有限的,它们只能在水平方向上移动K像素,可能并不是所有的矩形都能够被绘制出来。为了解决这个问题,每个矩形都有一个优先级(P),优先级较低的矩形应该首先被省略。(可以假设这是非歧义的,并且你总是可以知道任何两个矩形中哪一个的优先级更高。)
我需要的是概念性的算法,但如果你需要具体的内容,这将在iPad上运行,并且需要考虑几千个(>1000但<10,000)矩形。理想情况下,我希望每当用户改变缩放级别时都能够快速重新运行,但如果这不容易实现,我可以缓存位置。这些对象是时间线上的照片,我想让它们大致接近事件发生的时间——我是为了得到更多的照片而进行近似处理。
我看到过像这样的算法,可以避免重叠,但没有同样的想法,即每个项目只允许移动一定距离。显然,如果没有后一个约束条件,你可以显示所有项目,因此我还需要一些方法来知道什么时候不能再显示更多的矩形了。
如果按照描述解决问题太困难,我会欢迎一个更实用的建议。如果一切都失败了,我可以做一些事情,按优先顺序进行,如果可以的话,将每个项目呈现在其期望的位置上,否则尝试在垂直方向上移动它,如果仍然不行,则将其水平移动到允许的限制范围内,然后继续下一个。优先顺序意味着可能会找到一个次优的解决方案,但它会权衡最重要的项目。 enter image description here

这个问题可以加上一两张图片来更好地说明。 - user unknown
图片已创建。很抱歉描述起来有些困难 :) - Amy Worrall
1个回答

5
这是我认为可以实现的一种方法。
第一步是找出新的黄色矩形可能放置的所有位置。不失一般性,我们可以将其存储为矩形左上角的所有可能X-Y位置的列表。自然地,对于这样一个巨大的起始区域,该列表将包含数百万个条目,因此为了节省空间,让我们将此列表以矩形区域集的形式存储。
例如,如果我们的屏幕从X = 0到X = 2999(含)有像素,并且从Y = 0到Y = 999(含)有像素,并且我们的新矩形宽度为300像素,高度为150像素,则新矩形的左上角可以出现在从(X,Y)=(0,0)到(2699,849)的任何位置。让我们将其存储为四元组[0,0,2699,849]。
现在,当我们将每个现有的(红色)矩形放在屏幕上时,其中一些可能性会被排除,因为它们会导致新的(黄色)矩形重叠。例如,如果有一个红色矩形[1100,200,1199,299],则我们的黄色矩形不能将其左上角放置在(X,Y)=(801,51)到(1199,299)的任何位置。
因此,用覆盖相同区域但留下间隙的四个矩形区域替换[0,0,2699,849]。有许多方法可以做到这一点,但这是其中之一:[0,0,1199,50],[1200,0,299,2699],[0,51,800,849],[801,300,2699,849]。
继续向屏幕添加更多红色矩形。每次添加一个时,从列表中减去更多可能性(这通常会导致列表包含更多、更小的“安全区域”)。 (如果您从您提到的[X-K,0,X + K,H]空间开始,则在全屏上具有1000多个矩形的情况下,这可能非常耗时;由于相对较少的矩形会重叠,因此计算速度将更快。)该代码应该仔细编写,并进行大量单元测试,因为会出现栅栏帖错误。
最终结果是屏幕上可能放置新黄色矩形左上角的完整位置列表,以矩形区域列表的形式表示。
第二步:浏览此列表并选择最理想的位置。实际上与您理想的垂直线相交的任何矩形区域都将优先考虑。但是可能没有。在这种情况下,您需要从左侧的区域和右侧的区域中选择最优选项。提示:每种情况只需要考虑每个区域的一个角(右侧区域的左上角,左侧区域的右上角)。

抱歉直到现在才回复您。事实上,最终我选择了一种更简单的布局方法。这个答案绝对是实现我最初提出的要求最简单的方式 :) - Amy Worrall

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接