题目:给定两条线段,判断这两条线段是否相交,线段AB的表示形式是A(x1,y1)B(x2,y2),线段CD的表示形式为C(x3,y3)D(x4,y4)。那么我们如何判断线段AB与线段CD是否相交。
解析:在介绍如何解决线段相交问题之前,我们先介绍向量的叉积。如下图所示:
下面的图(1)表示p1向量在p2向量的顺时针方向,图(2)表示p1向量在p2向量逆时针方向,图(3)表示p1向量与p2向量共线,我们只画出了同向共线的情况,反向共线的情况同理可得。
![](https://img-blog.csdn.net/20160528110908073?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20160528110915675?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
有了上面的叉积运算,很容易判断两条线段是否相交,比如说我们要判断线段p1p2与线段p3p4是否相交。(1)计算p1p3向量与p1p2向量的叉积值。(2)计算p1p4向量与p1p2向量的叉积值。(3)判断这两个叉积值是否为异号。(4)计算p3p1向量与p3p4向量的叉积值。(5)计算p3p2向量与p3p4向量的叉积值。(6)判断这两个叉积值是否为异号。(7)如果这两对叉积值都为异号,则说明两条线段相交,否则则不想交。如下图所示:
![](https://img-blog.csdn.net/20160528110932910?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
有一种特殊情况:比如说下图中的左图中线段p1p2与线段p3p4相交。向量p1p3与向量p1p2的叉积值为零。右图中线段p1p2与线段p3p4不相交。但是向量p1p3与向量p1p2的叉积值也为零。那么我们如何处理这种情况:我们只需要判断p3点在p1点与p2点之间即可,也就是说x1<=x3<=x2且y1<=y3<=y2。
#include<iostream>
#include<vector>
using namespace std;
struct Point
{
int x;
int y;
Point(int myX, int myY) :x(myX), y(myY)
{}
Point(){}
};
bool isIntersect(vector<Point> &line1, vector<Point> &line2)
{
int x1 = line1[0].x;
int y1 = line1[0].y;
int x2 = line1[1].x;
int y2 = line1[1].y;
int x3 = line2[0].x;
int y3 = line2[0].y;
int x4 = line2[1].x;
int y4 = line2[1].y;
int num1 = (x4 - x1)*(y2 - y1) - (y4 - y1)*(x2 - x1);
int num2 = (x3 - x1)*(y2 - y1) - (y3 - y1)*(x2 - x1);
int num3 = (x1 - x3)*(y4 - y3) - (y1 - y3)*(x4 - x3);
int num4 = (x2 - x3)*(y4 - y3) - (y2 - y3)*(x4 - x3);
if (num1*num2 < 0 && num3*num4 < 0)
{
return true;
}
if (num1 == 0)
{
if ((x4 > x1 && x4 > x2) || (x4 < x1 && x4 < x2))
{
return false;
}
}
if (num2 == 0)
{
if ((x3 > x1 && x3 > x2) || (x3 < x1 && x3 < x2))
{
return false;
}
}
if (num3 == 0)
{
if ((x2 > x3 && x2 > x4) || (x2 < x3 && x2 < x4))
{
return false;
}
}
if (num4 == 0)
{
if ((x1 > x3 && x1 > x4) || (x1 < x3 && x1 < x4))
{
return false;
}
}
return true;
}
int main(void)
{
system("pause");
return 0;
}