通过圆弧凸度和两端点坐标计算出圆弧的中点坐标(C代码)

DXF文件的LWPOLYLINE类型记录的圆弧数据为凸度和两端点坐标,而实际应用中存储的圆弧多为三点圆弧,所以本文通过圆弧凸度和两端点坐标计算出圆弧中点坐标,从而可以用三点确定圆弧。

/*

*功能:xy圆弧的两个端点和凸度计算这段圆弧的中点坐标

*      1.计算出圆心坐标,半径

*      2.通过圆心与端点坐标分别计算出开始点的弧度和结束点的弧度

*      3.通过开始点和结束点弧度计算中点弧度      

*      4.中点弧度与圆心、半径计算圆弧中点坐标

*/

#include <stdio.h>
#include <math.h>
#ifndef PI
#define PI	3.1415926535898
#endif
typedef struct
{
    double x;
    double y;
    double z;
}COORD_T;

COORD_T calculateArcCenter(double startX, double startY, double endX, double endY, double bulge)
{
    COORD_T centerPoint = { 0 };
    double tangentRatio;

    if (bulge > 0.000000001 || bulge < -0.000000001)
    {
        tangentRatio = 0.5 * (1 / bulge - bulge);
        centerPoint.x = 0.5 * ((startX + endX) - tangentRatio * (endY - startY));
        centerPoint.y = 0.5 * ((startY + endY) + tangentRatio * (endX - startX));
        centerPoint.z = 0.0;  // 平面圆弧计算,z坐标设为0
    }
    return centerPoint;
}

/*
*功能:xy圆弧的两个端点和凸度计算这段圆弧的中点坐标
*	   1.计算出圆心坐标,半径
*	   2.通过圆心与端点坐标分别计算出开始点的弧度和结束点的弧度
*      3.通过开始点和结束点弧度计算中点弧度
*      4.中点弧度与圆心、半径计算圆弧中点坐标
*/
COORD_T calculateArcMidPoint(double startX, double startY, double endX, double endY, double bulge)
{
    COORD_T midPoint = { 0 }, centerPoint;
    double startAngle, endAngle, midAngle;//以圆心为原点(0,0),startAngle开始角度,endAngle结束点角度,midAngle圆弧中点角度
    double arcRadius, chordLength, includedAngle;

    const double EPSILON = 0.000000001;
    if (bulge > EPSILON || bulge < -EPSILON)
    {
        centerPoint = calculateArcCenter(startX, startY, endX, endY, bulge);

        startAngle = atan2((startY - centerPoint.y), (startX - centerPoint.x));//(-π,π];
        endAngle = atan2((endY - centerPoint.y), (endX - centerPoint.x));       //(-π,π];

        //计算顶点角度
        includedAngle = atan(bulge) * 4;   //弧度,atan(dBulge)*4 的范围是 (-π/2, π/2)*4;dBulge为0时dRadian为0 

        /*计算半径*/
        chordLength = sqrt((startX - endX) * (startX - endX) +
            (startY - endY) * (startY - endY));
        arcRadius = (chordLength / 2) / sin(includedAngle / 2);
        if (arcRadius < 0)
            arcRadius = -arcRadius;

        if (startAngle < 0)
            startAngle += 2 * PI;
        if (endAngle < 0)
            endAngle += 2 * PI;

        if (bulge < 0)
        {//点1到点2顺时针转
            if (startAngle < endAngle)
                startAngle += 2 * PI;
        }
        else 
        {//点1到点2逆时针转
            if (endAngle < startAngle)
            {
                //穿过第四、第一象限
                endAngle += 2 * PI;
            }
        }

        midAngle = (startAngle + endAngle) / 2;
        if (midAngle > PI)
            midAngle -= 2 * PI;

        midPoint.x = centerPoint.x + arcRadius * cos(midAngle);
        midPoint.y = centerPoint.y + arcRadius * sin(midAngle);
        midPoint.z = 0.0;  // 平面圆弧计算,z坐标设为0
    }
    else
    {
        midPoint.x = (startX + endX) / 2;
        midPoint.y = (startY + endY) / 2;
        midPoint.z = 0.0;
    }

    return midPoint;
}

int main()
{

    // 测试用例2:180度圆弧
    {
        double startX = -5.0, startY = 0.0;   // 起点 (-5,0)
        double endX = 5.0, endY = 0.0;        // 终点 (5,0)
        double bulge = 1.0;                    // bulge=1.0 表示180度圆弧
        
        COORD_T midPoint = calculateArcMidPoint(startX, startY, endX, endY, bulge);
        printf("Test Case 2 (180° Arc):\n");
        printf("Start Point: (%.3f, %.3f)\n", startX, startY);
        printf("End Point: (%.3f, %.3f)\n", endX, endY);
        printf("Bulge: %.3f\n", bulge);
        printf("Mid Point: (%.3f, %.3f, %.3f)\n\n", midPoint.x, midPoint.y, midPoint.z);
    }

    // 测试用例3:直线(bulge = 0)
    {
        double startX = 0.0, startY = 0.0;    // 起点 (0,0)
        double endX = 10.0, endY = 10.0;      // 终点 (10,10)
        double bulge = 0.0;                    // bulge=0 表示直线
        
        COORD_T midPoint = calculateArcMidPoint(startX, startY, endX, endY, bulge);
        printf("Test Case 3 (Straight Line):\n");
        printf("Start Point: (%.3f, %.3f)\n", startX, startY);
        printf("End Point: (%.3f, %.3f)\n", endX, endY);
        printf("Bulge: %.3f\n", bulge);
        printf("Mid Point: (%.3f, %.3f, %.3f)\n\n", midPoint.x, midPoint.y, midPoint.z);
    }

    // 测试用例4:负bulge值(顺时针圆弧)
    {
        double startX = 0.0, startY = 0.0;    // 起点 (0,0)
        double endX = 10.0, endY = 0.0;       // 终点 (10,0)
        double bulge = -1.0;                   // 负bulge表示顺时针方向
        
        COORD_T midPoint = calculateArcMidPoint(startX, startY, endX, endY, bulge);
        printf("Test Case 4 (Clockwise Arc):\n");
        printf("Start Point: (%.3f, %.3f)\n", startX, startY);
        printf("End Point: (%.3f, %.3f)\n", endX, endY);
        printf("Bulge: %.3f\n", bulge);
        printf("Mid Point: (%.3f, %.3f, %.3f)\n", midPoint.x, midPoint.y, midPoint.z);
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MotionHao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值