我有一个问题,需要测试给定的矩形集合的并集是否形成一个矩形。我在解决计算几何问题方面没有太多经验。我的解决方法是,由于我知道所有矩形的坐标,因此可以轻松地对点进行排序,然后推导出可能的最大矩形的角点。然后我可以扫描一条线,看看线上的所有点是否都在矩形内。但是,这种方法是有缺陷的,因为并集可能呈“U”形。如果您能指导我正确的方向,那将是一个很大的帮助。
我有一个问题,需要测试给定的矩形集合的并集是否形成一个矩形。我在解决计算几何问题方面没有太多经验。我的解决方法是,由于我知道所有矩形的坐标,因此可以轻松地对点进行排序,然后推导出可能的最大矩形的角点。然后我可以扫描一条线,看看线上的所有点是否都在矩形内。但是,这种方法是有缺陷的,因为并集可能呈“U”形。如果您能指导我正确的方向,那将是一个很大的帮助。
编辑: 如果目标是检查结果对象是否为填充矩形,而不是仅有边缘和角落的矩形,则添加步骤(4)。
4)查找由相交或接触矩形形成的所有线段。注意-根据定义,所有这些线段都是给定矩形的边缘线段。如果一个矩形不接触/相交其他矩形,则线段是它的边缘。
对于每个线段,检查其中点是否在
如果每个线段至少满足其中一个条件,则结果对象是一个填充矩形。
O(h*n)
的时间内完成,变成了O(h)
。 - UmNyobe[][ ]
还是其中一个包含另一个[[] ]
。你可以通过在统一某些内容时不移动到下一个迭代来加快速度,而是继续到索引的末尾再重新迭代。(当一个迭代没有统一或只剩下一个矩形时停止。)
此外,由于统一后得到的矩形的边缘始终大于或等于原始矩形的边缘,因此如果按升序排列索引的边缘大小,则新矩形将插入到您正在检查的相同位置或尚未检查的位置中,因此每次统一都不需要额外的迭代周期。(由于新矩形的边缘大于本次迭代中先前检查过的所有边缘,因此它肯定不会与任何先前检查过的矩形统一。)
为了实现这一点,在特定迭代的每个步骤中,您需要尝试从任一索引的下一个较小边缘开始进行统一:
[A ][B ]
[C ][D ]
可以将A与B统一,C与D统一,然后将AB与CD相统一。最终得到一个剩余的ABCD,因此是可能的。
[A ][B ]
[C ][D ]
可以将A与B统一,C与D统一,但AB不能与CD统一。剩下2个,即AB和CD,因此不可能。
[A ][B ]
[C ][D [E]]
可以将A与B统一,C与D,CD与E,CDE与AB。剩下1个,即ABCDE,因此可能。
[A ][B ]
[C ][D ][E]
A可以与B统一,C可以与D统一,CD可以与AB统一,但E不行。剩下2个,ABCD和E,因此不可能。
如果一个矩形被包含在另一个矩形中,但不共享边界,则此方法无法将它们统一。
解决这个问题的方法是,在遇到一个迭代不统一任何东西并且在得出不能统一矩形集之前,获取具有最宽边缘的矩形,并从索引中丢弃所有其他包含在此最大矩形内的矩形。
这仍然没有解决两种情况。
首先,考虑使用此地图的情况:
A B C D
E F G H
A B C D
E F G H
I J K L
我们有矩形ABIJ、CDHG和EHLI。它们不共享边缘,也不相互包含,而且任何两个矩形都不能合并成一个单独的矩形;但总体上形成了一个矩形。
由于存在这些陷阱,该方法并不完整。但是它可以用来大大减少问题的复杂性并减少需要分析的矩形数量。
你可以推断出最大矩形的角点,然后遍历所有与最大矩形共享边界的矩形,例如底部,并确保线完全包含在它们的边界内。但是,如果矩形中间有空隙会导致失败。我认为复杂度将为O(n2)。
我认为你走在了正确的方向上。当你得到最大可能矩形的坐标后,
如果最大可能矩形是一个有效的矩形,那么它的每一边都必须是原始矩形的边的联合体。你可以扫描原始矩形集,找到那些是我们正在寻找的最大边的一部分的矩形(这可以通过检查X==largestRectangle.Top.X来完成,如果你正在查看顶部边等),让我们称之为S。
对于S中的每条边s,我们可以创建一个区间[from,to]。我们需要检查的所有内容就是所有区间的联合是否与最大矩形的边匹配。这可以通过标准算法以O(nlog(n))的时间复杂度完成,或者通过某些哈希技巧平均O(n)的时间复杂度完成(请参见http://www.careercup.com/question?id=12523672,请看我的最后一条评论(最后一条评论)中的O(n)算法)。
例如,在第一象限中,我们有两个1*1的矩形,它们的左下坐标分别为(0,0)和(1,0)。最大的矩形是2*1,左下坐标为(0,0)。由于[0,1]并[1,2]等于[0,2],顶部和底部与最大矩形匹配,左侧和右侧同理。编辑2:检测空白区域的简单方法是对于不是最大矩形上的点的每个角落,我们向四个方向(对角线)稍微向外移动一点,并检查是否仍在任何矩形内。这是O(n^2)。(这破坏了我美丽的O(nlog(n))!有人能想出更好的主意吗?
计算一个最大的矩形 Big
,它覆盖了所有矩形,表示为 ((min_x,min_y)-(max_x,max_y))
使集合 S
包含矩形 Big:S = (Big)
对于每个矩形 B
在 R
中:
S1 = ()
对于集合 S
中的每个矩形 A
:
S1 = S1 + subtract_rectangle(A, B)
S = S1
如果 S
为空,则矩形的并集是一个矩形。
结束,S
包含未被 R
中任何矩形覆盖的 Big
的部分
如果矩形没有与坐标轴对齐,您可以使用类似的算法,但是使用三角形代替矩形。唯一的问题是减去三角形不那么容易实现,并且处理数字误差可能会很困难。
我以前没有看过类似的问题,所以可能有更有效的解决方法。关键问题在于你不能孤立地看待一个矩形是否包含另一个矩形,因为它们可能是相邻的但仍然形成一个矩形,或者一个矩形可能被多个矩形包含。
除非问题允许你在矩形中间留下空洞,否则你不能只看每个矩形在边界矩形上的投影,尽管这可能是一个快速的初始检查,可以在以下详尽的方法之前执行:
正如jva所说,“您自己的版本没有考虑到矩形的边缘可以彼此不平行。” 这个答案还假设了“平行”的矩形。
如果您有一个网格而不是需要无限精度,取决于矩形的数量和大小以及网格的粒度,可能可以使用暴力方法。
只需取出“最大可能的矩形”,并测试所有点,以查看每个点是否至少在一个较小的矩形中。
一般情况下,以图像思考: