我有一个n大小的Rects集合,其中大多数是相互交叉的。我想删除交叉点并将相交的Rects缩小为较小的非交叉rects。
我可以轻松地强制解决方案,但我正在寻找一种有效的算法。
这是一个可视化:
原件:
加工:
理想情况下,方法签名如下所示:
public static List<RectF> resolveIntersection(List<RectF> rects);
输出将大于或等于输入,其中输出解析上述视觉表示。
答案 0 :(得分:6)
扫描线算法擅长处理2D宇宙中的交叉点。我的意思是考虑从矩形边缘向下移动到下一个矩形边缘的水平线。该线撞击了许多矩形,形成了所谓的活动列表。活动列表会在每次移动时保持更新。
通过研究沿水平线的横坐标范围,您可以检测到重叠。
仔细研究所有配置应该允许你在一次扫描中按照你想要的方式分割矩形,复杂性低于蛮力(接近N ^ 1.5而不是N ^ 2)。
答案 1 :(得分:2)
这是我过去解决的问题。首先使用其中一条边的x或y值对矩形进行排序。让我们说你在y方向上订购并使用上边缘。示例中最顶部的矩形首先按排序顺序排列。对于每个矩形,您都知道它在y方向上的大小。
现在,对于每个条目(称之为当前条目,它对应于一个矩形),您在列表中向前搜索,直到您到达大于当前条目+相应矩形大小的条目。 (称之为停止条目)
当前条目和此停止条目之间的排序列表中的任何条目都将是潜在的交叉点。只需检查矩形x范围是否相交。
当选择在x或y方向上排序时,最好选择较大的尺寸,因为这意味着平均交叉点较少,因此检查较少。
这是一个例子。矩形定义为R(x1,x2,y1,y2),其中x1是左侧,x2是右侧,y1是顶部,y2是底部
rectangle 1 (1,5,0,4)
rectangle 2 (7,9,6,8)
rectangle 3 (2,4,2,3)
rectangle 4 (3,6,3,7)
rectangle 5 (3,6,9,15)
根据y1排序
# y1 size
rectangle 1 0 4
rectangle 3 2 3
rectangle 4 3 4
rectangle 2 6 2
rectangle 5 9 6
因此,矩形1具有y1 + size = 0 + 4 = 4意味着它可能与矩形3(y1值= 3 <4)和矩形4(y1值= 3 <4)相交但不是矩形2( y1值= 6> 4)...无需在2之后检查列表中的任何rectangels
矩形3具有y2 +尺寸= 2 + 3 = 5意味着它可能与矩形4相交(y1值= 3 <5)但不重复2(y1值= 6> 5)不需要检查任何矩形在2之后的列表中
矩形4具有y2 +大小= 3 + 4 = 7意味着它可能与矩形2相交(y1值= 6 <7)但不重复5(y1值= 9> 7)
当然,对于大量的矩形,您通常只需要检查一小部分可能的交叉点。
答案 2 :(得分:-2)