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;
	}




 本文章只供参考,希望不要用在商业性质上。



你可能感兴趣的:(DXF文件中将多段线凸度转换成圆弧)