如何获得覆盖另一堆矩形的最小数量的矩形?
假设我有一堆长方形,其中一些相交,一些孤立。 例如,
+--------------- + +-------- + | | | | | | | | | A | | C | | +---------------- + | | | | | | +---------+-------- + | | | | | | +---------|----- + B | | D | | | | | | | +------------------ + +---------------- + +------------------ + +-------- + | | | | | E | | X | +-------------------+ | | | | +-------- + | | +------------ + | | | | | F | | | | | | Y | | | | | +-------------------+ +------------ +
Rect A,B彼此相交,C,D有一个相同的点,E,F有两个相同的点,X,Y是孤立的。
我有两个问题:
+---------+----- + +-------- + | | | | | | | | | | | | | | | | | +--------- + | | | | | | +---------+-------- + | | | | | | +---------+ | | | | | | | | | | | | +-------------------+ +------+----------+ +------------------ + +-------- + | | | | | | | | | | | | | | +---------+ | | +------------ + | | | | | | | | | | | | | | | | +-------------------+ +-------------+
+---------------------------+ +-------------------+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +-------------------+ +---------------------------+ +-------------------+ +---------+ | | | | | | | | | | | | | | +---------+ | | +------------ + | | | | | | | | | | | | | | | | +-------------------+ +-------------+
对于Q1,我完全不知道......对于Q2,我用C ++编写了一些代码,但效率很差。 我相信有更好的方法/算法。
bool intersectRect(const Rect& rect1, const Rect& rect2) {
/* if rect1 and rect2 intersect return true
else return false
*/
}
Rect mergeIntersectRects(const set<Rect>& rects) {
// suppose rects are all intersected. This function only return a smallest Rect that cover all rects.
}
set<Rect> mergeRectToRects(const set<Rect>& rectset, const Rect& rect) {
set<Rect> _intersect_rects;
set<Rect> _unintersect_rects;
for(set<Rect>::const_iterator it = rectset.begin();
it != rectset.end();
++it) {
if(intersectRect(*it, rect))
_intersect_rects.insert(*it);
else
_unintersect_rects.insert(*it);
}
if(!_intersect_rects.empty()) {
_intersect_rects.insert(rect);
return mergeRectToRects(_unintersect_rects,
mergeIntersectRects(_intersect_rects));
}
else {
_unintersect_rects.insert(rect);
return _unintersect_rects;
}
}
算法如下:http://goo.gl/aWDJo
你可以阅读关于寻找凸包算法:http://ralph.cs.cf.ac.uk/papers/Geometry/boxing.pdf
首先,我假设你的矩形都是轴对齐的。
对于第一季度,一种选择是扫描飞机,同时保持位于矩形内部的扫描线上的线段列表。 当您在扫描期间发现每个矩形顶点时,您可以检查它是否修改当前的内部分段,如果需要,可以根据需要开始或结束矩形。
例如,假设您的扫描线从左向右移动:
Current Interior | +-|------------- + +-------- + * | | | | | | | | | | | | | | A | | C | | | | +---------------- + | | | | | | | | +---------+-------- + | | | | | | | | | +-|-------|----- + B | | D | * | | | | | | | | +------------------ + | +---------------- + | +-|---------------- + +-------- + * | | | | | | | | E | | X | | | |-----------------+ | | | | | | +-------- + | | | | +------------ + | | | | | | | | | F | | | | | | | | Y | | | | | | | | +-|-----------------+ +------------ + * |
当扫掠线位于上图所示位置时,有两个内部分段。 也就是说,在A内部和EUF内部。 当扫掠线到达B的最左边时,我们为左边的A部分输出一个矩形。 然后我们用(AUB)的内部替换段列表中的A的内部。
Current Interior | +---------+-|--- + +-------- + * | | | | | | | | | | | | | | | | | | | C | | | | |-------------- + | | | | | | | | +---------+-------- + | | | | | | | | | +---------+ |--- + B | | D | | | | | | | | | | | +------------------ + | +-|-------------- + * | +-----------|------ + +-------- + * | | | | | | | | | | X | | | |-------+ | | | | | | +-------- + | | | | +------------ + | | | | | | | | | | | | | | | | | Y | | | | | | | | +-----------|-------+ +------------ + * |
对于第二季度,答案可以在同一次扫描期间通过跟踪首先添加到列表中的段的x坐标(例如“A的左侧”)以及最小和最大y坐标来计算它跨越其整个生命周期(例如B的底部到A的顶部)。 当段最后从列表中删除(例如“B的右侧”),然后使用这四个坐标输出一个矩形。
在预处理步骤中按字母顺序排列矩形顶点将为O(n * log n)。 处理它们将是O(log n),因为您可以在已知的内部范围上执行二分搜索。 总运行时间应该是O(n * log n)。
Q1:这被称为直线多边形的分割。 来自Rob的评论的回答有很好的描述。 我发现在答案中提到的论文很有用。
Q2:我想你不想让两个不相交的区域相交。 像3个矩形,2个矩形产生L的矩形和L矩形相交覆盖,但不是任何L矩形。
如果是这样,那么可以逐步创建封面。 这是一个简单的算法。
covers = {A}
for each rectangle R
while there is a cover that intersects R, say C
remove C from covers and set R = cover of R and C
add R to covers
此代码在标准格式中效率不高。 具有良好的covers
结构结构,它可以是有效的。
上一篇: How to get minimum count rectangles that covers another pile of rectangle?