AutoCAD图形是存储在数据库中对象的集合。符号表和字典是用来存储数据库对象的容器对象,这两种容器对象都可以将一个符号名映射到一个数据库对象。
符号表举例:层表AcDbLayerTable 块表AcDbBlockTable 线性表
块表记录AcDbBlockTableRecord 块表引用AcDbBlockTableReference
字典提供了一个比符号表更加通用的容器对象来存储。一个字典可以包含任何AcDbObject类和子类对象。
acdbHostApplicationServices()->workingDatabase() 获取当前图形的数据库
AutoCAD中对象ID与句柄的区别:
对象的ID是在编辑过程中用来识别不同对象(概念上对象包含实体),而在最终存储至数据库中时,采用句柄来标示相应的对象。
即从数据库中提取或存储对象时,才会使用或产生句柄。而在AutoCAD程序中操作对象时,使用的大多为对象ID。
所以,对象ID在一个应用程序中是唯一标示一个实体,而在应用程序连接的数据库中,不同的实体分别存储到不同数据库中时,可能会用到相同句柄。
获取对象ID的方法:
1. 可在创建对象实体并写入数据库的过程中获取对象ID
2. 可以用迭代器遍历容器和对象列表获取对象ID。AcDbDictionaryIterator和AcDbObjectIterator.
3个块表记录:模型空间记录(MODEL_SPACE)和两种图形空间记录(PARER_SPACE,PARER_SPACE0)。层表最初只包含一个记录:0层记录。线性表最初记录:CONTINUOUS记录
1.命名对象字典:组词典(GROUP DICTIONARY)、多线样式词典(MLINE style dictionary)、布局辞典(layout dictionary)和打印样式词典(plot style dictionary)
2.当AcDbDatabase类构造函数中,buildDefaultDrawing为kTrue时,可以再新的AutoCAD数据库中构造以上对象,打开DWG和DXF文件时应该设置为kFalse。
获取当前图形数据库的块表:acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable,AcDb::kForRead);
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable, AcDb::kForRead); //获取可读的块表对象
3. 打开模型空间的块表记录:
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
成功返回Acad::eOk
4.将实体加入到块表记录:
Acad::ErrorStatus es = pBlockTableRecord->appendAcDbEntity(entId,pEnt);
5.创建新层:
AcDbLayerTable *pLayerTable;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pLaterTable,AcDB::kForWrite);
AcDbLayerTableRecord *pLayerTableRecord = newAcDbLayerTableRecord;
pLayerTableRecord->setName(“MYNEWLAYER”);
AcDbObjectId pLayerId;
pLayerTable->add(pLayerId,pLayerTableRecord);pLayerTable->close();
pLayerTableRecord->close();
6. 创建新层
AcDbLayerTable *pLayerTable;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pLaterTable,AcDB::kForWrite);
AcDbLayerTableRecord *pLayerTableRecord = new AcDbLayerTableRecord;
pLayerTableRecord->setName(“MYNEWLAYER”);
AcDbObjectId pLayerId;
pLayerTable->add(pLayerId,pLayerTableRecord);
pLayerTable->close();
pLayerTableRecord->close();
return pLayerId;
7. 打开ObjectARX对象:acdbOpenObject(AcDbObject*& pObject, AcDbObjectId, AcDb::OpenMode)
8. AcDbDatabase::getAcDbObjectId(AcDbObjectId&retId,Adesk::Boolean createIfNotFound,const AcDbHandle& objHandle, Adesk::UInt32 xRefId=0);
9. AcDbObject的成员函数void getAcDbHandle(AcDbHandle& handle) const ,若对象没有加入数据库则没有句柄,可以用AcDbHandle::isNull来检查
10. 对象在加入数据库之前,随时可以用delete()函数删除。但是加入之后需要用erase将对象表示为擦除,但是数据库中仍存在。但在存盘时会被析构。
Erase(Ktrue)删除对象 erase(Kfalse) 恢复对象。但是数据库对象被删除后无法通过该方式恢复,需要重新setAt。若为实体对象,则可以恢复。
ads_name数据类型相当于AcdbObjectId.
AcDb库提供以下函数进行相互之间的转换:
extern Acad::ErrorStatus acdbGetAdsName(ads_name& objName,AcDbObjectId objId);
extern Acad::ErrorStatus acdbGetObjectId(AcDbObjectId& objId,const ads_name objName);
通过对象句柄来获得ads_name:
Int acdbHandEnt(const char* handle, ads_name entres);
11. 加入新组
createNewGroup(AcDbObjectIdArray& objIds, char* pGroupName, AcDbObjectId pLayerID)
{
AcDbGroup *pGroup = new AcDbGroup(pGroupName);
For(int I = 0; I < objIds.length();I++)
{
pGroup->append(objIds[I]);
}
AcDbDictionary *pGroupDict;
acdbHostApplicationServices()->workingDatabase()->getGroupDictionary(pGroupDict,AcDb::kForWrite);
AcDbObjectId pGroupId;
pGroupDict->setAt(pGroupName,pGroup,pGroupId);
pGroup->setLayer(pLayerId);
pGroupDict->close();
pGroup->close();
}
return pLayerId;
对象ID于句柄之间的转换
AcDbDatabase::getAcDbObjectId(AcDbObjectId&retId,Adesk::BooleancreateIfNotFound,const AcDbHandle& objHandle, Adesk::UInt32 xRefId=0);
打开ObjectARX对象:acdbOpenObject(AcDbObject*& pObject, AcDbObjectId,AcDb::OpenMode)
AcDbObject的成员函数voidgetAcDbHandle(AcDbHandle& handle) const ,若对象没有加入数据库则没有句柄,可以用AcDbHandle::isNull来检查
对象在加入数据库之前,随时可以用delete()函数删除。但是加入之后需要用erase将对象表示为擦除,但是数据库中仍存在。但在存盘时会被析构。
Erase(Ktrue)删除对象 erase(Kfalse)恢复对象。但是数据库对象被删除后无法通过该方式恢复,需要重新setAt。若为实体对象,则可以恢复
ads_name数据类型相当于AcdbObjectId.
AcDb库提供以下函数进行相互之间的转换:
extern Acad::ErrorStatus acdbGetAdsName(ads_name&objName,AcDbObjectId objId);
extern Acad::ErrorStatus acdbGetObjectId(AcDbObjectId&objId,const ads_name objName);
通过对象句柄来获得ads_name:
Int acdbHandEnt(const char* handle, ads_name entres);
加入新组
createNewGroup(AcDbObjectIdArray&objIds, char* pGroupName, AcDbObjectId pLayerID)
{
AcDbGroup *pGroup = new AcDbGroup(pGroupName);
For(int I = 0; I < objIds.length();I++)
{
pGroup->append(objIds[I]);
}
AcDbDictionary *pGroupDict;
acdbHostApplicationServices()->workingDatabase()->getGroupDictionary(pGroupDict,AcDb::kForWrite);
AcDbObjectId pGroupId;
pGroupDict->setAt(pGroupName,pGroup,pGroupId);
pGroup->setLayer(pLayerId);
pGroupDict->close();
pGroup->close();
}
如果实体对象创建失败,返回值为NULL,return Acad::eOutOfMemory
当前数据库块表打开失败,返回值非Acad::eOk,关闭相应数据库表,并记录Acad::ErrorStatus es2对象,acrx_abort(“XXX”,acadErrorStatusText(es2))报出错误,删除相应对象。
如何辨析AutoCAD中数据库不同表之间的关系?
首先我们要明确的是AutoCAD数据库中不同表之间,甚至表与记录之间的关系都是平等的。并不是从表面上看到的包含关系。
初学者往往由于先要从当前主数据库中获取块表,然后通过块表来获得块记录,然后在块记录中存入或取出实体,认为这是包含关系。
但是事实上类似于块记录拥有一个存储多个实体对象ID的数组,块表与表记录之间大多都类似于这种关联关系。
所以,为了避免忘记,常常可以找到表记录时,就可以将不需要使用的表关闭。