因爲前段時間碰到一個問題,是要對一組相交、重疊、相離的矩形進行切割,一組大致有幾百個矩形,當時寫了個算法,雖然沒有問題單總感覺時間複雜度比較大,判斷次數比較多,那個算法就不發了,今天沒事有研究了下這個問題,發現用線段樹思想愛解決這個問題比較容易,準確說是用線段樹裏面的二維矩形樹,這裏只說下對兩個相交矩形的切割,對一組矩形的切割就比較簡單了。
如下圖,對矩形1按x和y方向切割後
// Clip.cpp : 定義控制檯應用程序的入口點。
//
#include <vector>
//#include <Windows.h>
using namespace std;
typedef struct tagRECT
{
int left;
int top;
int right;
int bottom;
}RECT;
RECT intSect(const RECT rectI, const RECT rectII)
{
RECT rect = {0, 0, 0, 0};
rect.left = max(rectI.left, rectII.left);
rect.right = min(rectI.right, rectII.right);
rect.top = max(rectI.top, rectII.top);
rect.bottom = min(rectI.bottom, rectII.bottom);
return rect;
}
bool isFull(RECT rc)
{
if (rc.left < rc.right && rc.top< rc.bottom)
{
return true;
}
return false;
}
int main()
{
vector<RECT> rcVct;
RECT rectI = {0,0,5,5};
RECT rectII = {3,3,10,10};
RECT inSectRect = intSect(rectI, rectII);
if (!isFull(inSectRect))
{
return 0;
}
//利用線段樹四分思想完成相交矩形的切割
//按x方向切割
int k1 = inSectRect.left;
int k2 = inSectRect.right;
if (rectI.left < k1)
{
RECT temp_rect = {rectI.left, rectI.top, k1, rectI.bottom};
rcVct.push_back(temp_rect);
}
if (k2 < rectI.right)
{
RECT temp_rect = {k2, rectI.top, rectI.right, rectI.bottom};
rcVct.push_back(temp_rect);
}
//按y方向切割
int k3 = inSectRect.top;
int k4 = inSectRect.bottom;
if (rectI.top < k3)
{
RECT temp_rect = {k1, rectI.top, k2, k3};
rcVct.push_back(temp_rect);
}
if (k4 < rectI.bottom)
{
RECT temp_rect = {k1, k4, k2, rectI.bottom};
rcVct.push_back(temp_rect);
}
rcVct.push_back(rectII);
for (vector<RECT>::iterator pos = rcVct.begin(); pos != rcVct.end(); pos++)
{
printf("left: %d, top: %d, right: %d, bottom: %d\n", pos->left, pos->top, pos->right, pos->bottom);
}
return 0;
}
因爲在線測試無法包含Windows.h,所以將RECT自定義了一次。 在線測試(點擊此處運行)