AutoCAD图形实际上是一系列存放在一个AcDbDatabase类型的数据库中的AcDb对象。AcDbDatabase数据库中所有的对象都有一个句柄,在一个图形(DWG)文件中,对象句柄是唯一的,用来标识对象。AutoCAD图形实体(AcDbEntity类对象)只是AcDbDatabase数据库的一种特殊的对象,用户可以在图形窗口看到并编辑它。AcDbDatabase数据库中的对象还有符号表、词典和其它与AcDb类对象相关的符号。数据库中所有的图形实体和对象都可以使用ObjectARX技术,通过程序设计来进行修改和编辑。这一点其实也就是AutoCAD二次开发的基本出发点和最终目标。<这话对吗?总感觉有些不妥,但不知道如何表达才准确。><尖括号中的内容是我个人感想,不会出现在最终文档中。>
AcDbDatabase既然是数据库,它必然具备数据库的基本组织结构。它由多个表(Table)和表中的记录(Record)构成。AcDbDatabase数据库包括九个符号表和一个命名对象词典。<下面这张图表与大部分教材不同,各位以为如何?>
AcDbDatabase数据库
AcDbDatabase数据库使用了面向对象的数据库(OODB)技术,用传统的数据库的术语来说,它甚至不是第一范式(1NF)的,记录的组织形式与普通的数据库有较大的不同。<这大概是很多人没把AutoCAD图形看作数据库的原因。>在AutoCAD命令行运行LISP函数entget可以清楚地看到实体在AcDbBlockTable块表中的记录组织形式。当然,在ObjectARX技术中,关于数据库记录的细节进行了数据封装,对数据库的表和记录进行操作要通过访问各个类的成员函数来实现。
以下详细解释AcDbDatabase数据库操作的ObjectARX技术。
1.1
要使用AcDbDatabase数据库,与使用其它数据库一样,首先要声明一个数据库对象。AcDbDatabase类的声明,调用类的构造函数:
AcDbDatabase
其中,buildDefaultDrawing参数控制是否创建一个包括所有默认数据记录的数据库。该参数的默认值为true,这样在AcDbDatabase数据库创建时,将在新建的数据库中包含一个AutoCAD图形数据库必须包含的基本数据要素,这些要素包括九个符号表及其初始记录(比如0层、STANDARD文字样式等),命名对象词典(组词典和多线样式词典)以及必要的系统变量设置。这样就可以向新建的数据库中添加各种实体和对象。若指定该参数为false,AutoCAD将创建一个完全空的AcDbDatabase数据库。这样的AcDbDatabase数据库不能直接向其中添加实体或对象,需读入一个图形文件来拓展该图形数据库,然后再逐步添加或修改数据库中的实体或对象。读入图形数据库使用函数:
AcadErrorStatus
<其实,readDwgFile()函数还有两个参数,分别控制数据库读写权限和内码转换,好象在这没必要作更深入的讨论,因此略过。>
AcDbDatabase构造函数的noDocument参数控制打开或的数据库是否与当前文档关联(true代表不和当前文档关联,false表示和当前文档关联)。此参数的使用将在“多文档处理”一节中详细讨论。
这样,要使用AcDbDatabase数据库,若准备新建数据库并向其中添加实体或对象,使用这样的代码:
AcDbDatabase
若要使用已有的图形,比如“”文件,则使用下列代码:
AcDbDatabase
pDb->readDwgFile(“”);
注意,在这种情况下,AcDbdatabase()的参数必须指定为false(当然,0或者Adesk::kFalse都可以)。<ARX帮助中说必须为Adesk::kFalse,AutoDesk是不是有点老大作风?>因为使用pDb->readDwgFile()函数时,pDb必须是一个完全空白的数据库,也就是说,哪怕使用了AcDbDatabase(false);新建数据库,只要对数据库进行了操作,就不能再使用readDwgFile()函数,否则会导致严重的内存错误。
还有一种情况,ARX程序只对当前图形数据库进行操作,在ACAD
AcDbDatabase
在ACAD
AcDbDatabase
实际上,在ARX
1.2
新建或打开图形数据库后,可获取表和记录的指针,然后再对记录进行操作。要获取AcDbDatabase数据库记录指针,大致分为两个步骤:
首先,获取数据库表的指针。为了获取该指针,须声明一个类指针,该指针类型决定要使用的数据库表的类型(或名称)。比如说,要使用AcDb的块表及其记录,应该这样声明指针类:AcDbBlockTable
然后使用AcDbDatabase类的成员函数获取表指针。获取块表指针可使用函数getBlockTable()函数。
Acad::ErrorStatus
AcDb::OpenMode
该函数的第一个参数是一个指向表引用(或者说地址)的指针。用于函数输出块表指针。另一个参数控制使用表的读写权限。
其它符号表指针的获取与块表指针的获取基本一致,可参考ARX帮助或头文件。从ARX2000开始,在AcDbDatabase类的成员函数中,还有一种方法可获取数据库中符号表的指针。即使用getSymbolTable()函数,该函数有九个重载版本,分别对应九个符号表,几个重载版本之间仅第一个参数的类型不同。例如,要新建图层,可以这样获取层表指针:
AcDbLayerTable*
pDb->getSymbolTable(pLayerTbl,AcDb::kForWrite);
使用数据库,最终往往要对数据库表中的记录进行操作,因此打开表后,就需要获取记录指针。所有AcDb符号表记录指针都可通过调用对应表的getAt()函数来实现。每一个getAt()函数都有两个重载版本,分别输出记录ID或记录指针。<是不是太哆嗦?>
getAt()函数完整语法:
输出记录指针:
Acad::ErrorStatus
AcDb##BASE_NAME##TableRecord*&pRecord,
Adesk::Boolean
输出记录ID:
Acad::ErrorStatus
AcDbObjectId&
实际应用时,将##BASE_NAME##替换成九个符号表的实际类型。
在这解释两个参数,char*
最后,取出数据库符号表记录后,若不再使用表对象,应及时关闭,回收系统资源。
AcDb##BASE_NAME##Table::close();
1.3
获取数据库记录指针或记录ID后,就可以对数据库记录进行操作了,这包括在数据库中添加、删除记录,提取记录中的数据,即查找记录。
向数据库中添加记录,通用的方法是调用符号表类的add()成员函数。
Acad::ErrorStatus
Acad::ErrorStatus
AcDbSymbolTableRecord*
在这要说明一下,通常我们向模型空间添加实体不用这些方法。因为模型空间本身就是AcDb块表中的一条记录,向其中添加实体仅仅是对该记录进行操作,不需要向数据库中添加记录。
1.4
第一个例子来自ARX示例文档,目录\ObjectARX
下一个例子是对上一例子中添加图层的方法做出完善。在这个例子中将说明对层表和线型表及其记录操作的方法。
void
{
}
以上只是对ACAD图形数据库的最基本介绍,图形数据库知识是ARX程序设计的基础和核心,以后还要对此进行更为深入的解释。今天就先说这些了。下一篇文章将对以上两个例子进行逐语句的详细解释,并且讨论与之相关的一些内容。另外,还要简单地介绍VC6和的ARX程序不同之处。