我有一组矩形和一个参考矩形。我想知道参考矩形是否被它上面的矩形(集合中的所有矩形)完全遮盖了。例如:
http://i54.tinypic.com/246w57l.png
显而易见的解决方案是创建一个bool或位图矩阵,然后简单地将所有矩形blit并检查是否有任何未覆盖的内容,但这不是一个选项。这必须每秒进行很多次。
我提出了这个想法:对于每个矩形,将它与每个其他矩形相交(并将它们限制在参考矩形),从而产生一组不相交的较小矩形,如下所示: http://i54.tinypic.com/s1j30h.png
然后简单地添加它们的所有区域并从参考矩形的区域中减去。但是我不确定如何做到最好。欢迎任何其他想法,建议或例子。
谢谢。
答案 0 :(得分:3)
设n为覆盖矩形的数量。可以使用平面扫描(http://en.wikipedia.org/wiki/Sweep_line_algorithm)和增强的自下而上的展开树(http://en.wikipedia.org/wiki/Splay_tree)在时间O(n log n)内解决此问题。
将所有覆盖矩形剪切为参考。
通过排序,将问题减少到覆盖矩形的所有x坐标在[0,2n)中为整数的问题。同样地转换y坐标。
创建一个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。
清扫线。对于[0,2n)中的x,找到左侧为x的所有矩形,并按如下方式更新树。对于从y0到y1的矩形,展开y1并增加其左子的diff(并重新计算diffmin),然后展开y0并减少其左子的diff。
处理完所有左侧后,检查树分钟。如果它为零,则不包括引用。
以相同的方式处理右侧(说明中的交换增量和减量)。