【问题标题】:Merging and splitting overlapping rectangles to produce non-overlapping ones合并和分割重叠的矩形以产生不重叠的矩形
【发布时间】:2010-05-16 05:06:58
【问题描述】:

我正在寻找如下算法:

给定一组可能重叠的矩形(所有这些都是“不旋转的”,可以统一表示为(左、上、右、下)连音等...),它返回一个最小的(非-rotated) 不重叠的矩形,占据相同的区域。

乍一看似乎很简单,但事实证明很棘手(至少要有效地完成)。

这个/ideas/pointers 有一些已知的方法吗?

对于不一定是最小但启发式小集的方法也很有趣,产生任何有效输出集的方法也是如此。

【问题讨论】:

  • 您的意思是合并矩形并将其拆分为矩形区域吗?还是必须在输出中表达原始行的并集?换句话说,如果我有两个相邻的 10x20 矩形,我可以输出一个 20x20 的正方形吗?或者,如果我有两个输入,我是否需要始终至少有两个输出?
  • 输出集(联合)的唯一要求是占据与输入集(联合)相同的区域,并且由不重叠的矩形组成。最好它也是最小的:包括尽可能少的矩形。所以,是的,在这种情况下你最好吐出一个矩形。
  • 你使用什么编程语言?
  • 对于未来出现的任何人 - stackoverflow.com/questions/5919298/… 是此副本的副本,并在答案中提供了最佳和有效的解决方案。

标签: algorithm computational-geometry mathematical-optimization rectangles graphics


【解决方案1】:

我认为基于线扫描算法的东西会起作用:

  • 将所有矩形的最小和最大x 坐标排序到一个数组中,作为“start-rectangle”和“end-rectangle”事件
  • 遍历数组,将遇到的每个新矩形(开始事件)添加到当前集合中
  • 同时,维护一组“非重叠矩形”作为您的输出集
  • 任何时候遇到新的矩形,您都可以检查它是否完全包含在当前/输出集中(简单比较y-coordinates 就足够了)
  • 如果不是,请在输出集中添加一个新矩形,并将y-coordinates 设置为新矩形中未被覆盖的部分。
  • 每当您遇到矩形结束事件时,请停止输出集中不再覆盖任何内容的所有矩形。

我不完全确定这涵盖了所有内容,但我认为通过一些调整应该可以完成工作。或者至少给你一些想法...... :)

【讨论】:

  • 这条评论为我激发了一些好主意,我已经完成了大部分的实现,但在一些边缘情况下遇到了麻烦。你能详细说明一下最终事件的情况吗?矩形“不再覆盖任何东西”是什么意思?
  • @schellsan - 想象一条垂直线“从左到右”扫过输入集(-x 到 +x)。当您点击任何输入矩形的开头时,您需要创建一个新的输出矩形来覆盖它,除非它已经被您现有的输出矩形之一完全覆盖。当您到达任何输入矩形的末尾时,如果该空间(y 坐标)中没有其他输入矩形,您需要结束一些输出矩形(并且可能创建一些新矩形,具体取决于输入配置)。跨度>
  • 是的,这就是我的想法。感谢您的帮助!
【解决方案2】:

所以,如果我想这样做,我要做的第一件事就是想出一个统一的网格空间。查找所有唯一的 x 和 y 坐标,并创建到索引空间的映射。因此,如果您有 x 值 { -1, 1.5, 3.1 },则将它们映射到 { 0, 1, 2 },对于 y 也是如此。然后每个矩形都可以用这些打包的整数坐标精确地表示。

然后我会分配一个位向量或覆盖整个网格的东西,并在网格中栅格化您的矩形。拥有网格的好处在于它非常易于使用,并且通过将其限制为唯一的 x 和 y 坐标,它既最小又精确。

想出一个非常快速的解决方案的一种方法是转储网格的每个“像素”。通过映射运行它们,然后就完成了。如果您正在寻找更优化的矩形数量,那么您就遇到了某种搜索问题。

让我们看一下 4 个相邻像素,一个 2x2 的小正方形。当我编写这样的算法时,我通常会考虑顶点、边缘和面。所以,这些是顶点周围的面。如果其中 3 个打开而 1 个关闭,则您有一个凹角。这是唯一无效的情况。例如,如果我没有任何凹角,我只需抓住范围并将整个事物作为单个矩形倾倒。对于每个凹角,您需要决定是水平分割、垂直分割还是两者兼而有之。我认为分割是在查找范围时标记边缘不交叉。您也可以将其作为成套着色来进行,这对您来说更容易。

凹角及其分割方向是您的搜索空间。您可以使用任何您喜欢的优化算法。分支/绑定可能运作良好。我敢打赌,您可以找到一个表现良好的简单启发式方法(例如,如果在您正在考虑的那个直接对面有另一个凹角,则始终沿该方向拆分。否则,沿较短方向拆分)。你可以贪婪。或者您可以在两个方向上拆分每个凹形顶点,这通常会比将每个“像素”输出为矩形给您的矩形更少,而且非常简单。

阅读本文后,我意识到可能有些地方不清楚。如果您希望我澄清任何事情,请告诉我。

【讨论】:

    猜你喜欢
    • 2015-06-13
    • 2016-10-17
    • 2018-11-02
    • 2016-06-27
    • 1970-01-01
    • 2023-04-01
    • 2012-06-21
    • 2014-05-13
    • 2017-01-15
    相关资源
    最近更新 更多