1. 程式人生 > >判斷線段是否與圓相交模板

判斷線段是否與圓相交模板

判斷線段和圓是否相交

判斷圓和線段相交,分兩種情況:

 


1. 如圖A所示,當圓心與線段的距離大於圓的半徑時,線段與圓肯定不相交

2. 如圖B,C所示,兩個端點都不在圓內,那麼看圓心到線段所在直線的垂足是否小於半徑且垂足是否線上段上;我們可以利用餘弦定理,避免判斷垂足是否線上段上,只要圓心到兩端點的得角度都為銳角,那麼他們必然相交。

推導過程:

  • 線段所在直線方程的一般公式為:ax+by+c=0;線段兩端點A(x1,y1)B(x2,y2),圓心O(x0,y0).

此處補充直線方程的五種形式:

一般式為ax+by+c=0,它的優點就是它可以表示平面上的任意一條直線,僅此而已.

斜截式y=kx+b,就不能表示垂直x軸的直線x=a.點斜式y-y0=k(x-x0),

也不能表示垂直x軸的直線x=a兩點式(y-y1)/(y2-y1)=(x-x1)/(x2-x1).不能表示兩點x1=x2或y1=y2時的直線(即垂直或水平直線)截距式x/a+y/b=1不能表示截距為0時的直線,比如正比例直線.

  • 所以根據兩點式,可以求得a=y2-y1,b=x1-x2,c=x1y2-x2y1;
  • 在根據點到直線的距離公式:

再補充一下餘弦定理:


這樣的話,根據餘弦定理的向量求法,CosA=(x0-x1)(x2-x1)+(y0-y1)(y2-y1)  (省略了分母部分,因為分母是正數)

#include <iostream>

using namespace std;
typedef struct
{
  int x,int y;
}point;
point A,B,C,O;

int pan_duan(point *p1,point *p2,double r)
{
    double a,b,c,dist1,dist2,angle1,angle2;//ax+by+c=0;
    if(p1->x==p2->x)
        a=1,b=0,c=-p1->x;//特殊情況判斷,分母不能為零
    else if(p1->y==p2->y)
        a=0,b=1,c=-p1->y;//特殊情況判斷,分母不能為零
    else
    {
        a=p1->y-p2->y;
        b=p2->x-p1->x;
        c=p1->x*p2->y-p1->y*p2->x;
    }
    dist1=a*O.x+b*O.y+c;
    dist1*=dist1;
    dist2=(a*a+b*b)*r*r;
    if(dist1>dist2)return 0;//點到直線距離大於半徑
    angle1=(O.x-p1->x)*(p2->x-p1->x)+(O.y-p1->y)*(p2->y-p1->y);
    angle2=(O.x-p2->x)*(p1->x-p2->x)+(O.y-p2->y)*(p1->y-p2->y);
    if(angle1>0&&angle2>0)return 1;
    return 0;

}