两种方法:
方法一:
我们设一个圆的圆心坐标为 (x0,y0),半径为 r。那么这个圆的方程可以写为:
在这个圆上随便取三个点,设这三个点的坐标分别是 (x1,y1),(x2,y2),(x3,y3)。那么有:
公式(1)(2)相减,(1)(3)相减之后经过化简可以得到:
x0,y0有唯一解的条件是系数行列式不为 0:
简单变变型也就是:
这样写几何含义就很明显了,三点不能共线。
得出答案:
有了 x0 和 y0 的值后,带入(1) 式就可以得到r的值。至此,三点确定圆的问题就解决了。
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const double eps=1e-10;
struct point{
double x,y;
point(){}
point(double _x,double _y){x=_x;y=_y;}
};
point pt1,pt2,pt3;
double radius;
double hypot(double a,double b)
{
return sqrt(a*a+b*b);
}
point tcircle()
{
double x1=pt1.x,x2=pt2.x,x3=pt3.x;
double y1=pt1.y,y2=pt2.y,y3=pt3.y;
double a=x1-x2;
double b=y1-y2;
double c=x1-x3;
double d=y1-y3;
double e=((x1*x1-x2*x2)+(y1*y1-y2*y2))/2.0;
double f=((x1*x1-x3*x3)+(y1*y1-y3*y3))/2.0;
double det=b*c-a*d;
if(fabs(det)<eps){
radius=-1;
return point(0,0);
}
double x0=-(d*e-b*f)/det;
double y0=-(a*f-c*e)/det;
radius=hypot(x1-x0,y1-y0);
return point(x0,y0);
}
int main()
{
scanf("%lf%lf%lf%lf%lf%lf",&pt1.x,&pt1.y,&pt2.x,&pt2.y,&pt3.x,&pt3.y);
point ans=tcircle();
printf("%f %f %f\n",ans.x,ans.y,radius);
return 0;
}
第二种方法:最常用的方法:
了解向量旋转
x’=xcosθ-ysinθ
y’=xsinθ+ycosθ
附上代码:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const double eps=1e-10;
struct point{
double x,y;
point(){}
point(double _x,double _y){x=_x;y=_y;}
point operator * (double k){
return point(x*k,y*k);
}
point operator + (point p){
return point(x+p.x,y+p.y);
}
point operator - (point p){
return point(x-p.x,y-p.y);
}
};
point pt1,pt2,pt3,ans;
double radius;
double cross(point a,point b)
{
return a.x*b.y-a.y*b.x;
}
double hypot(double a,double b)
{
return sqrt(a*a+b*b);
}
point rotate(point a)
{
return point(-a.y,a.x);
}
point getmid(point a,point b)
{
return point((a.x+b.x)/2,(a.y+b.y)/2);
}
point circlein()
{
point v1=pt2-pt1,v2=pt1-pt3;
v1=rotate(v1),v2=rotate(v2);
point p1=getmid(pt1,pt2),p2=getmid(pt1,pt3);
point u=p1-p2;
double t=cross(v2,u)/cross(v1,v2);
ans=p1+v1*t;
double x1=pt1.x,y1=pt1.y;
radius=hypot(x1-ans.x,y1-ans.y);
}
int main()
{
scanf("%lf%lf%lf%lf%lf%lf",&pt1.x,&pt1.y,&pt2.x,&pt2.y,&pt3.x,&pt3.y);
circlein();
printf("%f %f %f\n",ans.x,ans.y,radius);
return 0;
}