这次是用MFC+OpenGL写的,代码没法全部贴上,上传到下载栏目里好了。点击打开下载链接(现在好像不能上传0积分下载的东西了QAQ)
运行效果:
核心代码(剪裁的核心代码):
int GraphyCut::getCode(const Point a) //得到编码
{
int code = 0;
if (a.y > max(st.y, endd.y))
code |= 8;
if (a.y < min(st.y, endd.y))
code |= 4;
if (a.x > max(st.x, endd.x))
code |= 2;
if (a.x < min(st.x, endd.x))
code |= 1;
return code;
}
bool GraphyCut::isLinesAcross(const Line a, const Line b) //跨立试验
{
int num1 = (a.b.x - a.a.x)*(b.a.y - a.a.y) - (a.b.y - a.a.y)*(b.a.x - a.a.x);
int num2 = (a.b.x - a.a.x)*(b.b.y-a.a.y) - (a.b.y - a.a.y)*(b.b.x - a.a.x);
if (num1/abs(num1)*num2 <= 0) //这里不能用乘法计算,因为可能出现溢出(难查的bug)
return true;
return false;
}
bool GraphyCut::isRemain(Line &line)
{
int code1 = getCode(line.a);
int code2 = getCode(line.b);
if (code1 == 0 && code2 == 0) //在中间,保留
return true;
else if (code1&code2) //边界外,舍去
return false;
else if (!(isLinesAcross(line, Line(st, endd)) || isLinesAcross(line, Line(Point(st.x, endd.y), Point(endd.x, st.y)))))
{
//进行跨立试验,如果不通过则表示在框外
return false;
}
else
{
if (fabs(line.a.x - line.b.x) <= 2)
{
if (line.a.y > max(st.y, endd.y))
line.a.y = max(st.y, endd.y);
else if (line.a.y < min(st.y, endd.y))
line.a.y = min(st.y, endd.y);
if (line.b.y > max(st.y, endd.y))
line.b.y = max(st.y, endd.y);
else if (line.b.y < min(st.y, endd.y))
line.b.y = min(st.y, endd.y);
return true;
}
do
{
if (code1 == 0 && code2 == 0)
break;
int code = code1 == 0 ? code2 : code1;
double x, y;
if (code&1)
{
y = line.a.y + (line.b.y - line.a.y)*(min(st.x,endd.x) - line.a.x) / (line.b.x - line.a.x);
x = (double)min(st.x,endd.x);
}
else if (code&2)
{
y = line.a.y + (line.b.y - line.a.y)*(max(st.x,endd.x) - line.a.x) / (line.b.x - line.a.x);
x = (double)max(st.x,endd.x);
}
else if (code&4)
{
x = line.a.x + (line.b.x - line.a.x)*(min(st.y,endd.y) - line.a.y) / (line.b.y - line.a.y);
y = (double)min(st.y,endd.y);
}
else if (code&8){
x = line.a.x + (line.b.x - line.a.x)*(max(st.y,endd.y) - line.a.y) / (line.b.y - line.a.y);
y = (double)max(st.y,endd.y);
}
if (code == code1)
{
line.a.x = x;
line.a.y = y;
code1 = getCode(line.a);
}
else
{
line.b.x = x;
line.b.y = y;
code2 = getCode(line.b);
}
} while (true);
return true;
}
}
void GraphyCut::CutLines()
{
for (int i = 0; i < lines.size(); i++)
{
if (!isRemain(lines[i]))
{
lines.erase(lines.begin() + i);
i--;
}
}
}