根据起点、终点、半径、优弧、劣弧、顺时针和逆时针等要求,线性方程解圆心(C语言)

根据起点、终点、半径、优弧、劣弧、顺时针和逆时针等要求,线性方程解圆心(C语言)。


在求解过程当中,可能会求得两个圆心(一元二次方程解),这时候就需要判断是那个圆心,按照条件,总共也就以下4种情况:

在这里插入图片描述

话不多说,直接列代码

判断半径法求圆心参数的正确性:

/*
* 函数功能:判断半径法求圆心参数的正确性
* 函数类型:立即函数,调用后立即生效。
* 函数形参:
*	double x1:圆弧当中的一点,通常为起点位置的X坐标
*	double y1:圆弧当中的一点,通常为起点位置的Y坐标
*	double x2:圆弧当中的一点,通常为终点位置的X坐标
*   double y2:圆弧当中的一点,通常为终点位置的Y坐标
*   double dRadius:圆弧半径
* 返 回 值:
*  false:参数有问题
*   true:参数没有问题
* 其他:
*   1.
*   2.
*   3.
*/
bool Data_Validation(double x1, double y1, double x2, double y2, double dRadius)
{
    /* 1:变量定义 */
    double  dDistance = 0.0;				//两点间距离

    /* 2:变量赋值 */
    dDistance = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));

    /* 3:结果判断 */
    if (dDistance == 0.0)                   //距离为0
    {
        return  false;                      //参数有问题:输入了相同的点
    }
    if ((2 * dRadius) >= dDistance)         //判断两点间距离小于直径
    {
        return  true;
    }
    else
    {
        return  false;                      //参数有问题:两点间距离大于直径
    }
}

通过直线上一点和斜率,求得容易X下对应的Y的坐标值:

/*
* 函数功能:通过直线上一点和斜率,求得容易X下对应的Y的坐标值。
* 函数类型:立即函数,调用后立即生效。
* 函数形参:
*	double x:直线上的一点的X坐标(圆弧两点的中点坐标)
*	double y:直线上的一点的Y坐标(圆弧两点的中点坐标)
*	double k:直线斜率(垂直于圆弧上两点的直线斜率)
*	double x0:直线上的一点的X坐标(圆心的X坐标)
* 返 回 值:
* 其他:
*   1.
*   2.
*   3.
*/
double Y_Coordinates(double x, double y, double k, double x0)
{
    return k * x0 - k * x + y;
}

半径法通过线性方程求得圆心,并根据劣弧和优弧、顺时针和逆时针的要求返回正确圆心:

/*
* 函数功能:半径法通过线性方程求得圆心,并根据劣弧和优弧、顺时针和逆时针的要求返回正确圆心
* 函数类型:立即函数,调用后立即生效。
* 函数形参:
*	float   x1:圆弧当中的一点,通常为起点位置的X坐标
*   float   y1:圆弧当中的一点,通常为起点位置的Y坐标
*	float   x2:圆弧当中的一点,通常为终点位置的X坐标
*   float   y2:圆弧当中的一点,通常为终点位置的Y坐标
*   double  dRadius:圆弧半径(正数为劣弧,负数为优弧)
*   short   circleDir:0:顺时针圆弧。1:逆时针圆弧。
*	float*  center_x:满足条件的圆心的X坐标
*   float*  center_y:满足条件的圆心的Y坐标
* 返 回 值:
* 其他:
*   1.本函数暂时没有对参数进行判断,比如 circleDir 可能不是0或者1(本工程在上层调用函数进行了判断。)
*   2.也可以通过勾股定理求解
*   3.
*/
void Circle_Center(float x1, float y1, float x2, float y2, double dRadius, short circleDir, float* center_x, float* center_y)
{
    /* 1:变量定义 */
    double  k = 0.0, k_verticle = 0.0;      //圆弧上两点(起点和终点)线段的斜率 和 垂直于线段的斜率(圆心所在直线的斜率)
    double  mid_x = 0.0, mid_y = 0.0;       //圆弧上两点(起点和终点)线段的中心位置坐标
    double  a = 1.0;                        //一元二次方程二次项系数(求解圆心坐标的一元二次方程)
    double  b = 1.0;                        //一元二次方程一次项系数(求解圆心坐标的一元二次方程)
    double  c = 1.0;                        //一元二次方程常数项系数(求解圆心坐标的一元二次方程)
    double center_x1, center_y1, center_x2, center_y2;

    if (y2 == y1)                           //斜率为零,说明圆弧上两点(起点和终点)在同一水平线上面,
    {
        center_x1 = ((double)x1 + x2) / 2.0;	    //圆心x坐标为X之间中点
        center_x2 = ((double)x1 + x2) / 2.0;	    //圆心x坐标为X之间中点
        center_y1 = y1 + sqrt(dRadius * dRadius - ((double)x1 - x2) * ((double)x1 - x2) / 4.0);	//圆心y坐标
        center_y2 = y2 - sqrt(dRadius * dRadius - ((double)x1 - x2) * ((double)x1 - x2) / 4.0);	//圆心y坐标
    }
    else if (x2 == x1)                      //斜率无穷大,说明圆弧上两点(起点和终点)在同一垂直线上面,
    {
        center_x1 = x1 + sqrt(dRadius * dRadius - ((double)y1 - y2) * ((double)y1 - y2) / 4.0);	//圆心x坐标
        center_x2 = x2 - sqrt(dRadius * dRadius - ((double)y1 - y2) * ((double)y1 - y2) / 4.0);	//圆心x坐标
        center_y1 = ((double)y1 + y2) / 2.0;	    //圆心y坐标为Y之间中点
        center_y2 = ((double)y1 + y2) / 2.0;	    //圆心y坐标为Y之间中点
    }
    else
    {
        k = (y2 - y1) / (x2 - x1);          //圆弧上两点(起点和终点)线段斜率
        k_verticle = -1.0 / k;              //垂直于线段的斜率(圆心所在直线的斜率)
        mid_x = ((double)x1 + x2) / 2.0;    //线段中心坐标X
        mid_y = ((double)y1 + y2) / 2.0;    //线段中心坐标Y
        a = 1.0 + k_verticle * k_verticle;  //一元二次方程二次项系数(求解圆心坐标的一元二次方程)
        b = -2 * mid_x - k_verticle * k_verticle * ((double)x1 + x2);   //一元二次方程一次项系数(求解圆心坐标的一元二次方程)
        c = mid_x * mid_x + k_verticle * k_verticle * ((double)x1 + x2) * ((double)x1 + x2) / 4.0 -
            (dRadius * dRadius - ((mid_x - x1) * (mid_x - x1) + (mid_y - y1) * (mid_y - y1)));  //一元二次方程常数项系数(求解圆心坐标的一元二次方程)

        center_x1 = (-1.0 * b + sqrt(b * b - 4 * a * c)) / (2 * a);		//求得坐标x(右上角)
        center_x2 = (-1.0 * b - sqrt(b * b - 4 * a * c)) / (2 * a);		//求得坐标x(左下角)
        center_y1 = Y_Coordinates(mid_x, mid_y, k_verticle, center_x1);	//求得坐标y(右上角)
        center_y2 = Y_Coordinates(mid_x, mid_y, k_verticle, center_x2);	//求得坐标y(左下角)
    }

    //可以看出圆心坐标O1:(center_x1,center_y1)一定在圆心坐标O2:(center_x2,center_y2)右侧。
    //返回圆心O1:如果起点在终点上面:顺时针为大圆弧,逆时针为小圆弧。如果起点在终点下面:顺时针为小圆弧,逆时针为大圆弧。
    if (((y1 >= y2) && (((circleDir == 0) && (dRadius < 0)) || ((circleDir == 1) && (dRadius > 0)))) ||
        ((y1 < y2) && (((circleDir == 0) && (dRadius > 0)) || ((circleDir == 1) && (dRadius < 0)))))
    {
        *center_x = center_x1;      //(右上角)
        *center_y = center_y1;      //(右上角)
    }
    //返回圆心O2:如果起点在终点上面:顺时针为小圆弧,逆时针为大圆弧。如果起点在终点下面:顺时针为大圆弧,逆时针为小圆弧。
    else if(((y1 >= y2) && (((circleDir == 0) && (dRadius > 0)) || ((circleDir == 1) && (dRadius < 0)))) ||
        ((y1 < y2) && (((circleDir == 0) && (dRadius < 0)) || ((circleDir == 1) && (dRadius > 0)))))
    {
        *center_x = center_x2;      //(左下角)
        *center_y = center_y2;      //(左下角)
    }
    else
    {
        //如果 circleDir 可能不是0或者1,应该 return 返回?
    }
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值