关于DXF文件读取的小结---4

时间:2024-04-13 17:03:32

    上文对于DXF文件的基础图元做了详细的解释,我认为的小白级的描述。对上文的图元定义为基础图元,是因为这些都能直接套用数学公式,拿到DXF中的数据就能使用。并且在显示的时候只用调用基础的系统API就能实现。其他几种解析的图元,会需要一些小小的转换。

先说下多线段。

关于DXF文件读取的小结---4

这里有个特别的属性,凸度。这个是圆弧的一种描述方式。

设圆弧所包含的圆心角为A(弧度表示),则凸度=四分之一圆心角之正切值

凸度=sin(A/4)/cos(A/4)

凸度值的范围即sin(A/4)/cos(A/4)的取值范围,A=0~2*PI,0到正无穷,当A=360时,cos90=0,所以值无效

凸度的正负表明弧的方向。正表示逆时针,负值表示顺时针。0表示直线,1表示半圆。

没有凸度的多线段就是字面上的多线段,这时候表示一组连续线段的集合。如下实例

0
LWPOLYLINE
  5
26B
330
1F
100
AcDbEntity
  8                        //图元层信息
测试1

100
AcDbPolyline
 90
        6
 70
     0
 43
0.0
 10                        //多线段折点坐标 X
2325.515427482149
 20                        //多线段折点坐标 Y
1434.813515288826
 10                        //多线段折点坐标 X
2334.765848179141
 20                        //多线段折点坐标 Y
1440.911301575535
 10                        //多线段折点坐标 X
2346.051348490464
 20                        //多线段折点坐标 Y
1426.498357444138
 10                        //多线段折点坐标 X
2360.481998308269
 20                        //多线段折点坐标 Y
1439.617834296261
 10                        //多线段折点坐标 X
2375.65267854708
 20                        //多线段折点坐标 Y
1433.15048500898
 10                        //多线段折点坐标 X
2391.933412504283
 20                        //多线段折点坐标 Y

1439.433056018702

这些信息提取出来就能使用,和线类似。我这里要提的是带凸度属性的多线段。如下

0
LWPOLYLINE
  5
2DA
330
1F
100
AcDbEntity
  8                         //图元层信息
测试1

100
AcDbPolyline
 90
        4
 70
     0
 43
0.0
 10                     //多线段折点坐标 X
2405.776073407401
 20                    //多线段折点坐标 Y
1402.775628833996
 10                     //多线段折点坐标 X
2405.776073407401
 20                    //多线段折点坐标 Y
1434.639334246056
 42                    //多线段凸度

-1.018867149644012
 10                     //多线段折点坐标 X
2442.735853805221
 20                    //多线段折点坐标 Y
1434.639334246056

 10                     //多线段折点坐标 X
2442.735853805221
 20                    //多线段折点坐标 Y

1401.689366670287

在蓝色标记的就是凸度属性。

这表明在点(2405.776073407401,1434.639334246056)和点(2442.7358538052211434.639334246056)之间是一段圆弧,其凸度是(-1.018867149644012),这个凸度值表明,这段弧从点(2405.776073407401,1434.639334246056)开始,顺时针旋转到点(2442.7358538052211434.639334246056)结束。

这里就需要根据圆弧始末点和凸度,三个参数求解出圆弧的圆心、半径和始末角度。

具体的细节分析就算了,直接上转换代码了。代码好像是从网上下的一段,具体是哪里我也忘了关于DXF文件读取的小结---4,我做了一些简单的修改。如果哪个看到了可以把出处链接贴在回复区。

int Assist_LwP2DxfY_DXF(Coord2D c2dSur1,  Coord2D c2dSur2, Dxf_LeiYuan& DestY, double dCrown)
{
//当凸度dCrown不等于0时,表示为圆弧
if (0.0 != dCrown)
{
////角度,包角
double theta_degree = 4*atan(fabs(dCrown));

double dStarX = 0.0, dStarY = 0.0;//圆弧起始点
double dEndX = 0.0, dEndY = 0.0;//圆弧终止点
//起始点,终止点
dStarX = c2dSur1.X;
dStarY = c2dSur1.Y;
dEndX  = c2dSur2.X;
dEndY  = c2dSur2.Y;


//弦长
double dLength = sqrt(pow(dStarX-dEndX,2) + pow(dStarY-dEndY,2));
//圆弧半径
double dfR = fabs(0.5*dLength/sin(0.5*theta_degree));


//弦的斜率
double dCenterX=0,dCenterY=0;//圆心坐标
double dCenterX1=0,dCenterY1=0;//圆心坐标1
double dCenterX2=0,dCenterY2=0;//圆心坐标2
double 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
{
double mid_x = 0.0,mid_y = 0.0;//弦的中点坐标
double a = 1.0;
double b = 1.0;
double c = 1.0;
double k_verticle = 0.0;//弦的中垂线的斜率


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°
bool isMinorArc = TRUE;//圆弧半径是否为较小的
if (fabs(dCrown) <= 1)
isMinorArc = TRUE;
else
isMinorArc = FALSE;

//确定圆弧的顺逆
int direction = 0;//判断是G02顺还是G03逆
if (0.0 > dCrown)
direction = 2; //
else

direction = 3; //


//确定圆心
//弦向量X正方向的角度
double angleChordX=acos((1*(dEndX-dStarX)+0*(dEndY-dStarY))/dLength)*180/PI_pgy;
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;
}
}
}

//起始角度、终止角度
double dStarC=0,dEndC=0; //圆弧起始角度,终止角度

double num1,num2; //x方向矢量和圆心到弧线起点和终点的矢量的叉乘的z 


//起始角的cos(dStarC)值
double 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_pgy-dStarC; 

//终止角的cos(dEndC)值
double 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_pgy-dEndC; 

//保存 圆弧
DestY.X = dCenterX;
DestY.Y = dCenterY;
if (direction==2)
{
DestY.dEAngl = dStarC/PI_pgy*180.0;
DestY.dSAngl = dEndC/PI_pgy*180.0;
}
else
{
DestY.dSAngl = dStarC/PI_pgy*180.0;
DestY.dEAngl = dEndC/PI_pgy*180.0;
}
DestY.l1dlar = dfR;
DestY.l1dsar = dfR;

DestY.dSweepA = 0.0;
}
return 0;

}

下章再说椭圆。

相关文章