关于DXF文件读取的小结---5
这里就轮到椭圆了。实际上,在DXF中,椭圆和椭圆弧是同一套描述,只是在参数值不一样罢了。如下图红圈标识的。
这里可以看出来,椭圆就是闭合属性的。
通过椭圆的组码,可以看出来DXF文件对于椭圆的描述和椭圆的标准方程()是不一致。而是使用的参数方程
来个椭圆的实例:
0
ELLIPSE
5
27D
330
1F
100
AcDbEntity
8 //图元图层信息
测试1
100
AcDbEllipse
10 //椭圆中心坐标X
2331.726135418688
20 //椭圆中心坐标Y
1387.749676511899
30 //椭圆中心坐标Z
0.0
11 //椭圆长轴端点X
-11.66081242845666
21 //椭圆长轴端点Y
4.715658563840861
31 //椭圆长轴端点Z
0.0
210
0.0
220
0.0
230
1.0
40 //椭圆短轴与长轴的比例 //一般小于1.0
0.4573408781063685
41 //椭圆起始弧度
0.0
42 //椭圆结束弧度
6.283185307179585
在这里要解释下椭圆长轴端点坐标,这个值是相对于椭圆中心点的偏移。
求解椭圆长轴长度就是 len =fsqrt( pow(组码11,2)+pow(组码21,2))
求解椭圆的短轴就是len2 = len * (组码40)
在DXF文件中,椭圆长轴是可以在任意方向的。就是说,椭圆完全是可能,而且一定存在斜着的。在Windows系统提供的API中,椭圆只能是水平或者竖直的。在这里的解决方法就是:先按照水平求解椭圆方程,然后根据长轴端点坐标求解出旋转角度。
组码41,42表示的位置方向是弧度。这个需要注意下。
所以,综合之后,椭圆上的点求解公式就成为 x = c_x + (A*cos(θ)*cos(φ) - B*sin(θ)*sin(φ) ) y = c_y + ( A*sin(θ)*cos(φ) + B*cos(θ)*sin(φ) ) θ是椭圆旋转的角度,c_x ,c_y 表示椭圆中心点坐标。
要将任意角度旋转的椭圆绘画出来,决定将椭圆分解成连续多线段,在精度范围内分解椭圆。
下面就是分解椭圆的函数: int Assist_DxfY2PX_DXF(Dxf_LeiYuan& SurY, const double dRefLLen, CRD2D_V& PVDest)
{
if (!PVDest.empty())
PVDest.clear();
//类圆坐标点公式
//x = c_x + ( ilar*cos(Sweep)*cos(theta) - isar*sin(Sweep)*sin(theta) )
//y = c_y + ( ilar*sin(Sweep)*cos(theta) + isar*cos(Sweep)*sin(theta) )
//先转为多线段
if (SurY.l1dlar < dRefLLen*1.732)
return 1;
//分解类圆
double dcenX = SurY.X;
double dcenY = SurY.Y;
double dLAR = SurY.l1dlar;
double dSAR = SurY.l1dsar;
double dSweep = SurY.dSweepA;
double dagStart = SurY.dSAngl;
double dagEnd = SurY.dEAngl;
if(dagStart > dagEnd)
dagEnd += 360.0;
double dTheta = 2.0 * asin(dRefLLen/(dLAR+dSAR));
if(dTheta < 0)
dTheta += PI_pgy;
dTheta = dTheta * 180.0/PI_pgy;
dSweep = dSweep/180.0*PI_pgy;
long lLineN = double2int_add_pgy( (dagEnd-dagStart)/dTheta) + 1;
for(long lIndex = 0; lIndex < lLineN; ++lIndex)
{
double dTemA = 0.0;
Coord2D c2dPoint;
dTemA = dagStart+lIndex*dTheta;
if (dTemA > dagEnd)
dTemA = dagEnd;
dTemA = dTemA/180.0*PI_pgy;
c2dPoint.X = dcenX + ( dLAR*cos(dSweep)*cos(dTemA) - dSAR*sin(dSweep)*sin(dTemA) );
c2dPoint.Y = dcenY + ( dLAR*sin(dSweep)*cos(dTemA) + dSAR*cos(dSweep)*sin(dTemA) );
PVDest.push_back(c2dPoint);
}
return 0;
}
椭圆基本上就是这些了。
而对于椭圆弧,就是组码41,42的改变罢了,完全可以套用椭圆中的东西的。