这个专题讨论用解析几何的方法解决线段,直线和点的计算问题。
默认使用笛卡尔直角坐标系。
计算点到线段的最近点。
已知线段P1P2((x1,y1),(x2,y2)),点Q(x0,y0),求点Q到线段P1P2的 最近坐标。
存在两种情况:
1.情况一:y1=y2&&x1!=x2时,直线P1P2的方程为y=y1,则Q到P1P2的垂线方程为x=x0,垂足坐标为(x0,y1)。
直线AB,下面是Q的三种不同的位置。最近的点的坐标很明显分别对应的三个红色的点。
同理x1=x2时:
直线AB,左右时Q的三种不同的位置。最近点的坐标对应的三个红点。
2.情况二:当y1=y2&&x1=x2时,该线段不平行于x轴&&不平行于y轴,斜率存在但不为0,则可设线段的两端点分别为P1,P2,斜率k=(y2-y1)/(x2-x1)。
该直线方程为:y=k(x-x1)+y1;
垂线方程为y=(-1/k)(x-x0)+y0;连立公式,解得x=(x1*k^2+k(y0-y1)+x0)/(1+k^2);y=k(x-x1)+y1;
同理可以求出点到折线,矩形,多边形的最近点。
计算点到圆的最近距离及最近点的坐标。
已知圆心坐标O=(xr,yr)及半径r,点P=(x0,y0),求点P到最近点的坐标分为以下几种情况:
1. P=A,则点到圆的最近距离为r,点位圆上任意一点的坐标。
2. P=C||P=C',y轴相等,则为:(xr+r,yr) || (x-r,yr)。
3. P=D||P=D',x轴相等,则为:(xr,yr+r) || (xr,yr-r)。
4. P=G||P=G',没有什么关系,存在一个斜率不为0的直线,则斜率为:k=(y0-yr)/(x0-xr)。
直线AG的方程为:y=k(x-Gx)+Gy。圆的方程为:(x-Ax)^2+(y-Ay)^2=r^2;连立求出交点(注意有两个)即可。
计算两条共线的线段的交点。
对于两条共线的线段,位置关系有以下几种情况:
分别是,没交点,有一个,无穷,无穷。
计算线段与线段的交点。
虽然感觉不太实用,但是姑且还是写出来吧,向量大法好!
首先判断两线段是否相交,
一般情况:k1=(y2-y1)/(x2-x1),k2=(y4-y3)/(x4-x3);
直线方程分别是:L1:y=k1(x-x1)+y1 L2:y=k2(x-x3)+y3;
注意斜率为0及斜率不存在的特判。
计算线段||直线和圆的交点。
参考上文:”点到圆的最近距离“求解。
求圆和圆的交点
用三角函数求交点,精度更高哦。
Code:
int Dcmp(double x){if(fabs(x)<EPS) return 0;return x<0?-1:1;}
struct Point{
double x,y;
Point(double _x=0,double _y=0){
x=_x;y=_y;
}
friend Point operator - (Point a,Point b){return Point(a.x-b.x,a.y-b.y);}
friend double operator * (Point a,Point b){return a.x*b.x+a.y*b.y;}
friend double operator ^ (Point a,Point b){return a.x*b.y-a.y*b.x;}
friend int operator == (Point a,Point b){return Dcmp(a.x-b.x)==0&&Dcmp(a.y-b.y)==0;}
};
struct Cir{
Point cen;double r;
void InPut(){scanf("%lf%lf%lf",&cen.x,&cen.y,&r);}
Point Inter(double a){return Point(cen.x+cos(a)*r,cen.y+sin(a)*r);}
};
double Distance(Point a,Point b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
double Distance(Point a){return sqrt(a.x*a.x+a.y*a.y);}
double Ang(Point a){
return atan2(a.y,a.x);
}
int CirCir(Cir c1,Cir c2,Point &p1,Point &p2){
double d=Distance(c1.cen,c2.cen);
if(Dcmp(d)==0){
if(Dcmp(c1.r-c2.r)==0) return -1;
return 0;
}
if(Dcmp(c1.r+c2.r-d)<0) return 0;
if(Dcmp(fabs(c1.r-c2.r)-d)>0) return 0;
double a=Ang(c2.cen-c1.cen);
double da=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2.0*d*c1.r));
p1=c1.Inter(a-da);p2=c1.Inter(a+da);//所求得的两交点
if(p1==p2) return 1;
return 2;
}