DXF文件中将多段线凸度转换成圆弧

在数控系统中,我们常常会将DXF文件转换成G代码,主要涉及到 直线、多段线、圆、圆弧、椭圆、样条曲线、点,七大类,在转换成G代码过程中,其中样条曲线和多段线中凸度问题是比较复杂一些,而样条曲线的转换网上有很多源代码,而处理凸度问题的源代码似乎少很多。最近刚好我也在解析DXF文件,遇到了处理凸度的问题。我花了两天时间集中完成这个难题。通过大量的测试代码基本没有什么问题,凸度问题完美解决了。(其中主要的方法是运用了数学推导出来的方程计算的)

 double dConvexityDegree=0; //凸度
    long nSumLines = dxf_code.size();
    double theta_arc;
    double theta_degree ;//角度,包角
    double dAngle;//起点到终点的弦向量与X正方向之间的倾斜角
    double dStarX=0,dStarY=0;//圆弧起始点
    double dEndX=0,dEndY=0;     //圆弧终止点
    double dStarC=0,dEndC=0; //圆弧起始角度,终止角度
    double dmiddleX=0,dmiddleY=0;//起始点和终止点连接线的中点横纵坐标
    double dCenterX=0,dCenterY=0;//圆心坐标
    double dCenterX1=0,dCenterY1=0;//圆心坐标1
    double dCenterX2=0,dCenterY2=0;//圆心坐标2
    double dLength; //弦长
    double dfR;  //半径
    double dH;    //圆心到弦的距离
    //double k; //起始点和终止点连线的中垂线斜率
    double dAmass; //弦向量与X轴正向单位向量的叉积
    double dDirectionAngel;//弦中点到圆心的直线向量的方向角(0-2PI之间)
    double dD; //圆心到弦长的距离
    double dNslope;弦的斜率
    double dK;     //弦中垂线的斜率
    double dNAngel;//中垂线的倾斜角
    double dX,dY;        //圆心相对于弦中心点的坐标偏移量
    double num1,num2;    //x方向矢量和圆心到弧线起点和终点的矢量的叉乘的z 
 
 
    double k = 0.0;//弦的斜率
    double 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 angleChordX=0;//弦向量X正方向的角度
    int direction=0;//判断是G02还是G03
    bool isMinorArc=TRUE;//圆弧半径是否为较小的
    double dStartVale=0; //起始角的cos(dStarC)值
    double dEndVale=0; //终止角的cos(dEndC)值

      dConvexityDegree=code.r1;
    //当凸度dConvexityDegree不等于0时,表示为圆弧
    if (0!=dConvexityDegree)
    {
        theta_degree = 4*atan(fabs(dConvexityDegree));
                
        //起始点,终止点
        dStarX = code.x1;
        dStarY = code.y1;
        dEndX  = code.x2;
        dEndY  = code.y2;
 
        //弦长
        dLength = sqrt(pow(dStarX-dEndX,2)+pow(dStarY-dEndY,2));
        //圆弧半径
        dfR = fabs(0.5*dLength/sin(0.5*theta_degree));
 
        k = (dEndY - dStarY) / (dEndX - dStarX);
        if(k == 0)
        {
            dCenterX1 = (dStarX + dEndX) / 2.0;
            dCenterX2 = (dStarX + dEndX) / 2.0;
            dCenterY1 = dStarY + sqrt(dfR * dfR -(dStarX - dEndX) * (dStarX - dEndX) / 4.0);
            dCenterY2 = dEndY - sqrt(dfR * dfR -(dStarX - dEndX) * (dStarX - dEndX) / 4.0);
        }
        else
        {
            k_verticle = -1.0 / k;
            mid_x = (dStarX + dEndX) / 2.0;
            mid_y = (dStarY + dEndY) / 2.0;
            a = 1.0 + k_verticle * k_verticle;
            b = -2 * mid_x - k_verticle * k_verticle * (dStarX + dEndX);
            c = mid_x * mid_x + k_verticle * k_verticle * (dStarX + dEndX) * (dStarX + dEndX) / 4.0 - 
            (dfR * dfR - ((mid_x - dStarX) * (mid_x - dStarX) + (mid_y - dStarY) * (mid_y - dStarY)));
 
            dCenterX1 = (-1.0 * b + sqrt(b * b -4 * a * c)) / (2 * a);
            dCenterX2 = (-1.0 * b - sqrt(b * b -4 * a * c)) / (2 * a);
            dCenterY1 = k_verticle*dCenterX1 -k_verticle*mid_x+mid_y;
            dCenterY2 = k_verticle*dCenterX2 -k_verticle*mid_x+mid_y;
        }
 
 
        //凸度绝对值小于1表示圆弧包角小于180°,凸度绝对值大于1表示圆弧包角大于180°
        if (fabs(dConvexityDegree)<=1)
            isMinorArc=TRUE;
        else
            isMinorArc=FALSE;
 
 
        //确定圆弧的顺逆
        if (0>dConvexityDegree)
            direction=2;
        else
            direction=3;
 
        //确定圆心
        angleChordX=acos((1*(dEndX-dStarX)+0*(dEndY-dStarY))/dLength)*180/PI;    
        if ((dEndY-dStarY)<0)
        {
            angleChordX*=-1;
        }
        if ((angleChordX>0 && angleChordX<180)||angleChordX==180)
        {
            if (direction==2)//顺圆
            {
                if(isMinorArc)
                {
                    dCenterX=dCenterX1;
                    dCenterY=dCenterY1;
                }
                else
                {
                    dCenterX=dCenterX2;
                    dCenterY=dCenterY2;
                }
            }
            else if (direction==3)//逆圆
            {
                if (isMinorArc)
                {
                    dCenterX=dCenterX2;
                    dCenterY=dCenterY2;
                }
                else
                {
                    dCenterX=dCenterX1;
                    dCenterY=dCenterY1;
                }
            }
        }
                
        else 
        {
            if (direction==2)//顺圆
            {
                if(isMinorArc)
                {
                    dCenterX=dCenterX2;
                    dCenterY=dCenterY2;
                }
                else
                {
                    dCenterX=dCenterX1;
                    dCenterY=dCenterY1;
                }
            }
            else if (direction==3)//逆圆
            {
                if (isMinorArc)
                {
                    dCenterX=dCenterX1;
                    dCenterY=dCenterY1;
                }
                else
                {
                    dCenterX=dCenterX2;
                    dCenterY=dCenterY2;
                }
            }
        }
 
 
        //起始角度、终止角度
        dStartVale=(dStarX-dCenterX)/dfR;
        //在C++中,浮点型中的结果1可能是1.00000000000000001,避免这种情况出现。
        if (dStartVale>1)
            dStartVale=1;
        if (dStartVale<-1)
            dStartVale=-1;
        dStarC = acos(dStartVale);  
        //x方向矢量和圆心到弧线起点和终点的矢量的叉乘的z 
        num1=dStarY-dCenterY;  
        if(num1<0)  
            dStarC=2*PI-dStarC; 
 
        //终止角度、终止角度
        dEndVale=(dEndX-dCenterX)/dfR;
        //在C++中,浮点型中的结果1可能是1.00000000000000001,避免这种情况出现。
        if (dEndVale>1)
            dEndVale=1;
        if (dEndVale<-1)
            dEndVale=-1;
        dEndC = acos(dEndVale);  
        //x方向矢量和圆心到弧线起点和终点的矢量的叉乘的z 
        num2=dEndY-dCenterY;  
        if(num2<0)  
            dEndC=2*PI-dEndC; 
 
        //将DXF_LWPOLYLINE转换成ARC
 
        code.mStyle=DXF_ARC;
        //如果凸度小于0则为顺时针,clockwise为true
        if (0>dConvexityDegree)
            code.bWise=TRUE;
        else
            code.bWise=FALSE;
 
        code.x1 = dCenterX;
        code.y1 = dCenterY;
        code.x2 = dStarC;
        code.y2 = dEndC;
        code.r1 = dfR;
    }

————————————————
版权声明:本文为CSDN博主「死神在世」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/eickandy/article/details/48317855

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值