DXF檔案中將多段線凸度轉換成圓弧
阿新 • • 發佈:2019-01-22
在數控系統中,我們常常會將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; }
本文章只供參考,希望不要用在商業性質上。