找出一个矩形是否被它上面的矩形遮挡了?

时间:2011-02-17 11:16:47

标签: algorithm language-agnostic

我有一组矩形和一个参考矩形。我想知道参考矩形是否被它上面的矩形(集合中的所有矩形)完全遮盖了。例如:

http://i54.tinypic.com/246w57l.png

显而易见的解决方案是创建一个bool或位图矩阵,然后简单地将所有矩形blit并检查是否有任何未覆盖的内容,但这不是一个选项。这必须每秒进行很多次。

我提出了这个想法:对于每个矩形,将它与每个其他矩形相交(并将它们限制在参考矩形),从而产生一组不相交的较小矩形,如下所示: http://i54.tinypic.com/s1j30h.png

然后简单地添加它们的所有区域并从参考矩形的区域中减去。但是我不确定如何做到最好。欢迎任何其他想法,建议或例子。

谢谢。

1 个答案:

答案 0 :(得分:3)

设n为覆盖矩形的数量。可以使用平面扫描(http://en.wikipedia.org/wiki/Sweep_line_algorithm)和增强的自下而上的展开树(http://en.wikipedia.org/wiki/Splay_tree)在时间O(n log n)内解决此问题。

  1. 将所有覆盖矩形剪切为参考。

  2. 通过排序,将问题减少到覆盖矩形的所有x坐标在[0,2n)中为整数的问题。同样地转换y坐标。

  3. 创建一个2n节点的展开树。节点j的值是在开放间隔(j,j + 1)中与扫描线相交的矩形的数量。对于O(log n)-time更新,不要将j的值存储在j中,而是将j的值与j的父值相加(root存储其真值)。旋转稍微复杂一些:旋转

        y          x
       / \        / \
      x   c  ->  a   y
     / \            / \
    a   b          b   c
    

    涉及更新

    b.diff += x.diff;  // if b exists
    x.diff += y.diff;
    y.diff -= x.diff;
    

    每个节点还跟踪其子树最小值。为了与先前描述的值表示兼容,节点j存储其子树最小值与其值的差值。轮换期间:

    y.diffmin = min(0, b.diffmin + b.diff, c.diffmin + c.diff);
    

    在展开操作结束时,以相同方式更新根。如果不存在则省略b或c。

  4. 清扫线。对于[0,2n)中的x,找到左侧为x的所有矩形,并按如下方式更新树。对于从y0到y1的矩形,展开y1并增加其左子的diff(并重新计算diffmin),然后展开y0并减少其左子的diff。

    处理完所有左侧后,检查树分钟。如果它为零,则不包括引用。

    以相同的方式处理右侧(说明中的交换增量和减量)。