C++练习:已知三点,求过这三点的圆

本文介绍了一种通过三个已知点来确定一个圆的方法,包括计算圆心坐标和半径的过程。文中详细解释了如何利用点和直线的数学概念来找到经过这三个点的圆的相关参数。

    在论坛里看到了这个问题,基本上都是平面几何里的问题。把点,线做成了结构。

  

// 3point.cpp : Defines the entry point for the console application.
//已知三点 求过这三点的圆心坐标和圆的半径
// xmxoxo 2006.11.8 at XiaMen

#include 
"stdafx.h"
#include 
"stdlib.h"
#include 
"math.h"
#include 
"stdio.h"
#include 
"iostream.h"

//常数
double const pai = 3.1415926535897932384626;

//坐标点结构
struct point
{
    
double x;    //横坐标
    double y;    //纵坐标
};

//直线方程结构
struct line
{
    
double k;    //斜率
    double b;    //截距
};

//判断两点是否相同
bool samep(point p1,point p2)
{
    
if ((p1.x==p2.x)&&(p1.y==p2.y))
    {
        
return 1;
    }
    
else
    {
        
return 0;
    }
}

//求两点距离
double dist(point p1,point p2)
{
    
double ret=0;
    ret
=sqrt((p1.x-p2.x)*(p1.x-p2.x)+ (p1.y-p2.y)*(p1.y-p2.y));
    
return ret;
}


/*
已知两点,求连线中点坐标
---------------------------------
两点(x1,y1),(x2,y2)的连线中点坐标
((x1+x2)/2,(y1+y2)/2)
*/
point midpoint(point p1, point p2)
{
    point ret;
    ret.x 
= (p1.x + p2.x )/2;
    ret.y 
= (p1.y + p2.y )/2;
    
return ret;
}

/*
已知两点,求连线方程
-------------------------------------
两点(x1,y1),(x2,y2)的连线方程表示成Y=ax+b
a=(y1-y2)/(x1-x2)

b= y2 - x2*a
或者
b= y1- x1*a
-------------------------------------

*/
line line2p(point p1,point p2)
{
    line ret;
    
if ((p1.x==p2.x) && (p1.y = p2.y))
    {
        ret.k 
= 0;
        ret.b 
= 0;
    }
    
else
    {
        ret.k 
= (p1.y - p2.y)/ (p1.x -p2.x);
        ret.b 
= p1.y - p1.x * ret.k ;
    }
    
return ret;
}


//判断两直线是否相交

bool iscross(line l1,line l2)
{
    
if (l1.k==l2.k)
    {
        
return 0;
    }
    
else
    {
        
return 1;
    }
}

/*
已知两直线,求交点坐标
两条直线

y1=ax+b
y2=cx+d
求交点
a<>c时有交点(不平行)
y1=y2时
=> ax+b=cx+d
=> x=(d-b)/(a-c)

x1=x2 时
y=(ad-cb)/(a-c)

交点坐标是( (d-b)/(a-c),(ad-cb)/(a-c))
*/
point crosspoint(line l1,line l2)
{
    point ret;
    
if (!iscross(l1,l2))
    {
        ret.x 
= 0;
        ret.y 
= 0;
    }
    
else
    {
        ret.x 
= (l2.b-l1.b ) / (l1.k - l2.k);
        ret.y 
= (l1.k*l2.b-l2.k*l1.b)/(l1.k-l2.k);
    }
    
return ret;
}

/*
求斜率为k的直线,转过n弧度后,且经过某一点的方程
*/
line linepoint(point p,
double k,double n) //过某点直线方程
{
    line ret;
    ret.k 
= tan(atan(k)+n);
    ret.b 
= p.y -  ret.k * p.x ;
    
return ret;
}

/*
-------------------------------------
直线Y=ax+b 与X轴夹角是
atan((-b)/a)
转90度只要加上90度(3.14/2)就可以了
---------------------------------
*/

point p1,p2,p3;
point m1,m2,m3;
line l1,l2,l3;
line lm1,lm2,lm3;
point circlep;
double circler,dis2,dis3;

int main(int argc, char* argv[])
{

    printf(
"几何问题图解 2006.11.8 Xmxoxo ");
    
while (1)
    {
        cout
<<" 请输入第1点坐标:";
        cin
>>p1.x>>p1.y;
        printf(
"请输入第2点坐标:");
        cin
>>p2.x>>p2.y;
        printf(
"请输入第3点坐标:");
        cin
>>p3.x>>p3.y;
        
        
if (samep(p1,p2))
        {
            printf(
"两点相同! ");
            
break;
        }
        
//cout<<setprecision(10)<<setiosflags(ios::showpos);

        cout
<<"第1点坐标是: ("<<p1.x <<"," <<p1.y <<") ";
        cout
<<"第2点坐标是: ("<<p2.x <<"," <<p2.y <<") ";
        cout
<<"第3点坐标是: ("<<p3.x <<"," <<p3.y <<") ";
        
        m1
=midpoint(p1,p2);
        m2
=midpoint(p2,p3);
        m3
=midpoint(p3,p1);

        cout
<<"p1,p2中点坐标是: ("<<m1.x <<"," <<m1.y <<") ";

        l1
=line2p(p1,p2);
        l2
=line2p(p2,p3);
        l3
=line2p(p3,p1);

        cout
<<"P1,P2连线方程是: Y=("<< (float) l1.k <<")X+(" << (float) l1.b <<") ";
        cout
<<"P2,P3连线方程是: Y=("<< (float) l2.k <<")X+(" << (float) l2.b <<") ";
        cout
<<"P3,P1连线方程是: Y=("<< (float) l3.k <<")X+(" << (float) l3.b <<") ";
        
        lm1
=linepoint(m1,l1.k,pai/2);
        lm2
=linepoint(m2,l2.k,pai/2);
        lm3
=linepoint(m3,l3.k,pai/2);

        cout
<<"P1,P2连线的垂线方程是: Y=(" << (float) lm1.k << ")X+("<< (float) lm1.b << ") ";
        cout
<<"P2,P3连线的垂线方程是: Y=(" << (float) lm2.k << ")X+("<< (float) lm2.b << ") ";
        cout
<<"P3,P1连线的垂线方程是: Y=(" << (float) lm3.k << ")X+("<< (float) lm3.b << ") ";
        
        circlep
=crosspoint(lm1,lm2);
        circler
=dist(circlep,p1);
        dis2
=dist(circlep,p2);
        dis3
=dist(circlep,p3);

        cout
<< "圆心坐标是: (" << circlep.x << "," << circlep.y << ") ";
        cout
<< "半径是: (" << circler << ") ";
        cout
<< "到另两点的距离是: (" << dis2 << "," << dis3 << ") ";
        
//break;
    }

    
return 0;
}

 运行情况如下:

几何问题图解 2006.11.8 Xmxoxo

请输入第1点坐标:158.25 352.25
请输入第2点坐标:15.88 36.58
请输入第3点坐标:78.06 105.43
第1点坐标是: (158.25,352.25)
第2点坐标是: (15.88,36.58)
第3点坐标是: (78.06,105.43)
p1,p2中点坐标是: (87.065,194.415)
P1,P2连线方程是: Y=(2.21725)X+(1.37006)
P2,P3连线方程是: Y=(1.10727)X+(18.9966)
P3,P1连线方程是: Y=(3.07794)X+(-134.834)
P1,P2连线的垂线方程是: Y=(-0.451009)X+(233.682)
P2,P3连线的垂线方程是: Y=(-0.903123)X+(113.425)
P3,P1连线的垂线方程是: Y=(-0.324893)X+(267.228)
圆心坐标是: (-265.989,353.646)
半径是: (424.242)
到另两点的距离是: (424.242,424.242)

这里只解出了三角形的外接圆,如果要得到内切圆,也很简单,只要计算经过任意两个顶点的角平分线,

再计算这两条角平分线的交点就可以了。另外还可以推算出三角形的面积,周长等,都只是公式的应用,写

成表达式就可以了。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值