最近项目中遇到一个问题。问题描述如下:给定一条AcDbLine,需要将其替换为AcDbPolyline。在网上搜索了一下,没有得到满意的答案。无奈只好自己艰苦探索一番,问题基本搞定,不禁赞叹CAD数据库的结构和Arx类库的精美与强大。现把自己的心得体会和一些疑问贴出来,望与高手交流和讨教。
AcDbLine 中端点的坐标是以AcGePoint3d保存的,而AcDbPolyline 成员函数AcGeVector3d对象elevationn,以n为新坐标系的Z轴,n是与直线的方向向量正交的,因此直线a是平行与新定义的坐标系的xy平面的,这样,直线a两个端点在新坐标系中的z轴分量就相同了,于是就可以把z轴分量分离出来用以标高表示。将WCS空间中的三维点转换到自定坐标系中就变成了二维点和一个标高了。这就是定义实体自定义坐标系的方法。上面的论述中还有一个问题,就是OCS中x轴和y轴如何确定呢?这就要用到CAD的任意轴算法了:设给定的向量为N,WCS中Y轴为Wy,表示成点坐标的方式为(0,1,0),Z轴为Wz,表示成点坐标的方式为(0,0,1);设OCS X轴为Ax,Y轴为Ay,N也可作Az。
则该算法可写做为:
If( abs(Nx) < 1/64) and ( abs(Ny) < 1/64 then
Ax = Wy x N
Else
Ax = Wz x N
上式首先检查向量N的x轴分量和y轴分量的绝对值是否小于1/64,也就是说如果N与Wz很接近的话就计算Wy与N的叉积,否则就计算Wz与N的叉积,这样就得到了新的x轴,将x轴单位化后,使用公式Ay = N x Wz,将Ay单位化后便得到新的y轴了。这样新的坐标系就计算出来了。
有了上面的知识后,再回到本文开头的问题。解决该问题的第一步就是要给AcDbPolyline建立一个坐标系,并得到WCS到OCS的变换矩阵A,给定直线端点的坐标经过变换矩阵A变换后得到的两个点的坐标z轴分量应该是相同的,将其z轴分量设置为AcDbPolyline的标高,将新坐标系OCS中的Z轴向量设置为AcDbPolyline的法向量,将变换后的两点舍去其z轴分量便得到两个二维点,然后将这两个二维点添加到AcDbPolyline中,这样,AcDbLine转化为AcDbPolyline的工作便完成。
因此,关键是要得到变换矩阵A,如何实现呢?下面我谈谈自己做的一个方法,该方法比较繁琐,而且有些问题没有搞清楚,在此希望能得到高手的求证,小弟在此不胜感激。
首先,可以得到AcDbLine的法向量和方向向量,这两个向量理论上因该是正交的,代码如下:AcGeVector3d normLine = pline->normal();
AcGeVector3d vectorDircetionLine = endPoint3d - startPoint3d;
double dRes = normLine.dotProduct(vectorDircetionLine);
也就是说变量dRes的值为0,但是实际上不是的,为什么呢?目前搞不明白!
所以在此我不得不手动计算AcDbLine的一个法向量,下面贴出这个过程的代码片段: