- UID
- 124967
- 积分
- 180
- 精华
- 贡献
-
- 威望
-
- 活跃度
-
- D豆
-
- 在线时间
- 小时
- 注册时间
- 2004-4-14
- 最后登录
- 1970-1-1
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
前面看过mzm发表过关于Amodeler进行三维建模的一些看法,凭着对三维建模的兴趣,也去学习了一下AModeler这个类库,这个类库在ObjectArx2000和2002中都有,我目前是基于2002开发。
以下时我的一些经验,拿出来大家分享,希望大家能在这里讨论讨论,共同进步!
AModeler中的拓扑数据结构如下:Body,Face,Edge,Surface,分别对应着体,面,边,表面。体是用边界来确定的,也就是边界表示法(Boundary representation, B-rep)。使用改良的快速的边界数据结构,能构表示所有的体,表面,面,边和顶点(在AModeler类库中的topology.dwg中有它的拓扑结构说明)。
面都是平面造型的,它的法向矢量从体的内部指向外部。曲面是由很多紧密相连的小面组成的,每个小面都有一个指向它所属的曲面的指针,曲面可以是圆柱(cylindrical)、圆锥(conical)、球形(spherical)、圆环(toroidal)和没有指明的类型(undpecified)(能表示所有的其它我们不能又一个具体表达式表示的类型)。如果在对体进行操作时破坏了曲面的数据信息(例如:非标准的缩放),曲面也会变成没有指明的类型(unspecified)。实际的曲面方程式会丢失,但是曲面上各小面之间的关联信息和曲面的形状还是能表达出来。
体的每一个欧拉边(在我的理解中是体的边缘)最少由一对边来表示,因为体每个欧拉边都至少被两个面共享,更复杂的欧拉边可能需要更多的配对边来表示。
那些被两个相邻的面共享的边并且属于同一个曲面的叫Approximationg Edges(我不知道怎么翻译成中文^_^),被标记成 AEF(Approximating Edge Flag),并且只有当他们是体的侧面轮廓是才被显示出来。
每一个面都被一个正确的边组成的环包围起来。当从体的外面看的时侯,边是按逆时针方向来组织的。也就是说内部的面是在边的左侧。
在面(Faces)中的洞(Holes)是反平行着外面的边环,,叫桥边(Bridge Edges),这样的边被标记成 BEF(bridge Edge Flag)。
被在斜面上连续的两个面共享的边也被标记成BEF,桥边不会正常地被显示。
顶点是由 x, y , z 坐标来描述的。
以上是AModeler类库中对象拓扑结构,仅仅是我个人的理解,肯定还有不对的地方,大家可以去看(Body.h)头文件的英文说明,希望能把我理解不对的地方说出来,好让我不要走弯路。
下面说说我对AModeler建模的步骤的理解:
可以参照AModeler中的例子:
一、从AcDbEntity或者AcDbCurve里派生一个自定义实体,比如类名叫“MyBody”,用来描述你自己的实体类型。限于篇幅,具体派生规则我就不多说了。
二、在MyBody类里建一个body的成员对象m_3dGeo,所有的实体生成可都靠它了。
三、从SaveRestoreCallback类派生一个自己的类DwgFilerCallBack,用来输入输出数据,它是要被Body::save() 和 Body::restore()这两个函数调用的,必须派生,因为基类是抽象基类,没有实现任何功能。其函数的实现参照粒子写成如下就行了。
void
DwgFilerCallBack::saveBytes( const void* buffer, int requiredLength )
{
m_filer->writeBytes( buffer, requiredLength );
}
void
DwgFilerCallBack::restoreBytes( void* buffer, int requiredLength )
{
m_filer->readBytes( buffer, requiredLength );
}
四、从OutputTriangleCallback类派生一个自己的类MyOutputTraangleCallback,用来被Body::triangulate() 和 Face::triangluate()调用,实现其
void outputTriangle(Edge* edges[], int numSides);
void outputTriStrip(Edge* edgeArray[], int arrayLength,bool firstTriangleIsCcw);函数,这两个函数会被自动调用,当然也可以在这个类里加入其它函数,比如DrawAllEdges(const body& 3dGeo)(用来绘制自定义实体的所有边),DrawAllFaces(const body& 3dGeo)(用来绘制所有的面,能看到的才绘制)等等,看自己需要,具体实现也是看自己需要。自己加入的函数可以在MyBody类的viewPortDraw()和worldDraw()里使用,我觉得这样很好,
五、从OutputPolylineCallback类派生一个自己的类MyOutputPolyLineCallback,重载
virtual void outputPolyline(Edge* edgeArray [],
const Point3d pointArray[],
const double bulgeArray[],
int numPoints,
bool isClosed,
bool isVisible);
virtual void outputArc (Edge* edge,
const Point3d& center,
double radius,
double startAngle,
double endAngle,
bool isVisible)
函数,outputPolyline()能被Body::hideDisplay()调用,主要用来输出平面图形中轮廓。
有了以上几个派生类,就可以在MyBody中描述任意自己需要的体模型了,在viewPortDraw()
或这worldDraw()实现自己的描述,可以分级别,绘制体模型的平面造型、轮廓、面等等。
要进行布尔运算就调用MyBody::m_3dgeo中的布尔运算函数去进行。比AutoCAD自带的AcDbSolid3d类要好用!
水平有限,可能好多地方说的不清楚,大家可以参照AModeler提供的例子,自己去实现一个模型,大家可以共同探讨,共同进步! |
|