说矩形相交算法之前,先看下如何判断两条线段是否相交
如果有两条线段 [a, b],[c, d](a, b, c, d 为 X 轴坐标点),有下面两种不相交的情况:
1)b < c 时,线段 [a, b] 在 [c, d] 的左边不相交
2)d < a 时,线段 [a, b] 在 [c, d] 的右边不相交
把上面两种情况取反就是相交的情况。
相交的线段则可以表示为[min(a, c), min(b, d)](注意:min(b, d) 应大于 min(a, c),否则就是不相交了),即两条线段中起点大的和终点小的。
写成程序如果下所示(程序中用的结构体表示是起点和长度):
#define max(x, y) ((x) > (y) ? (x) : (y))
#define min(x, y) ((x) < (y) ? (x) : (y))
struct section
{
int start;
int length;
};
/* determine if the two input section intersect with each other */
static int section_intersect(struct section sec1, struct section sec2)
{
/*return !(sec1.start > sec2.start + sec2.length
|| sec2.start > sec1.start + sec1.length);*/
return sec1.start < sec2.start + sec2.length
&& sec2.start < sec1.start + sec1.length;
}
static void section_intersect_test()
{
struct section sec1 = {5, 5};
struct section sec2 = {7, 8};
struct section sec3 = {18, 3};
printf("sec1 ^ sec2 : %d\n", section_intersect(sec1, sec2));
printf("sec1 ^ sec3 : %d\n", section_intersect(sec1, sec3));
printf("sec2 ^ sec3 : %d\n", section_intersect(sec2, sec3));
}
/* return the intersection of the two input, if not intersect, return a emtpy section */
static struct section section_intersection(struct section sec1, struct section sec2)
{
struct section sec = {0, 0};
int start = max(sec1.start, sec2.start);
int end = min(sec1.start + sec1.length, sec2.start + sec2.length);
if (end >= start)
{
sec.start = start;
sec.length = end - start;
}
return sec;
}
static void print_section(const char *pcstr, struct section sec)
{
printf("%s {%d, %d}\n", pcstr, sec.start, sec.length);
}
static void section_intersection_test()
{
struct section sec1 = {5, 5};
struct section sec2 = {7, 8};
struct section sec3 = {18, 3};
print_section("sec1 ^ sec2 :", section_intersection(sec1, sec2));
print_section("sec1 ^ sec3 :", section_intersection(sec1, sec3));
print_section("sec2 ^ sec3 :", section_intersection(sec2, sec3));
}
static void test_driver()
{
section_intersect_test();
section_intersection_test();
}
说明:
section_intersect 判断两条线段是否相交,如果不相交返回 0。它里面的注释部分和没有注释的部分的意思等同。
section_intersect_test 是对 section_intersect 的简单测试。
section_intersection 返回两条线段相交的部分,如果不相交,返回一个空线段(起点为 0,长度为 0)。
section_intersection_test 是对 section_intersection 的简单测试。
判断矩形是否相交与之类似,因为矩形是由相互垂直的两条线段确定的。
代码如下:
struct rectangle
{
int x;
int y;
int width;
int height;
};
static int rectangle_intersect(struct rectangle rec1, struct rectangle rec2)
{
return rec1.x < rec2.x + rec2.width
&& rec2.x < rec1.x + rec1.width
&& rec1.y < rec2.y + rec2.height
&& rec2.y < rec1.y + rec1.height;
}
static struct rectangle rectangle_intersection(struct rectangle rec1, struct rectangle rec2)
{
struct rectangle rec = {0, 0, 0, 0};
int x1 = max(rec1.x, rec2.x);
int x2 = min(rec1.x + rec1.width, rec2.x + rec2.width);
int y1 = max(rec1.y, rec2.y);
int y2 = min(rec1.y + rec1.height, rec2.y + rec2.height);
if (x2 >= x1 && y2 >= y1)
{
rec.x = x1;
rec.y = y1;
rec.width = x2 - x1;
rec.height = y2 - y1;
}
return rec;
}
说明,以上的代码都没有经过严格的测试,只为了说明线段矩阵相交算法。