第二章 AutoCAD数据库入门
AutoCAD数据库中存储了组成AutoCAD图形的对象和实体。本章讨论数据库的关键元素:实体,符号表和命名对象字典。
这一章也会介绍对象ID和打开数据库对象的接口。还会给出创建实体、层和组及向数据库加入对象的例子。
AutoCAD数据库概览
AutoCAD图形是存储在为数据库中的对象集合。数据库对象的基类是实体、符号表和字典。实体是AutoCAD图形中具有图形界面的一种特殊的数据库对象。直线、圆、文本、solid、面域、椭圆等就是实体。换句话说,实体就是用户可以在屏幕上看到并且可以操作的东西。
符号表和字典是用来存储数据库对象的容器。这些容器对象把符号名(一个字符串)映射成一个数据库对象。每个AutoCAD数据库都包括一系列固定的符号表,每个符号表包括一种特定类型的符号表记录的实例。你不能在数据库中加入新的符号表。符号表的例子包括:层表(LayerTable,包含层表记录),块表(BlockTable,包括块表记录)。所有的AutoCAD实体都属于块表记录。
字典提供了比符号表更通用的存储对象的容器。字典可以包含DBObject类(就是实体类的基类)或它的派生类的对象。当创建一个新的AutoCAD图形时,AutoCAD数据库会创建一个名为命名对象字典的字典。你可以在命名对象字典中创建新的字典,然后在创建的字典中加入新的数据库对象。
下图展示了AutoCAD数据库中的主要元素。
在AutoCAD编辑的过程中,你可以通过调用语句来获取当前图形所在的数据库:
Application.DocumentManager.MdiActiveDocument.Database
或者HostApplicationServices.WorkingDatabase
多个数据库
在一个AutoCAD进程中可以载入多个数据库。进程中的每个对象都有一个句柄和对象ID。句柄唯一标识了一个数据库中的对象,对象ID唯一标识了所有数据库中的对象。对象ID只存在于一次编辑进程中,而句柄则和图形文件一起保存。和对象ID不同的是,当多个数据库被载入到AutoCAD进程中时,句柄不一定会唯一。
获得对象ID
有了对象ID,你可以对实际的数据库对象进行操作。
你可以通过不同的方法来获得对象ID:
l 创建一个对象并加入到数据库中。数据库会给加入的对象分配一个ID,你可以通过访问对象的OjectID属性来获得分配的ID。
l 使用数据库接口来获得对象ID,这些对象都是在数据库创建的时候被自动创建的(例如九个固定的符号表和命名对象字典)。
l 使用特定类的接口来获得对象ID。特定类(如符号表和字典)定义的对象会包含其它的对象。这些类提供了获得包含的对象的ID的接口。
l 查询一个选择集。用户选择后,可以通过查询选择集来获取选中的对象ID列表。
基本的数据库对象
在AutoCAD中创建的对象都会被加入到适合它们的容器对象中。实体被加入到块表的记录中。符号表记录被加入到对应的符号表。实体和符号表之外的其它对象被加入到命名对象字典、被其它对象拥有的对象(其实这些对象最终还是被命名对象字典所拥有)或扩展的字典中。
数据库必须至少拥有以下的对象才可用:
l 包括块表、层表和线型表在内的九个符号表。块表最初包含三个记录:MODEL_SPACE,两个图纸空间记录(PAPER_SPACE,PAPER_SPACE0)。这三个块表记录表示模型空间和两个系统预定义的图纸空间布局。层表最初只包含一个记录0层。线型表最初只包含CONTINUOUS线型。
l 一个命名对象字典。当一个数据库创建后,这个字典就包含了以下四个数据库字典:组字典、多线样式字典、布局字典和打印样式命名字典。在多线样式字典中,STANDARD样式总是存在的。
当你给Database类的构造函数的buildDefaultDrawing参数传递true时,上面介绍的这些对象会被自动创建。如果传递false,则会创建一个可以载入DWG或DXF文件的空数据库。
在AutoCAD中创建对象
这一部分向大家介绍在AutoCAD中创建直线、圆、层和组,并展示AutoCAD是怎样把这些对象加入到数据库中的。首先,假定用户使用下列命令在模型空间中创建了一条直线:
line 4,2 10,7
在数据库中,AutoCAD先创建了一个Line类的实例,然后把它存储在模型空间块表记录中,如下图所示:
当你首次启动AutoCAD时,数据库处于缺省状态,实体被加入到模型空间,它是AutoCAD的主空间,被用于模型几何体和图形。图纸空间是用来支持“文档”几何体和图形的。生成实体的命令(LINE,对应于这个例子)把实体加入到当前的数据库中,并把它加入到模型空间块中。你可以查询实体所属的数据库和块。
接下来,假定用户用下面的命令创建了一个圆:
circle 9,3 2
同样地,AutoCAD创建了对应实体(这次是Circle)的实例,然后把它加入到模型空间块表记录中。
接下来,用户创建了一个新层:
layer _make mylayer
AutoCAD创建了一个新的层表记录来表示这个层,然后把这个记录加入到层表中。
最后,用户把所有的实体组合在一起。
group 3,2 9,3
AutoCAD创建一个新的组对象,然后把它加入到组字典中,组字典包含在命名对象字典中。这个新的组包括组成这个组的对象的ID。
在ObjectARX中创建对象
这部分的ObjectARX代码示例向你演示如何创建一些AutoCAD实体(直线和圆)、创建一个新层、改变直线的颜色、加入一个组到组字典中。
创建实体
下面的CreateLine()函数创建一条直线并把它加入到模型空间块表记录中:
public void CreateLine()
{
Point3d startPoint=new Point3d(4,2,0);
Point3d endPoint=new Point3d(10,7,0);
Lines line=new Lines(startPoint,endPoint);
Database db= Application.DocumentManager.MdiActiveDocument.Database;
ObjectId btID=db.BlockTableId;
BlockTable bt=(BlockTable)btID.Open(OpenMode.ForRead);
ObjectId btrID=bt[BlockTableRecord.ModelSpace];
BlockTableRecord btr=(BlockTableRecord)btrID.Open(OpenMode.ForWrite);
bt.Close();
btr.AppendEntity(line);
btr.Close();
line.Close();
}
CreateLine()首先获取当前图形的块表,然后打开模型空间块表记录用于写入。关闭块表后,向块表记录中加入实体,最后关闭块表记录和实体。
注意:当你使用完ObjectARX对象后,你必须尽快地显式关闭它们。呵呵,就好像要大家节约用水一样,用完水以后要记得关上水龙头。不过你可能注意到在你编译这个程序的时候,Visual Studio.net提示你最好用transaction来代替Open()和Close()函数。使用transaction的好处是你不用再手动编写关闭ObjectARX对象的代码,因为系统已经自动帮你做好了(呵呵,这就好像可以自动关闭的水龙头)。
下面是使用transaction的例子。
public void CreateLine()
{
Point3d startPoint=new Point3d(4,2,0);
Point3d endPoint=new Point3d(10,7,0);
Line line=new Line(startPoint,endPoint);
Database db= Application.DocumentManager.MdiActiveDocument.Database;
DBTransMan tm=db.TransactionManager;
using(Transaction trans=tm.StartTransaction())
{
BlockTable bt=(BlockTable)tm.GetObject(db.BlockTableId,OpenMode::ForRead,true);
BlockTableRecord btr=(BlockTableRecord) tm.GetObject(bt[BlockTableRecord.ModelSpace],OpenMode::ForWrite,true);
btr.AppendEntity(line);
tm.AddNewlyCreatedDBObject(line,true);
trans.Commit();
}
}
在以后的例子,我都会用transaction来写相关的代码。
下面的CreateCircle()函数创建一个圆并把它加入到模型空间块表记录中:
public void CreateCircle()
{
Point3d center=new Point3d(9.0,3.0,0.0);
Vector3d normal=new Vector3d(0.0,0.0,1.0);
Circle circle=new Circle(center,normal,2.0);
Database db= Application.DocumentManager.MdiActiveDocument.Database;
DBTransMan tm=db.TransactionManager;
using(Transaction trans=tm.StartTransaction())
{
BlockTable bt=(BlockTable)tm.GetObject(db.BlockTableId,OpenMode::ForRead,true);
BlockTableRecord btr=(BlockTableRecord) tm.GetObject(bt[BlockTableRecord.ModelSpace],OpenMode::ForWrite,true);
btr.AppendEntity(circle);
tm.AddNewlyCreatedDBObject(circle,true);
trans.Commit();
}
}
下面的代码演示了如何从数据库中获得层表,创建一个新的层表记录,命名这个记录(ASDK_MYLAYER)。层表记录最后被加入到层表中。
public void CreateNewLayer()
{
Database db= Application.DocumentManager.MdiActiveDocument.Database;
DBTransMan tm=db.TransactionManager;
using(Transaction trans=tm.StartTransaction())
{
LayerTable lt=( LayerTable)tm.GetObject(db.LayerTableId,OpenMode::ForWrite,true);
LayerTableRecord ltr=new LayerTableRecord();
ltr.Name="ASDK_MYLAYER";
lt.Add(ltr);
tm.AddNewlyCreatedDBObject(ltr,true);
trans.Commit();
}
}
打开ObjectARX对象
这部分的代码向你讲述当你处理数据库驻留对象时,你必须遵守的打开和关闭对象的规则。这个规则会保证当需要访问对象时它们会在内存中,当不需要它们的时候则被记录到磁盘。在你修改一个对象之前,你必须像下面的例子一样打开它:
tm.GetObject(objId,OpenMode::ForWrite,true);
OpenMode是一个枚举类型,它表示你打开对象是用来读(ForRead)、写(ForWrite)或通知(ForNotify)。如果打开对象是用来写的话,那么你可以修改它。
一个新生成的对象实例被认为是打开用来写的。一个对象只有被加入到数据库后才能关闭。你可以在对象被加入到数据库之前自由地删除它。但如果对象已被加入到数据库后,你就不能直接删除它。你可以调用DBObject的Erase()函数来擦除它。被擦除的对象仍然会保留在数据库中直到数据库被销毁为止,但当AutoCAD图形被保存时,它不会被保存。
警告!如果直接删除已加入到数据库中的对象,那么会导致AutoCAD终止。
在组字典中加入一个组
下面的代码使用CreateLine()函数和CreateCircle()函数创建的直线和圆来创建一个组,然后把这个组加入到组字典中。直线和圆的ID被当作参数传递到函数中。请注意组字典是如何打开用于写、修改。
public void CreateGroup(ObjectIdCollection objIds,string groupName)
{
Group group=new Group(groupName,true);
group.Append(objIds);
Database db= Application.DocumentManager.MdiActiveDocument.Database;
DBTransMan tm=db.TransactionManager;
using(Transaction trans=tm.StartTransaction())
{
DBDictionary groupDict =
(DBDictionary)tm.GetObject(db.GroupDictionaryId,OpenMode::ForWrite,true);
groupDict.SetAt(groupName,group);
tm.AddNewlyCreatedDBObject(groupp,true);
trans.Commit();
}
} |