在2D平面上反转一组矩形

时间:2010-11-21 19:02:13

标签: algorithm rectangles

我有一个整数维矩形平面。在这个平面内部,我有一组非交叉矩形(整数维和整数坐标)。

我的问题是如何才能有效地找到该集的逆;这是平面中未包含在子矩形中的部分。当然,这个点集合形成了一组矩形 - 这些是我感兴趣的。

我当前的天真解决方案使用布尔矩阵(平面的大小),并通过将点i,j设置为0来实现,如果它包含在子矩形中,则为1。然后我遍历矩阵的每个元素,如果它是1(自由),则试图从该点向外“生长”一个矩形。唯一性不是问题(任何合适的矩形都很好)。

有没有哪种算法可以更有效地解决这个问题? (即,无需求助于布尔矩阵。

5 个答案:

答案 0 :(得分:7)

是的,这很简单。我以前在SO上回答了一个几乎相同的问题,但还没有找到它。

无论如何,基本上你可以这样做:

  • 以包含单个输出矩形的输出列表开始,该输出矩形等于感兴趣的区域(某些任意边界框定义了感兴趣的区域并包含所有输入区域)
  • 每个输入矩形
    • 如果输入rect与输出列表中的任何rects相交
      • 删除旧输出rect并生成最多四个新输出 表示交叉点之间差异的rects 和原始输出矩形

可选的最后一步:遍历输出列表,查找可以合并为单个矩形的对的对(即,共享公共边的rects对可以组合成单个rect)。

答案 1 :(得分:5)

好的!第一次实施! (java),基于@Paul's回答:

List<Rectangle> slice(Rectangle r, Rectangle mask)
{
        List<Rectangle> rects = new ArrayList();

        mask = mask.intersection(r);

        if(!mask.isEmpty())
        {
                rects.add(new Rectangle(r.x, r.y, r.width, mask.y - r.y));
                rects.add(new Rectangle(r.x, mask.y + mask.height, r.width, (r.y + r.height) - (mask.y + mask.height)));
                rects.add(new Rectangle(r.x, mask.y, mask.x - r.x, mask.height));
                rects.add(new Rectangle(mask.x + mask.width, mask.y, (r.x + r.width) - (mask.x + mask.width), mask.height));

                for (Iterator<Rectangle> iter = rects.iterator(); iter.hasNext();)
                        if(iter.next().isEmpty())
                                iter.remove();
        }
        else rects.add(r);

        return rects;
}

List<Rectangle> inverse(Rectangle base, List<Rectangle> rects)
{
        List<Rectangle> outputs = new ArrayList();
        outputs.add(base);

        for(Rectangle r : rects)
        {
                List<Rectangle> newOutputs = new ArrayList();

                for(Rectangle output : outputs)
                {
                        newOutputs.addAll(slice(output, r));
                }

                outputs = newOutputs;
        }
        return outputs;
}

可能是工作示例here

答案 2 :(得分:2)

您应该查看空间填充算法。这些算法是用一些几何图形来填充给定空间的。根据您的需要修改此类算法并不困难。

这种算法是从头开始(空白空间),所以首先用二维平面上已有的方框填充内部数据。然后你让算法完成剩下的工作 - 用另一个框填满剩下的空间。那些盒子正在制作你飞机倒置空间块的清单。

您将这些框保留在某个列表中,然后检查一个点是否在倒置平面上非常容易。您只需遍历列表并检查点是否位于框内。

这是一个site,其中包含大量可能有用的算法。

答案 3 :(得分:0)

我怀疑你可以通过y坐标对矩形进行排序,并采用扫描线方法来获得某个位置。我可能会或可能不会实际构建实现。

答案 4 :(得分:0)

这相对简单,因为你的矩形是不相交的。目标基本上是一组完全覆盖平面的非交叉矩形,一些标记为原始,一些标记为“反向”。

考虑自上而下(或左右或其他)扫描。你有一个当前的“潮汐线”位置。确定您将遇到的下一条水平线的位置是不在潮汐线上的位置。这将为您提供下一个潮汐线的高度。

在这些潮汐线之间,你有一条带,每条垂直线从一条潮线到另一条潮汐线(也许在两个方向上都有)。您可以对这些垂直线的水平位置进行排序,并使用它将条带划分为矩形,并将它们标识为原始矩形(部分)或反向矩形(部分)。

进展到最后,你得到(可能太多太小)的矩形,并且可以选择你想要的那些。您还可以选择(每个步骤)将当前条带中的小矩形与之前的一组潜在可扩展矩形相结合。

即使您的原始矩形可能相交,您也可以这样做,但它更加繁琐。

详细信息留给读者练习; - )