【问题标题】:how to check a collection of rectangles for holes and intersctions?如何检查矩形集合中的孔和交互?
【发布时间】:2012-02-15 15:00:17
【问题描述】:

我正在寻找一种方法来检查矩形集合 (Java TreeSet) - 由“可比较”Java 类实现,该类使用 google guava Range for x 和 y 范围 - 交叉点和孔。 我知道一个选项可能是使用 kd-trees,但我不知道如何构建这样一个 kd-tree(对于矩形,它应该是 4d,不是吗?)以及如何解决问题(交叉点,孔)。

排序将 x 轴优先于 y 轴。

编辑:(尝试重述问题):用例是创建任意表(由 2 或 3 个矩形块“标题”、“前列”、“数据”组成) .我必须保证每个块中没有交叉点和漏洞(即由无效的 html 或其他表格数据源提供)(除此之外,块必须组合在一起)。 目前(刚刚有了一个想法)我尝试保存一个二维数组,其中位置(x,y)被占用。最后,所有位置都必须被占用一次。

【问题讨论】:

  • 我建议您重述问题,尽可能详细。如果你不能说明问题,解决方案就很难看到。
  • 矩形的边缘平行于 x/y 轴还是可以在任何方向上?
  • 边缘是平行的,要填充的矩形由所有 x 范围和所有 y 范围的跨度定义。
  • 您当前检查所有 (x,y) 位置的解决方案是否不起作用?您是否需要支持如此大的 (x,y) 坐标,以至于填充二维数组会太慢?
  • 这些区域很小,包含的矩形总是少于 1000 个 - 我说的是人类可以阅读的表格。

标签: java algorithm tree geometry treeset


【解决方案1】:

有很多方法可以解决这类问题,每种方法都有不同的优缺点。以下是其中一些:

矩形对交点 + 面积总和

查看每一对矩形 - 如果两个矩形相交,则存在重叠。将矩形区域相加并检查总和是否与画布区域匹配 - 如果区域不匹配,则存在间隙。

绘画

这就是您提到的方法:创建一个具有画布尺寸的二维数组。然后,遍历矩形并将它们“绘制”到数组中。

对这种方法的一个优化是坐标压缩。假设您有矩形 [(10,20), (15,25)] 和 [(7,3), (15, 25)]。您可以查看不同的 x 坐标 (7, 10, 15) 并将它们重新映射到 (0, 1, 2),以及不同的 y 坐标 (3, 20, 25) 并将它们重新映射到 (0, 1, 2)。然后,剩下的矩形是 [(1, 1), (2, 2)] 和 [(0,0), (2,2)],所以绘画只需要一个 3x3 数组,而不是 26x26数组。

扫描线算法

从左到右扫过一条线,停在“有趣”的点,并跟踪哪些区域被占用。

二维范围树

一种可以在矩形范围内高效执行查询的数据结构。

选择哪一个?

这取决于您拥有的矩形的数量、它们在该区域中的分布方式、您的算法必须有多快、您愿意承担多少复杂性等等。我提到的前两种算法要简单得多比后两者,所以我建议从那里开始。

更多信息

如果您想了解有关这些算法的更多信息,请尝试在线搜索“矩形联合”。最有效的解决方案是扫线算法。

以下是扫描线算法的一些参考资料:

  1. What is an Efficient algorithm to find Area of Overlapping Rectangles
  2. http://compgeom.cs.uiuc.edu/~jeffe/open/klee.html
  3. J. L. Bentley,Klee 矩形问题的算法。未发表的笔记,卡内基梅隆大学计算机科学系,1977 年

参考文献3.通常作为矩形并集的线扫算法的原始来源给出,但我不得不承认我实际上并没有在网上找到该论文,可能是因为它是“未发表”...

【讨论】:

  • 能否请您提供描述此类问题及其解决方案的书籍或 inetlink 参考 - 你让我很好奇。在我的特殊情况下,我不必处理太多矩形(大约 100 个),但只要我知道有更好的算法,我就忍不住尝试更好/最好的算法
  • 我在回复中添加了“更多信息”部分 - 希望对您有所帮助。玩得开心学习算法。 :)
  • @Igor 是正确的。 Bentley 在这一领域写了很多经典和开创性的论文。他的论文对我来说是无价的。不要最小化您关心正交边界的事实。这是一个巨大的交易,因为在这个领域已经做了很多工作。对于这个问题,扫描线方法实现起来非常简单,只需选择一个轴并将正交边投影到该轴上,该轴上的事件线将表示矩形的开始或结束。参见计算几何的第 8 章:Preparata 和 Shamos 的介绍。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-09
  • 2019-06-07
  • 1970-01-01
  • 2020-06-28
  • 2023-03-14
  • 2015-06-06
  • 1970-01-01
相关资源
最近更新 更多