假设我有一堆矩形,其中一些是相交的,有些是孤立的。 E. g。
+--------------- + +-------- + | | | | | | | | | A | | C | | +---------------- + | | | | | | +---------+-------- + | | | | | | +---------|----- + B | | D | | | | | | | +------------------ + +---------------- + +------------------ + +-------- + | | | | | E | | X | +-------------------+ | | | | +-------- + | | +------------ + | | | | | F | | | | | | Y | | | | | +-------------------+ +------------ +
矩形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;
}
}
答案 0 :(得分:3)
首先,我假设您的矩形都是轴对齐的。
对于Q1,一个选项是sweep the plane,同时保持沿扫描线的位于矩形内部的线段列表。当您在扫描过程中发现每个矩形顶点时,您可以检查它是否修改当前内部线段,如果是,则根据需要开始或结束矩形。
例如,假设您的扫描线从左向右移动:
Current Interior | +-|------------- + +-------- + * | | | | | | | | | | | | | | A | | C | | | | +---------------- + | | | | | | | | +---------+-------- + | | | | | | | | | +-|-------|----- + B | | D | * | | | | | | | | +------------------ + | +---------------- + | +-|---------------- + +-------- + * | | | | | | | | E | | X | | | |-----------------+ | | | | | | +-------- + | | | | +------------ + | | | | | | | | | F | | | | | | | | Y | | | | | | | | +-|-----------------+ +------------ + * |
当扫描线位于上图所示的位置时,有两个内部区段。即,内部A和内部(E U F)。当扫描线到达B的最左边时,我们输出一个矩形,用于位于左侧的A部分。然后,我们用(A U B)的内部替换段列表中A的内部。
Current Interior | +---------+-|--- + +-------- + * | | | | | | | | | | | | | | | | | | | C | | | | |-------------- + | | | | | | | | +---------+-------- + | | | | | | | | | +---------+ |--- + B | | D | | | | | | | | | | | +------------------ + | +-|-------------- + * | +-----------|------ + +-------- + * | | | | | | | | | | X | | | |-------+ | | | | | | +-------- + | | | | +------------ + | | | | | | | | | | | | | | | | | Y | | | | | | | | +-----------|-------+ +------------ + * |
对于Q2,可以在同一扫描期间通过跟踪首先将片段添加到列表的x坐标(例如“A的左侧”)以及最小和最大y来计算答案。 - 协调它在其生命周期中跨越(例如B的底部到A的顶部)。当段最终从列表中删除时(例如“B的右侧”),然后使用这四个坐标输出一个矩形。
在预处理步骤中按字典顺序对矩形顶点进行排序将为O(n * log n)。处理它们将是O(log n),因为您可以对已知的内部范围进行二分搜索。总运行时间应为O(n * log n)。
答案 1 :(得分:1)
Q1:这称为直线多边形的分区。 Rob的comment的答案有很好的描述。我发现paper中提及的answer很有用。
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
结构的结构良好,效率很高。
答案 2 :(得分:0)
我使用@Damon建议的方法,但使用一些空间索引结构加速相邻矩形搜索,例如四叉树或网格。您需要其中两个,首先构建在输入矩形集上,以搜索要分割的交叉矩形,然后在第一步中获得的分割矩形集上构建,以搜索相邻的矩形进行合并。与天真的方法相比,这应该会大大加快速度。
答案 3 :(得分:0)
以下是算法:http://goo.gl/aWDJo
您可以阅读有关查找凸包算法的信息:http://ralph.cs.cf.ac.uk/papers/Geometry/boxing.pdf