找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 662|回复: 0

[文章]:关于使用AModeler进行三维建模的一些经验

[复制链接]
发表于 2005-1-14 10:10:56 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
前面看过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提供的例子,自己去实现一个模型,大家可以共同探讨,共同进步!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-9-22 07:30 , Processed in 0.342110 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表