上文对于DXF文件的基础图元做了详细的解释,我认为的小白级的描述。对上文的图元定义为基础图元,是因为这些都能直接套用数学公式,拿到DXF中的数据就能使用。并且在显示的时候只用调用基础的系统API就能实现。其他几种解析的图元,会需要一些小小的转换。
先说下多线段。
这里有个特别的属性,凸度。这个是圆弧的一种描述方式。
设圆弧所包含的圆心角为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.735853805221,1434.639334246056)之间是一段圆弧,其凸度是(-1.018867149644012),这个凸度值表明,这段弧从点(2405.776073407401,1434.639334246056)开始,顺时针旋转到点(2442.735853805221,1434.639334246056)结束。
这里就需要根据圆弧始末点和凸度,三个参数求解出圆弧的圆心、半径和始末角度。
具体的细节分析就算了,直接上转换代码了。代码好像是从网上下的一段,具体是哪里我也忘了,我做了一些简单的修改。如果哪个看到了可以把出处链接贴在回复区。
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
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;
}
下章再说椭圆。