判断线段与圆是否相交
一、知识点
1、判断点是否在圆内的方法:设点到圆心的距离为d,圆的半径为r,那么有
d<r | 在圆内 |
d=r | 在圆上 |
d>r | 在圆外 |
(其中d可由两点距离公式求出)
2、已知两点p1(x1,y1)、p2(x2,y2),求直线p1p2的一般式方程Ax+By+C=0
先求出两点式直线方程,然后由两点式直线方程求出一般式方程
3.点到直线的距离公式
点(x,y)到直线Ax+By+C=0的距离公式为
4、余弦定理
二、判断线段与圆是否相交
情况一、两点都在圆内。不相交
情况二、一个点在圆内,一个点在圆外。相交
情况三、两个点都在圆外
设点p1和p2均在圆外,判断线段p1p2与圆是否相交的方法
1、求出直线p1p2的一般式方程
2、用距离公式判断圆心到直线p1p2的距离是否大于半径:距离大于半径,则不相交;距离小于等于半径,执行3
3、设圆心为o,使用余弦定理判断角op1p2和角op2p1是否都为锐角,都为锐角则相交,否则不相交。
注意:可用向量来实现余弦定理
三、C++实现
//点
struct Point{
double x,y;
Point(){}
Point(int x,int y):x(x),y(y){}
};
//圆
struct Circle{
double r,x,y;
Circle(){};
Circle(double r,double x,double y):r(r),x(x),y(y){}
};
//判断直线p1p2与圆c是否相交,相交返回true,否则返回false
bool judge(Point p1,Point p2,Circle c)
{
bool flag1=(p1.x-c.x)*(p1.x-c.x)+(p1.y-c.y)*(p1.y-c.y)<=c.r*c.r;
bool flag2=(p2.x-c.x)*(p2.x-c.x)+(p2.y-c.y)*(p2.y-c.y)<=c.r*c.r;
if(flag1&&flag2) //情况一、两点都在圆内 :一定不相交
return false;
else if(flag1||flag2) //情况二、一个点在圆内,一个点在圆外:一定相交
return true;
else //情况三、两个点都在圆外
{
double A,B,C,dist1,dist2,angle1,angle2;
//将直线p1p2化为一般式:Ax+By+C=0的形式。先化为两点式,然后由两点式得出一般式
A=p1.y-p2.y;
B=p2.x-p1.x;
C=p1.x*p2.y-p2.x*p1.y;
//使用距离公式判断圆心到直线ax+by+c=0的距离是否大于半径
dist1=A*c.x+B*c.y+C;
dist1*=dist1;
dist2=(A*A+B*B)*c.r*c.r;
if(dist1>dist2)//圆心到直线p1p2的距离大于半径,不相交
return false;
angle1=(c.x-p1.x)*(p2.x-p1.x)+(c.y-p1.y)*(p2.y-p1.y);
angle2=(c.x-p2.x)*(p1.x-p2.x)+(c.y-p2.y)*(p1.y-p2.y);
if(angle1>0&&angle2>0)//余弦为正,则是锐角,一定相交
return true;
else
return false;
}
}