http://toumao.blog.sohu.com/13648650.html
有朋友在论坛上提问,如何判断两个矩形是否相交,他自己的初步想法是这样的:
1、一个矩形只有一个角的点在另一个矩形内;
2、一个矩形a只一条边上的2个顶角在另一个矩形b内(这种情况对于另一个矩形b来说却是4个顶角都在矩形a之外,所以要交换判断)。
3、一个矩形穿过另一个矩形;
这位朋友想了这么三种情形之后,觉得把这些情形写成代码过于复杂,这才跑到论坛上来提问。
首先说明,我本人比较喜欢思考,也喜欢陪喜欢思考的人一起思考。我好久没有在论坛上做什么了,因为一眼看去都是问作业的,一气之下关掉窗口生闷气了。呵呵。
其实,解决一个问题的方法可以有多种,不同的人应该从不同的方向去考虑。就拿这个“矩形相交”的问题来说,如果从纯几何上考虑,提问者的分析不错,但是从程序算上上看,却未必是好办法。因为这三种情形的细分是从眼睛看的角度出发的,不利于算法的实现。
有的时候,程序员考虑问题的方向就得跟别人不一样,换一个角度考虑,这个问题将变得简单:
如果两个矩形相交,则必然存在线条交叉,而能交叉的线条只有横线和竖线,两根横线或两根竖线都不可能交叉。所以,这个问题就转化成寻找是否存在交叉的横线与竖线。
另外,A线与B线交叉等价于B线与A线交叉,所以,只要写一个函数就足够用了,多调用几次,反正计算机是专门做简单而又烦琐的工作的。
下面是这个函数:判断一条横线和一条竖线是否交叉。该函数的参数分别是:横线左、横线右,横线Y,竖线上,竖线下,竖线X。
bool CrossLine(left, right, y, top, bottom, x)
{
//判断一根横线和一根竖线是否交叉
//横线有三个参数:left, right和y
//竖线有三个参数:top, bottom和x
return (top < y) && (bottom > y)
&& (left < x) && (right > x);
}
下面是判断两个矩形是否相交的函数,把同一个函数多调用几篇就OK了。
bool CrossRect(CRect &r1, CRect &r2)
{
//判断两个矩形是否相交,
//从一个矩形中取出一条横线,与另一矩形中的一条竖线判断是否交叉
return CrossLine(r1.x1, r1.x2, r1.y1, r2.y1, r2.y2, r2.x1)
|| CrossLine(r1.x1, r1.x2, r1.y1, r2.y1, r2.y2, r2.x2)
|| CrossLine(r1.x1, r1.x2, r1.y2, r2.y1, r2.y2, r2.x1)
|| CrossLine(r1.x1, r1.x2, r1.y2, r2.y1, r2.y2, r2.x2)
|| CrossLine(r2.x1, r2.x2, r2.y1, r1.y1, r1.y2, r1.x1)
|| CrossLine(r2.x1, r2.x2, r2.y1, r1.y1, r1.y2, r1.x2)
|| CrossLine(r2.x1, r2.x2, r2.y2, r1.y1, r1.y2, r1.x1)
|| CrossLine(r2.x1, r2.x2, r2.y2, r1.y1, r1.y2, r1.x2);
}
1、一个矩形只有一个角的点在另一个矩形内;
2、一个矩形a只一条边上的2个顶角在另一个矩形b内(这种情况对于另一个矩形b来说却是4个顶角都在矩形a之外,所以要交换判断)。
3、一个矩形穿过另一个矩形;
这位朋友想了这么三种情形之后,觉得把这些情形写成代码过于复杂,这才跑到论坛上来提问。
首先说明,我本人比较喜欢思考,也喜欢陪喜欢思考的人一起思考。我好久没有在论坛上做什么了,因为一眼看去都是问作业的,一气之下关掉窗口生闷气了。呵呵。
其实,解决一个问题的方法可以有多种,不同的人应该从不同的方向去考虑。就拿这个“矩形相交”的问题来说,如果从纯几何上考虑,提问者的分析不错,但是从程序算上上看,却未必是好办法。因为这三种情形的细分是从眼睛看的角度出发的,不利于算法的实现。
有的时候,程序员考虑问题的方向就得跟别人不一样,换一个角度考虑,这个问题将变得简单:
如果两个矩形相交,则必然存在线条交叉,而能交叉的线条只有横线和竖线,两根横线或两根竖线都不可能交叉。所以,这个问题就转化成寻找是否存在交叉的横线与竖线。
另外,A线与B线交叉等价于B线与A线交叉,所以,只要写一个函数就足够用了,多调用几次,反正计算机是专门做简单而又烦琐的工作的。
下面是这个函数:判断一条横线和一条竖线是否交叉。该函数的参数分别是:横线左、横线右,横线Y,竖线上,竖线下,竖线X。
bool CrossLine(left, right, y, top, bottom, x)
{
//判断一根横线和一根竖线是否交叉
//横线有三个参数:left, right和y
//竖线有三个参数:top, bottom和x
return (top < y) && (bottom > y)
&& (left < x) && (right > x);
}
下面是判断两个矩形是否相交的函数,把同一个函数多调用几篇就OK了。
bool CrossRect(CRect &r1, CRect &r2)
{
//判断两个矩形是否相交,
//从一个矩形中取出一条横线,与另一矩形中的一条竖线判断是否交叉
return CrossLine(r1.x1, r1.x2, r1.y1, r2.y1, r2.y2, r2.x1)
|| CrossLine(r1.x1, r1.x2, r1.y1, r2.y1, r2.y2, r2.x2)
|| CrossLine(r1.x1, r1.x2, r1.y2, r2.y1, r2.y2, r2.x1)
|| CrossLine(r1.x1, r1.x2, r1.y2, r2.y1, r2.y2, r2.x2)
|| CrossLine(r2.x1, r2.x2, r2.y1, r1.y1, r1.y2, r1.x1)
|| CrossLine(r2.x1, r2.x2, r2.y1, r1.y1, r1.y2, r1.x2)
|| CrossLine(r2.x1, r2.x2, r2.y2, r1.y1, r1.y2, r1.x1)
|| CrossLine(r2.x1, r2.x2, r2.y2, r1.y1, r1.y2, r1.x2);
}