创建和编辑基本图形对象.ppt

上传人:大米 文档编号:569179852 上传时间:2024-07-28 格式:PPT 页数:49 大小:543.86KB
返回 下载 相关 举报
创建和编辑基本图形对象.ppt_第1页
第1页 / 共49页
创建和编辑基本图形对象.ppt_第2页
第2页 / 共49页
创建和编辑基本图形对象.ppt_第3页
第3页 / 共49页
创建和编辑基本图形对象.ppt_第4页
第4页 / 共49页
创建和编辑基本图形对象.ppt_第5页
第5页 / 共49页
点击查看更多>>
资源描述

《创建和编辑基本图形对象.ppt》由会员分享,可在线阅读,更多相关《创建和编辑基本图形对象.ppt(49页珍藏版)》请在金锄头文库上搜索。

1、第三章 创建和编辑基本图形对象 在学习ObjectARX的时候,大多数曾经试图直接去学习数据库的操作、几何类等概念,结果并不理想。经过一段时间的摸索,将创建和编辑基本图形对象作为突破口,逐步深入,在学习过程中成就感很强。3.1.1 说明本实例运行的结果是在AutoCAD 2008中,创建一条直线,该直线的起点是(0,0,0),终点是(100,100,0)。除此之外,不准备再做更多的事情。麻雀虽小,五脏俱全。通过这个程序,你将要开始了解AutoCAD数据库的基本结构3.1 创建直线3.1.2 思路首先来看看,在AutoCAD中,使用LINE命令创建一条直线,需要哪些东西: 命令: _line 指

2、定第一点: 0,0 指定下一点或 放弃(U): 100,100 指定下一点或 放弃(U): 从上面的命令提示可以看出,创建一条直线,需要用户指定起点和终点。在继续之前,必须给大家介绍一点数据库最基础的几个名词: 表:表是数据库的组成单位,一个数据库至少包含一个表。 记录:记录是表的组成单位,一个表可能包含多条记录,也可能不包含任何记录。 上图用来描述AutoCAD数据库的基本结构再好不过了。从图中来看,实体包含在块表记录中,因此要创建一个图形对象,需要遵循下面的基本步骤: (1)确定要创建对象的图形数据库; (2)获得图形数据库的块表; (3)获得一个存储实体的块表记录,所有模型空间的实体都存

3、储在模型空间的特定记录中。(4)创建实体类的一个对象,将该对象附加到特定的块表记录中。3.1.3 步骤(1)使用向导创建一个命令(名称为MyLine)。(2)函数中,添加创建直线对象(在ObjectARX中,AcDbLine类代表直线)的代码: / 在内存上创建一个新的AcDbLine对象AcGePoint3d ptStart(0, 0, 0); AcGePoint3d ptEnd(100, 100, 0); AcDbLine *pLine = new AcDbLine(ptStart, ptEnd); 注意,基于AutoCAD内部的实现机制,必须在堆上创建对象,而不能用下面的语句创建直线的对

4、象: AcDbLine line(ptStart, ptEnd); 此时,直线对象仅被在内存上创建,并没有添加到图形数据库中,因此不可能会显示在图形窗口中。(3)在函数中,添加获得指向块表的指针的相关代码: / 获得指向块表的指针AcDbBlockTable *pBlockTable; acdbHostApplicationServices()-workingDatabase() -getBlockTable(pBlockTable, AcDb:kForRead); acdbHostApplicationServices()-workingDatabase()能够获得一个指向当前活动的图形数据

5、库的指针,这在后面还要经常遇到。getBlockTable是AcDbDatabase类的一个成员函数,用于获得指向图形数据库的块表的指针,其定义为: inline Acad:ErrorStatus getBlockTable( AcDbBlockTable*& pTable, AcDb:OpenMode mode); 该函数的返回值Acad:ErrorStatus是ObjectARX中定义的一个枚举类型,主要用于判断函数的返回状态,如果函数成功执行会返回Acad:eOk。第一个参数pTable返回指向块表的指针;第二个参数同样是一个枚举类型的变量,其类型AcDb:OpenMode包含了AcDb

6、:kForRead、AcDb:kForWrite和AcDb:kForNotify三个可取的值,创建直线的时候不需要更改块表,因此这里打开的模式为AcDb:kForRead。(4)在函数中,添加获得指向特定块表记录的指针的相关代码: / 获得指向特定的块表记录(模型空间)的指针AcDbBlockTableRecord *pBlockTableRecord; pBlockTable-getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb:kForWrite); getAt函数是AcDbBlockTable类的一个成员函数,用于获得块表中特定的记录,其定义为A

7、cad:ErrorStatus getAt( const char* entryName, AcDbBlockTableRecord*& pRec, AcDb:OpenMode openMode, bool openErasedRec = false) const; 第一个参数用于指定块表记录的名称,ACDB_MODEL_SPACE是ObjectARX中定义的一个常量,其内容是“*Model_Space”;第二个参数用于返回指向块表记录的指针;第三个参数指定了块表记录打开的模式,下一步要向块表记录中添加实体,所以就用写的模式(AcDb:kForWrite)打开;第四个参数指定是否查找已经被删除

8、的记录,这里暂时不深入介绍,后面在合适的地方我会谈到它,一般使用默认的参数值。(5)在函数中,添加向块表记录中附加实体的代码: / 将AcDbLine类的对象添加到块表记录中AcDbObjectId lineId; pBlockTableRecord-appendAcDbEntity(lineId, pLine); appendAcDbEntity是AcDbBlockTableRecord类的成员函数,用于将pEntity指向的实体添加到块表记录和图形数据库中,其定义为: Acad:ErrorStatus appendAcDbEntity( AcDbObjectId& pOutputId, A

9、cDbEntity* pEntity); 第一个参数返回图形数据库为添加的实体分配的ID号;第二个参数指定了所要添加的实体。(6)在函数中,添加关闭图形数据库各种对象的代码: / 关闭图形数据库的各种对象pBlockTable-close(); pBlockTableRecord-close(); pLine-close(); 在操作图形数据库的各种对象时,必须遵守AutoCAD的打开和关闭对象的协议。该协议确保当对象被访问时在物理内存中,而未被访问时可以被分页存储在磁盘中。创建和打开数据库的对象之后,必须在不用的时候关闭它。(7)最后,来看一下完整的代码: void ZffCHAP2Crea

10、teLine() / 在内存上创建一个新的AcDbLine对象AcGePoint3d ptStart(0, 0, 0); AcGePoint3d ptEnd(100, 100, 0); AcDbLine *pLine = new AcDbLine(ptStart, ptEnd); / 获得指向块表的指针 AcDbBlockTable *pBlockTable; acdbHostApplicationServices()-workingDatabase()-getBlockTable(pBlockTable, AcDb:kForRead); / 获得指向特定的块表记录(模型空间)的指针 AcDb

11、BlockTableRecord *pBlockTableRecord; pBlockTable-getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb:kForWrite); / 将AcDbLine类的对象添加到块表记录中 AcDbObjectId lineId; pBlockTableRecord-appendAcDbEntity(lineId, pLine); / 关闭图形数据库的各种对象 pBlockTable-close(); pBlockTableRecord-close(); pLine-close(); 3.2 修改图形对象的属性3.2.

12、1 说明上一节的学习,你已经能创建一条直线了,本节介绍的例子则会改变直线的颜色。所要实现的效果非常简单:创建一条直线之后,将它的颜色变为红色。3.2.2 思路如果是在创建时修改直线的颜色,就可以直接在上节函数中加入下面的代码(放在关闭图形数据库各种对象之前): pLine-setColorIndex(1); 运行程序中注册的命令,创建的直线颜色变为红色。在实际编程中,并不是每一次都可以在创建对象时将其特性设置到合适的状态,相反,更多的时候可能在创建对象之后才修改其特性,本节正要解决这个问题。1打开和关闭图形数据库的对象访问图形数据库中对象的特性,必须在该对象被打开(对象创建时也会被打开)的状态

13、下,用对象的指针进行访问,并且在访问结束后要及时关闭该对象,不然就会引起AutoCAD的错误终止。创建一个对象,必须在创建之后关闭该对象,那么如何在某个时候再访问该对象?这就要用到上面介绍的AcDbObjectId,也就是对象的ID号。在创建对象时,可以将图形数据库分配给该对象的ID保存起来,在需要访问该对象时,根据这个ID从数据库中获得指向该对象的指针,就可以修改或者查询该对象的特性。AcDbBlockTableRecord类的appendAcDbEntity函数能够将一个实体添加到图形数据库中;全局函数acdbOpenAcDbEntity用于从实体的ID号获得指向图形数据库中实体的指针,其

14、定义为: Acad:ErrorStatus acdbOpenAcDbEntity( AcDbEntity*& pEnt, AcDbObjectId id, AcDb:OpenMode mode, bool openErasedEntity = false); 第一个参数返回指向图形数据库实体的指针;第二个参数输入了要获得的实体的ID号;第三个参数指定了打开该实体的方式,如果仅是查询该实体的特性用“读”模式打开即可,要修改实体的特性就必须用“写”模式打开;第四个参数指定是否允许访问一个已经被删除的实体。ObjectARX提供了另外两个全局函数acdbOpenAcDbObject和acdbOpen

15、Object来实现类似的功能,这三个函数的区别在与适用范围: acdbOpenAcDbEntity:适用于打开继承于AcDbEntity的数据库常驻对象,这类对象一般都能在图形窗口中显示,如直线、圆等。acdbOpenAcDbObject:适用于打开未继承于AcDbEntity的数据库常驻对象,这类对象不能在图形窗口中显示,如层表、线型表等。acdbOpenObject:如何不知道要打开的对象是否继承于AcDbEntity类,可以使用这个函数。打开某个对象之后,使用close函数就可以将其关闭。对象标识开发者使用ObjectARX API开发时,通常需要标识所处理的对象,同一个数据库对象根据所

16、处的阶段不同可以用不同的标识符加以标识,不同的阶段可以是在dwg 文件中或者是当前图形数据库(内存中),以及选择集中,通常可以通过以下方式标识一个实体。AcDbHandleDWG 文件中的每一个实体都有一个唯一的标识符,称为句柄,用AcDbHandle表示。实体的句柄可以随DWG 文件保存,所以即使DWG 文件没有被AutoCAD 打开,也可以根据句柄搜索DWG 文件获取对象信息,句柄的唯一性仅限于其所在的DWG 文件。 AcDbObjectId当DWG 图形被打开后,数据库中的实体对象都会在内存中对应一个唯一的对象ID(AcDbObjectId),对象ID 也是与实体对象相关联的唯一的标识符

17、, 与句柄不同,对象ID仅存在于其所在的数据库从内存中产生到数据库被删除之间,并且如果操作多个数据库,对象ID 在多个数据库之间都是唯一的。AcDbObject对象指针当一个对象被打开后,AutoCAD 会返回指向AcDbObject或其派生类型的一个C+指针,开发者就可以采用标准C+类对象的方式对实体进行操作。显然,这是ObjectARX操作实体的主要方式。ads_nameads_name 是AutoCAD 定义的一个数据类型,这个数据类型在AutoCAD 发展到ADS开发阶段被引入,并作为ADSRX 的一部分保留在ObjectARX 开发方式下。ads_name 一般用来保存用户交互过程中

18、成功选择实体的结果,通常,选择实体是为了用户能获得并修改实体的属性,ObjectARX提供了ads_name与对象ID的转换函数,从而可以按ObjectARX的方式修改实体属性。对象标识符的相互转换ObjectARX 提供了丰富的实体标识符转换函数,保证开发者采用合适的开发方式获取或修改实体的属性,如图所示:具体来说,ID、指针、句柄和ads_name之间具有下面的转换关系(不完转换并未提及): 从ID到对象指针:通过打开数据库对象的三个函数acdbOpenAcDbEntitu、cdbOpenAcDbObject和acdbOpenObject中的任何一个。 从对象指针到ID:所有的数据库常驻对

19、象都继承自AcDbOject,而AcDbObject类包含的objectId函数能获得所指向对象的ID。 从句柄到ID:使用AcDbDatabase:getAcDbObje函数。从ID到句柄:使用AcDbObjectId:handle函数。从指针到句柄:使用AcDbObject:getAcDbHandle函数。从ads_name到ID:使用全局函数acdbGetObjectId。从ID到ads_name:使用全局函数acdbGetAdsName。调用全局函数acdbOpenObject()传入AcDbObjectId将打开对象,得到对象指针。调用AcDbObject :getAcDbHandl

20、e()可以获取对象的句柄AcDbHandle,通过AcDbDatabase: getAcDbObjectId()可以将对象句柄AcDbHandle映射为AcDbObjectId对象;反之,AcDbObjectId:handle()函数用于返回AcDbObjectId所关联的对象句柄AcDbHandle。调用acdbGetObjectId()可以ads_name 转化为AcDbObjectId;反之,调用acdbGetAdsName()则将AcDbObjectId转化为ads_name。例:/选择对象,返回ads_nameads_name en;ads_point pt;acedEntSel(_

21、T(n选择对象: ), en, pt);/通过对象标识转换函数得到对象IDAcDbObjectId eId;acdbGetObjectId(eId, en);/打开实体,得到AcDbEntity指针AcDbEntity * pEnt;acdbOpenObject(pEnt, eId, AcDb:kForRead);3.3 创建圆在ObjectARX中,AcDbCircle类用来表示圆。该类有两个构造函数,其形式分别为: AcDbCircle(); AcDbCircle(const AcGePoint3d& cntr, const AcGeVector3d& nrm, double radius

22、); 两个构造函数的名称相同,接受不同的参数,这是C+中函数的重载。重载是C+提供的一个很有用的特性,相同功能的函数采用同样的名称,大大减少了程序员的记忆量。 第一个构造函数不接受任何参数,创建一个圆心为(0,0,0)、半径为0的圆,其所在平面法向量为(0,0,1);第二个构造函数则接受了圆心、圆所在平面法向量和半径三个参数。一般来说,我习惯于在创建实体时直接将其初始化,很少用第一个构造函数。AcGePoint3d ptCenter(0,0,0); AcGeVector3d vec(0,0,1) double radius =10AcDbCircle *pCircle = new AcDbCi

23、rcle(ptCenter, vec, radius); / 将实体添加到图形数据库 AcDbObjectId circleId; 3.3 对象的类型判断由于所有实体都是从AcDbEntity 派生的,所以当打开一个AcDbEntity 对象时,开发者经常需要进一步判断其类型,如判断是一条线还是一个圆等。在实际的开发中,对ObjectARX 对象进行类型判断需要使用ObjectARX 提供的类型判断机制。我们可以通过AcRxObject:desc()静态函数返回AcRxClass 类型的指针,然后调用AcRxObject:isA()或者AcRxObject:isKindOf()来进行类型判断,

24、其中AcRxObject:isA()用于判断对象是否是所需要的对象类型,而AcRxObject:isKindOf()可用于判断对象是否是所需要的类型或者其派生类类型。假定AcDbEntity *pEnt,判断实体是否正好是一条线段可用以下代码:if(pEnt-isA()=AcDbLine:desc()如果要判断实体是否是线段或者线段的派生对象,可用以下代码来实现:if(pEnt-isKindOf(AcDbLine:desc() AcDbLine* pLine = AcDbLine:cast(pEnt);通过上述方法完成了对象的类型判断以后,如果需要进行类型转换,通常调用静态函数AcRxObje

25、ct:cast ()来完成,该函数将传入的对象指针转化为指定的对象类型指针,如上述代码中将实体pEnt 转化为AcDbLine对象指针。3.4 实体操作前面介绍了通过API创建新实体对象,除此之外,开发者还可以通过API来对实体进行打开、编辑、删除等操作,当然对于复杂实体在处理的时候需要多做一些工作。3.4.1 实体操作方式ObjectARX 中对实体的操作一般有两种方式,一种为open/close 方式,另一种为通过事务的方式。 open/close方式在 open/close 方式中,通常调用全局函数acdbOpenObject()来打开实体对象,需要传入数据库对象ID,返回数据库对象的指

26、针。另外还可以通过acdbOpenAcDbEntity()打开从AcDbEntity派生的实体对象,或者调用acdbOpenAcDbObjec()打开从AcDbObject派生的数据库常驻对象。这三个函数的用法一样,下面以acdbOpenObject()为例说明函数的使用,acdbOpenObject函数原型为:Acad:ErrorStatus acdbOpenObject(AcDbObject*& obj,AcDbObjectId objId,AcDb:OpenMode openMode,Adesk:Boolean openErasedObject);或者:Acad:ErrorStatus

27、acdbOpenObject(AcDbEntity *& pEnt,AcDbObjectId id,AcDb:OpenMode mode,bool openErased);在通过 acdbOpenObject函数打开对象的时候,需要指定对象的打开模式AcDb:OpenMode, 打开模式有AcDb:kForRead,AcDb:kForWrite和AcDb:kForNotify三种,各种模式的说明如下:打开模式打开模式 说明说明AcDb:kForRead以读的模式打开对象。一个对象最多可以同时被以读模式打开256次,此时不能再以读或通知模式打开AcDb:kForWrite以写模式打开。如果已经打

28、开,则以写模式打开对象将失败。一个对象同时只能以写的模式打开一次。AcDb:kForNotify以通知模式打开。当对象已经被读或写模式打开时,可以通知模式打开。当以AcDb:kForRead打开对象的时候,只能访问数据库对象的数据,不能进行修改操作,如果要进行修改,需要调用AcDbObject:upgradeOpen()将打开模式升级为写,可以调用AcDbObject:downgradeOpen将对象打开模式降低为读。实体对象打开后,就可以通过实体的对象指针操作实体,当操作结束后,切记关闭实体对象,否则会造成AutoCAD 异常,关闭实体调用的是实体的close()成员函数。/选择对象ads_

29、name en;ads_point pt;acedEntSel( _T(n选择实体: ), en, pt);AcDbObjectId id;/转化ads_name 为AcDbObjectIdacdbGetObjectId(id,en);AcDbEntity * pEnt;/打开对象acdbOpenObject(pEnt, id, AcDb:kForRead );/将打开的对象转化为AcDbLine对象指针if(pEnt-isKindOf (AcDbLine:desc()/ 编辑对象AcDbLine* pLine = AcDbLine:cast(pEnt);pLine-upgradeOpen (

30、);pLine-setColorIndex (1);/关闭对象pEnt-close();3.4.2实体的删除如果新创建的实体没有通过AcDbBlockTableRecord:appendAcDbEntity()加入到块表记录的时候,它只是一个普通的C+对象指针,开发者可以使用delete将其删除。一旦实体被添加加进数据库,则不能通过delete 进行删除,否则会造成AutoCAD 崩溃。删除已经在数据库中的实体必须通过AcDbObject:erase(),该函数有一个bool 型的参量,所以它既可以删除实体,也可以将删除的实体恢复。实际上,erase 函数只是将实体做了是否删除的标记,实体仍然

31、在数据库中,只有执行了文件保存操作的时候,它才会从数据库中消失。3.5 实体属性不论是AutoCAD 自带的实体还是开发者开发的自定义实体,所有实体都是从AcDbEntiy派生的,它们都具有一些共同的属性,并且拥有共同的存取属性的函数。这些属性包括颜色、线型、线型比例、可见性、图层等。当添加一个实体到块表记录的时候,如果没有明确的设置这些属性,AutoCAD 会自动调用AcDbEntity:setDatabaseDefaults()函数,将这些属性设置为默认值。3.5.1实体颜色实体颜色可以用0256 的颜色索引值表示,也可以用AcCmColor 类来表示,通过AcCmColor:colorI

32、ndex()成员函数可以得到颜色的索引值。颜色索引值17 用于标准颜色,8255 的颜色取决于显示设备。17 的颜色如下表可以通过AcDbEntity:colorIndex() 来获取实体颜色索引值,也可以通过AcDbEntity:setColorIndex(Adesk:UInt16 color)来设置实体的颜色,下面代码通过输入颜色索引来改变实体的颜色。Acad:ErrorStatuschangeColor(AcDbObjectId entId, Adesk:UInt16 newColor)AcDbEntity *pEntity;acdbOpenObject(pEntity, entId,

33、AcDb:kForWrite);pEntity-setColorIndex(newColor);pEntity-close();return Acad:eOk;3.5.2实体线型线型就是定义了一系列的点和短线的组合,用来绘制不同样式的线段,在ObjectARX中线型对象对应线型表中的一条线型记录,通过AcDbLinetypeTableRecord来表示,通过API 可以根据线型记录的名称来获取指定的线型表记录,如下代码所示:/首先获取线型表AcDbLinetypeTable *pLinetypeTbl;es = acdbHostApplicationServices()-workingData

34、base()-getSymbolTable(pLinetypeTbl, AcDb:kForRead);if (es != Acad:eOk) return;/ 获取指定的线型表记录AcDbObjectId ltypeObjId;es = pLinetypeTbl-getAt(_T(CONTINUOUS), ltypeObjId);if (es != Acad:eOk) es = pLinetypeTbl -close();return;当一个实体对象被创建时,其线型被初始化为NULL,然后用户可以通过调用AcDbEntity:setLinetype()传入线型名或线型的对象ID 来设置实体的线

35、型,同样也可以AcDbEntity:linetype()或AcDbEntity:linetypeId()来返回实体线型名或线型的对象ID。可以通过以下代码来设置实体的线型:ads_name en;ads_point pt;acedEntSel( _T(n选择实体: ), en, pt);AcDbObjectId entId;acdbGetObjectId(entId, en);AcDbEntity *pEntity;acdbOpenAcDbEntity(pEntity, entId,AcDb:kForWrite);pEntity-setLinetype(_T(HIDDEN);pEntity-close();如果实体对象添加到数据库时没有显式地调用以上函数进行设置,则实体将采用数据库的当前线型值,此值存在CELTYPE 系统变量中。AutoCAD 中提供一些特殊的线型,具体说明如下表:

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号