资源描述
ACIS-HOOPS新手上手学习方法
时间进度安排:
开始学习————————————————————————————————————1.5天
环境准备————————————————————————————————————0.5天
学会ACIS造型方法——————————————————————————————— 1天
在工程中实现对四面体的“实时拖动变形”功能————————————————— 1天
掌握acispartview工程功能实现机制——————————————————————— 1天
Acispartviewer的修改:实现三维立方体的功能—————————————————— 2天
参数化驱动 三维立方体的功能——————————————————————————2天
三维立方体功能的产品化—————————————————————————————2天
如何学习ACIS和HOOPS
学习前所具备的知识及能力:
具备C/C++基础,MFC基础,熟悉pro_e UG 等3D软件的一种。
开始学习
首次接触ACIS和HOOPS不是马上进行学习,而是应该了解HOOPS和ACIS到底是是什么,有什么用。
ACIS是什么?
(以下内容来自百度百科)
ACIS是由美国Spatial Technology公司推出的,Spatial Technology公司成立于1986年,并于1990年首次推出ACIS。ACIS最早的开发人员来自美国Three Space公司,而Three Space公司的的创办人来自于Shape Data公司,因此ACIS必然继承了Romulus的核心技术。ACIS的重要特点是支持线框、曲面、实体统一表示的非正则形体造型技术,能够处理非流形形体。
ACIS是用C++构造的图形系统开发平台,它包括一系列的C++函数和类(包括数据成员和方法)。开发者可以利用这些功能开发面向终端用户的三维造型系统。ACIS是一个实体造型器,但是线框和曲面模型也可以在ACIS中表示。ACIS通过一个统一的数据结构来同时描述线框、曲面和实体模型,这个数据结构用分层的C++类实现。ACIS利用C++的特点构造了标准的、可维护的接口。API函数在不同ACIS版本之间保持一致性,而类及其接口函数则可能改变。ACIS中应用到的主要C++概念包括:数据封装、类构造重载、构造拷贝、类方法和操作符重载以及函数重载等。C++没有提供描述几何体的数学基本类,ACIS提供了一些C++基类实现这个功能,并且利用C++的特性可以对它进行了扩充,这样ACIS就可以支持任意几何体的定义和构造功能。
ACIS是美国Spatial Technology公司推出的三维几何造型引擎,它集线框、曲面和实体造型于一体,并允许这三种表示共存于统一的数据结构中,为各种3D造型应用的开发提供了几何造型平台.Spatial Technology公司在1986年成立,目前ACIS 3D Toolkit在世界上已有380多个基于它的开发商,并有180多个基于它的商业应用,最终用户已近一百万.许多著名的大型系统都是以ACIS作为造型内核,如AutoCAD,CADKEY,Mechanical Desktop,Bravo,TriSpectives,TurboCAD,Solid Modeler,Vellum Solid等.
ACIS主要功能是用来构建和保存读取实体数据,并对这些数据进行处理。注意:ACIS无法在窗口中显示图形,你能看到的只是一些数据。
Hoops是什么?
(以下内容来自百度百科)
HOOPS 3D Application Framework (HOOPS/3dAF)是由Tech Soft America公司开发并由Spatial再次销售的产品,该产品为当今世界上领先的3D应用程序提供了核心的图形架构和图形功能,这些3D应用程序涉及 CAD/CAM/CAE、工程、可视化和仿真等领域。有了HOOPS/3dAF,用户就站在一个高起点上,能够快速和有效地开发和维护高性能的用户应用程 序。用户通过将HOOPS/3dAF集成到相应的软件开发中,可以更好地管理开发成本、优化资源和缩短产品上市时间。
这里HOOPS可以将ACIS中的数据以图形的方式在窗口中显示出来。
学习过程中,可以花少量时间上网查询相关内容,了解ACIS和HOOPS的相关内容,方便更好的理解相关内容。(以上内容花半天的时间了解)
ACIS的学习
了解完ACIS和HOOPS相关知识后,接下来我们要具体学习ACIS方面的相关知识。
抓住一个核心:ACIS的数据结构,即ACIS模型的拓扑结构,如下图,阅读教材:《基于ACIS的几何造型技术与系统开发》的第1,2,3章章节内容(4-12章粗略阅读,有个大致印象即可,不必详读)。
hoops的学习
合理安排时间,在学习ACIS的同时,也要对hoops的相关内容有所掌握,结合PPT文档《HOOPS基础培训课程》,理解hoops中相关组件的作用。
n HOOPS/3dGS:
场景图API
n HOOPS/MVO:
实现了3D应用程序框架的功能
• 模型:文件的输入输出,模型的管理
• 显示:文字和相机的管理
• 操作:对象操作的管理
n HOOPS/MFC
封装了所需要的操作
• 与窗口的连接,获得窗口句柄和窗口的ID号
• 将鼠标和键盘事件映射到了HOOPS/MVO
• 封装了剪贴板,打印机和打印机预览
n HOOPS/Stream
支持HSF的读写功能
• 数据是高度压缩的,大大缩短传输时间
• 数据的分类,流化处理
支持2D和3D
• 支持3dGS中所有的几何体
n HOOPS/GM Bridge
连接HOOPS与建模内核(如ACIS)
• 封装了连接模型与HOOPS几何的函数
将模型映射到HOOPS几何
• 读写SAT文件
• 选择与高亮显示的处理
• 当创建和更新模型的时候,图形数据也被创建和更新
n HOOPS ACIS Bridge是ACIS组件的一部分
环境准备
通过前面的内容学习,我们对ACIS和HOOPS作用及相关内容有了初步的认识,接下来将要搭建学习后续知识的平台。
acispartview是一个简单的小型ACIS/HOOPS三维CAD平台,ACIS是一个几何造型引擎,HOOPS是图形显示平台,通过学习该平台,可以概况地了解基于ACIS/HOOPS的三维CAD系统的基本结构。(参考文档《ACIS-HOOPS造型学习方法.doc》中第二部分,工程设置入门)
该平台的搭建工作可能遇到各种问题:(最好将ACISR15和HOOPS1220放在根目录下)
1 没有找到头文件和动态库文件
操作系统环境变量设置:添加如下环境变量:1)A3DT<自定义目录>\acisR15\include2)HOOPS<自定义目录>\Hoops1220\Dev_Tool
在VC6.0中的菜单项tools->options的Directories选项卡中 include files和Library files的Directories添加:
2 运行activeproject.exe时发现缺少dll文件
找到上图中的文件并将其放在activeproject.exe的文件夹内即可。
如遇到其它问题可参考文档《ACIS-HOOPS造型学习方法.doc》中工程设置的内容。
工程运行及效果
将工程运行起来,加载部分sat文件,观察并实验工具栏上部分按钮的功能及效果。
掌握工程中的基础技术
学会ACIS造型方法
活学活用ACIS造型方法,可以从构造一个几何体开始。仔细阅读并理解教材《基于ACIS的几何造型技术与系统开发》中第十三章,第十四章的内容。掌握构造一个实体模型的基本方法和各个API的使用方法。教材中涉及的Scheme语言暂不学习。
以下是构建一个实体的基本方法:
api_start_modeler(0);//生成内部数据结构
api_initialize_"组件";
//api函数和直接函数调用
api_terminata_"组件";
api_stop_modeler();//删除内部数据结构
例子:
void main(){
api_start_modellor(0); //启动造型器
api_initialize_constructors(); //初始化应用程序组件
BODY *block; //声明一个指针
api_make_cuboid(100,50,200,block); //调用ACIS的API函数构造几何体
FILE *output = fopen(“cube.dbg”,”w”); //打开一个文件
debug.size(block,output); //调用调式功能的函数将数据结构存入文件
fclose(output); //关闭文件
api_terminate_constructors(); //中断组件,释放组件所占用的组件
api_stop_modeller(); //停止造型器
}
利用ACIS和HOOPS来开发三维图形软件,编程时的基本思路;
启动:
api_start_modeller(0);
……
造型:
HC_Open_Segment_By_Key(m_pHView->GetViewKey());
BODY* sphere_body;
api_make_sphere(radius, sphere_body);
……
转换:
HA_Set_Rendering_Option();
HA_Render_Entity((ENTITY*) sphere_body);
HC_Close_Segment();
……
终止:
HA_Close();
api_stop_modeller();
在工程中实现对四面体的“实时拖动变形”功能
1 建立ACIS/HOOPS造型平台acispartview。
2 在acispartview中构造ACIS数据结构的四面体模型。
参考教材14.5。
3 实现在Hoops中显示该四面体模型。
参考程序1。添加了两个成员变量: m_iIndexVertex、m_positon[4]。
4 响应顶点(Vertex)被选中的消息。
参考程序2。
5 实现“实时拖动变形”功能:将某一顶点拖动到屏幕任意位置后,重新构造新四面体。
参考程序3。
6 完善该程序。
6.1 将构件四面体的功能添加到菜单功能中;
6.2 拖拽鼠标,构造四面体动态线框,以表达拖拽的实时性。
参考程序1:
“CSolidHoopsView.h”下添加如下两个成员变量:
public:
int m_iIndexVertex; //标示当前被选中顶点的序号@zxc
SPAposition* m_positon[4]; //四面体的四个顶点@zxc
void CSolidHoopsView::OnTetra()
{
HSolidModel* pSolidModel = (HSolidModel*)(m_pHView->GetModel());
if (!pSolidModel)
return ;
pSolidModel->m_bSolidData = true; // 将m_bSolidData设为TURE,则可以选中顶点
pSolidModel->m_bSolidModel = true;
pSolidModel->SetBRepGeometry(true);
pSolidModel->SetModelHandedness(HandednessSetLeft);
//构造一个四面体
m_positon[0] = new SPAposition(0.0,0.0,0.0);
m_positon[1] = new SPAposition(10.0,0.0,0.0);
m_positon[2] = new SPAposition(0.0,10.0,0.0);
m_positon[3] = new SPAposition(0.0,0.0,10.0);
BODY *block;
Tetrahedron(block); //四面体的构造函数,参考教材14.5
pSolidModel->AddAcisEntity(block);
HC_Open_Segment_By_Key(m_pHView->GetModelKey());
HA_Render_Entity(block);// ha_bridge将ACIS几何体转换为Hoops几何体
HC_Close_Segment();
m_pHView->Update();
}
参考程序2:
void CSolidHoopsView::OnLButtonDown(UINT nFlags, CPoint point)
{
CHoopsView::OnLButtonDown(nFlags,point);
//判断顶点是否选中,如果选中,记录被选择点的序号
HSelectionSet* sel_set = m_pHView->GetSelection();
const HSelectionItem *selItem=sel_set->GetSelectionItemAt(0);//@zxc
if (selItem != NULL)
{ HC_KEY hKey=selItem->GetKey();
if (hKey!=NULL)
{ char type[MVO_BUFFER_SIZE];
HC_Show_Key_Type(hKey, type);
char* pdest;
pdest=strstr(type,"marker");
if (pdest != NULL)
{// AfxMessageBox(_T("选中的对象是顶点!"));
ENTITY*enty=HA_Compute_Entity_Pointer(hKey);
VERTEX* vertex=(VERTEX*)enty;
SPAposition pos=vertex->geometry()->coords();
for (int i=0;i<=3;i++)
{if (*m_positon[i] == pos)
{m_iIndexVertex=i+1;
break;}}}}}}
参考程序3:
void CSolidHoopsView::OnLButtonUp(UINT nFlags, CPoint point)
{ HSolidModel* pSolidModel = (HSolidModel*)(m_pHView->GetModel());
if (!pSolidModel)
return ;
if (m_iIndexVertex!=0)
{ pSolidModel->DeleteAllEntities();//删除原来的四面体,再重构一个新的四面体
HC_Open_Segment_By_Key(m_pHView->GetSceneKey());
HPoint localPixel,world;
localPixel.Set(point.x,point.y,0.0);
HC_Compute_Coordinates(".","local pixels",&localPixel,"world",&world);
m_positon[m_iIndexVertex-1]->set_x(world.x);
m_positon[m_iIndexVertex-1]->set_y(world.y);
m_positon[m_iIndexVertex-1]->set_z(world.z);
m_iIndexVertex=0;//标示符m_iIndexVertex清零,重新构造四面体后, HC_Close_Segment(); 可对四面体反复拖拽。
BODY *block;
Tetrahedron(block);
pSolidModel->AddAcisEntity(block);
HC_Open_Segment_By_Key(m_pHView->GetModelKey());
HC_Insert_Line(0.0,0.0,0.0,20.0,20.0,20.0);
HA_Render_Entity(block);
HC_Close_Segment();
m_pHView->Update();
}
CHoopsView::OnLButtonUp(nFlags,point);}
掌握acispartview工程功能实现机制
通过上面的例子,理解工程中部分功能模块的实现机制
例1:
点击菜单项View->Tetra,在窗口中显示了一个四面体
它的实现机制是:点击tetra后,产生了一个消息COMMAND消息,该消息ID是IDM_TETRA,根据消息ID,系统调用OnTetra()函数,OnTetra()函数里面封装了四面体的实现过程。
例2:
点击按钮,窗口中四面体显示为实线
点击Wireframe按钮后,产生了一个COMMAND消息,消息ID为ID_TOOLS_RENDERMODE_WIREFRAME,系统根据消息ID调用函数,CSolidHoopsView::OnToolsRendermodeWireframe(),该函数封装了将实体用实线表示的方式,同时也产生了一个ON_UPDATE_COMMAND_UI消息,保证了三个toolbars只激活其中一个。
通过以上例子的学习,利用VC6.0,查看源代码,使我们对acispartview工程中的功能实现有了初步的了解,工具栏和菜单栏中功能的实现基本与上面的例子类似。我们在学习过程中,还应该不断的积累文档内容,了解相关API,这样保证我们在今后的工作中能更加得心应手。
Acispartviewer的修改:实现三维立方体的功能
在acispartviewer窗口中构建一个立方体,首先在资源文件的菜单选项里添加菜单项(lifang),设置其消息ID(IDM_LIFANG)
在CSoildHoopsView类的头文件中添加消息处理函数OnLifang(),
在CSoildHoopsView类的实现文件中添加消息映射ON_COMMAND,
以上内容可直接用VC6.0中MFC ClassWizard自动生成,然后编写OnLifang()函数实现内容:
实现效果:
Acispartviewer参数化驱动 三维长方体的功能
在实现立方体的功能上,我们将实现长方体的功能,长方体的长、宽、高数值由我们自己设置。
思路:在菜单栏或者工具栏增加一个菜单项,消息映射函数里创建一个模式对话框,该对话框里设置数值,点击确定创建长方体,点击取消,不做任何操作。
例:
首先在资源文件的菜单选项里添加菜单项(lifang),设置其消息ID(IDM_LIFANG)
添加对应的消息函数OnLifang() ,方法与前面例子相同。
设置全局变量,用来存放立方体的长宽高等数据。
在资源菜单里添加一个对话框窗口,具体设置如图:
创建该对话框类CLifangDlg。重写OnOK()函数,实现当点击确定按钮时,将编辑框内的数据传给全局变量。
在OnLifang()函数实现该长方体创建的功能。
实现效果:
思考:
该功能是否还有需要完善的地方?
如编辑框内数值为0时,程序崩溃。
三维立方体功能的产品化
针对上面例子中部分功能不完善处,下面我们来实现改进工作。
1 编辑框内可以填写除数字以外的符号。
打开该对话框的资源文件,设置其属性Properties的styles选项卡中勾选Number选项。
2 编辑框内设置初始值。
打开编辑框的类,在Dodataexchange()函数中对编辑框内的内容进行初始化。
初始化代码如下
3 编辑框内设置数值为0时程序会崩溃
解决数值为0的问题首先要对编辑框内得到的数据进行判断,判断为非正数的时候不能通过,达到如下效果
为了达到该效果,就需要对点击确定时进行处理,当数据正确时,能正常的进行后续操作,当数据不对时,弹出对话框提示输入正确的数据,并继续进行输入数据操作。这里判断位置仍然在OnOk()函数中进行判断。代码如下:
添加条件判断即可解决该问题。
4 添加预览功能
首先,要添加预览功能,则需要在对话框不关闭的前提下进行,否则无法在窗口中显示我们需要的图形。前面的对话框都是在建立的模式对话框,达到预览功能则需要建立非模式对话框。
创建具有预览功能的对话框。
① 建立非模式对话框
我们例子中代码只需在菜单项flifang的响应函数中添加即可。
② 点击确定、预览等按钮都可达到显示立方体的功能,那么就需要用消息来传递,当视图窗口接收到了对话框发来的消息,即可在窗口显示图形。
下面,首先要在CSolodHoopsView中添加自定义的消息处理函数
在头文件中添加自定义的消息ID
在CSolodHoopsView添加消息处理函数
自定义消息处理函数OnFlifang1的代码,实际上就是调用Onlifang()函数进行长方体的构造。
实现对话框在点击确定和预览时都发送WM_MYMESG消息,能够让视图窗口接收到。在它们的代码中添加如下代码即可发送消息
点击预览和确定按钮代码有所区别,点击预览对话框不关闭,具体代码如下:
备注:熟悉MFC中自定义消息传递的用法(具体内容查资料)
③ 实现预览时颜色和点击确定颜色不相同。
设置预览时,实现的颜色为黄色,实现时为绿色,调用 api_rh_set_entity_rgb()对实体进行着色,该函数的用法如下:
api_rh_set_entity_rgb((ENTITY*&)body,rgb_color(r,g,b));
//其中,api_gi_set_entity_rgb是着色函数,(ENTITY*&)body指定实体, body,rgb_color (r,g,b)进行着色。
达到的效果如下
点击预览
点击确定
5 视图中显示多个立方体,预览颜色和非预览颜色同时出现 ,如下图
解决该问题时,将实体类定义为全局变量,前面我们都是用的局部变量,定义后,每次显示时将原实体取消显示即可达到效果,添加代码
附录:(以下内容仅供参考)
ACIS的API相关函数:
api_make_... 坐标原点构建
api_solid_... 给定位置构建
//立方体
api_make_cuboid(length(x),width(y),height(z),BODY)
api_solid_block(SPAposition(左上角顶点坐标), SPAposition(右下角顶点坐标),BODY)
//球体
api_make_sphere(半径,BODY)
api_solid_sphere(SPAposition(圆心坐标),半径,BODY)
//圆环体
api_make_torus(外环半径,环宽,BODY)
api_solid_torus(SPAposition(环心坐标), 外环半径,环宽,BODY)
//圆锥体
api_make_frustum(height(z), length(x),width(y),顶部半径,BODY)
api_solid_cylinder_cone(SPAposition(顶部圆心坐标), SPAposition(底部圆心坐标),m*M_PI(底部长轴),n*M_PI(底部短轴),0(顶部半径),NULL,BODY)
//圆柱体
api_make_frustum(height(z), length(x),width(y),顶部半径,BODY)
api_solid_cylinder_cone(SPAposition(顶部圆心坐标), SPAposition(底部圆心坐标),m*M_PI(底部长轴),n*M_PI(底部短轴),0(顶部半径),NULL,BODY)
//棱柱
api_make_prism(height(z), length(x),width(y),棱数,BODY)
//棱锥
api_make_pyramid(height(z),length(x),width(y),顶部半径,棱数,BODY)
outcome api_ent_area ( ENTITY * ent,
double req_rel_accy,
double & area,
double & est_rel_accy_achieved,
AcisOptions * ao = NULL
) //计算面积
api_set_file_info 设置文件头部信息,生成模型文件时这些信息会被自动加入到文件的头部
api_save_entity_list 将实体的ASCII信息写入文件
api_restore_entity_list 将磁盘上的SAT文件读入到内存中
ENTITY_LIST类的成员函数
int add(ENTITY*) 将实体加入列表
int count() 返回列表中实体的个数,包括被删除的实体
int iteration_count() 返回列表中实体的个数,不包括被删除的实体
int lookup(ENTITY*) 在列表中查找实体
int remove(ENTITY*) 在列表中删除实体
ENTITY *operator[](int) 返回给定位置的实体指针
void init() 准备进行列表遍历
ENTITY* next() 依次返回列表中的实体
api_apply_transf(BODY,transf) // 旋转实体
api_unite(body1,body2) //实体求并 结果保存在第二个变量中,第一个变量所表示的实体将被系统删除
展开阅读全文