ARX帮助文档:数据库对象

英语比较烂,借着翻译帮助文档,一边学习英语,一边加强专业知识,有翻译的不妥的地方,欢迎评论区指正,谢谢各位看官赏脸

arxdev.chm帮助文档:ObjectARX库为AutoCAD 2010提供的开发指南

第一章:ObjectARX 介绍性的概念

第五节:数据库对象

本章节描述的主题涉及所有的AutoCAD数据库对象,包括实体、符号表记录和字典项;主要概念包括打开/关闭对象、管理内存中的对象、对象权限和使用扩展数据或对象的扩展字典扩展一个对象。对象的其他常见操作,还讨论了移除和文件读取问题。

本小节内容:

1.打开关闭数据库对象

2.删除对象

3.数据库对象的所有权

4.添加特定的数据到对象

5.移除对象

6.对象文件读取

7.嵌入和封装对象

(1)打开/关闭数据库对象

每个AcDbObject对象可以用三种不同的方式来用:

1.句柄

2.对象id

3.c++实例指针

当AutoCAD没有运行的时候,图像是存储在文件系统中的。DWG文件中包含的对象通过他们的句柄来标识。图像打开之后,可以通过AcDbDatabase 对象访问图像信息。每个对象在数据库中都有一个对象id,该id在当前编辑的对话框中,从创建到删除都始终存在于该对象的AcDbDatabase中。open()函数将对象ID作为参数,并返回一个指向AcDbObject对象的指针。这个指针在对象关闭之前都是有效的,如下图所示:

1.你可以使用全局函数acdbOpenObject() 打开一个对象

2.你可以使用函数getAcDbObjectId()将句柄映射到对象id

3.你也可以打开一个对象,然后获得它的句柄

AcDbObject* pObject;
AcDbHandle handle;
pObject->getAcDbHandle(handle);

注:每当打开数据库对象时,应该尽早关闭它,用AcDbObject::close()函数关闭数据库对象。

ads_name等价于AcDbObjectId。AcDb库提供了两个独立的函数,允许你在AcDbObjectId和ads_name之间进行转换:

// 通过AcDbObjectId 返回一个ads_name
acdbGetAdsName(ads_name& objName, AcDbObjectId objId); 

// 通过ads_name返回一个AcDbObjectId 
acdbGetObjectId(AcDbObjectId& objId, ads_name objName); 

通常,你通过选择获得一个对象,然后它以ads_name形式返回,此时你需要把ads_name转换成AcDbObjectId,并打开AcDbObjectId。下面的函数演示了这个过程:

AcDbEntity*selectEntity(AcDbObjectId& eId, AcDb::OpenMode openMode)
{
 ads_name en;
 ads_point pt;
 acedEntSel("\n请选择一个实体: ", en, pt);

 acdbGetObjectId(eId, en);

 AcDbEntity * pEnt;
 acdbOpenObject(pEnt, eId, openMode);

 return pEnt;
}

你可以在以下三种权限中打开一个对象:

1.kForRead:只要对象还没有通知以写的权限被打开,就可以被多达256个读者打开一个对象。

2.kForWrite:如果对象尚未打开,则可以打开该对象。否则,打开失败。

3.kForNotify:当对象关闭、 以读的权限打开或以写的权限打开时,可以通知打开一个对象,但当该对象已经通知被打开时则不能打开。请参见Notification (第四章:第二节:通知),它很少需要通知打开一个对象并通知发送

下表显示了一个对象已经打开后,在尝试以不同权限打开对象时所返回的错误信息:

如果你试图以写的权限打开一个对象,然后得到一个错误eWasOpenForRead,只有一个读者时,可以使用upgradeOpen()来升级打开状态,也可以使用downgradeOpen()来降低其读取的状态。同理,如果你通知打开对象,例如,当您接收通知,您想要以写的权限打开时,您可以使用upgradeFromNotify()来升级它的打开状态。或者使用downgradeToNotify()降低其状态。

有关如何管理打开和关闭对象的复杂顺序的更多信息,请参见Transaction Manager(第四章:第四节:事务管理器)

(2)删除对象

当你创建一个用于将 AcDbObject对象添加到数据库的实例时,使用AcDbObject::new()函数。当一个对象首先被创建并且还没有被添加到数据库时,你可以删除他,然而,一旦一个对象被加到数据库,你就不能删除他;AutoCAD管理删除所有数据库内的对象。

(3)数据库对象所有者

根对象:一个由数据库隐式拥有的对象(而不是另一个数据库对象)。数据库包含10个根对象:九个符号表和命名的对象字典。所有的文件读取操作都是通过对数据库的根对象进行文件读取来开始的。看Object Filing(对象文件读取)

除了根对象外,数据库中的每个对象都必须有一个所有者,并且只能有一个所有者。数据库创建的对象像一个有层次结构的树。下面的调用将对象添加到数据库,并为其分配一个ID,但是该对象还没有所有者:

db->addAcDbObject(...);

通常,您可以使用一个成员函数AcDbBlockTableRecord::appendAcDbEntity()将对象添加到它的所有者,同时将其添加到数据库中,他同时执行俩个任务。

AutoCAD的所有权关系如下:

1.块表记录自己的实体

2.符号表记录每个特定类型的符号

3.AcDbDictionary对象可以拥有任何AcDbObject对象

4.任何AcDbObject对象都可以有一个扩展字典;

另外,应用程序可以建立自己的所有权连接。

(4) 添加特定的数据到对象

你可以任意使用四种机制来在应用程序中添加实例特定的数据:

1.扩展数据

2.扩展记录(看Container Objects:第一章:第七节:容器对象)

3.任何对象的扩展字典

4.自定义对象也可以保存实体

本小节内容:

1.扩展数据

2.扩展字典

(4.1)扩展数据

扩展数据是由应用程序用ObjectARX®或AutoLISP®编写的,可以添加到任何对象。应用程序使用由resbufs链表组成的扩展数据。(不是使用AutoCAD维护信息)。扩展数据的DXF组代码在1000到1071的范围内相关联。

此机制具有空间效率,可用于将轻量级数据添加到对象中。所以,扩展数据必须小于16K,或者是现有的DXF组代码和类型集。

有关扩展数据的详细描述,请参阅AutoCAD DXF引用。

使用AcDbObject::xData()函数,获取包含对象的扩展数据的resbuf链:

virtual resbuf* AcDbObject::xData(const char* regappName = NULL) const;

使用AcDbObject::setXData()函数来设置对象的扩展数据:

virtual Acad::ErrorStatus AcDbObject::setXData(const resbuf* xdata);

下面的例子使用xData()函数获取所选对象的扩展数据,并将扩展数据打印到屏幕上。然后向xdata添加一个字符串(testrun),并调用setXdata()函数来修改对象的xdata。这个示例也说明了upgradeOpen()和downgradeOpen()函数的用法。

// selectObject()函数允许用户选择一个对象,然后为对象增加扩展数据,并且用printList()函数发送列表的类型和resval值
void printXdata()
{
 //选择并且打开一个对象
 AcDbObject *pObj = selectObject(AcDb::kForRead);
 if (pObj == NULL)
     return;

 //获取扩展数据名称。
 char appname[133];
 if (acedGetString(NULL, "\n请输入所需扩展数据的扩展数据名称: ",appname) != RTNORM)
     return;

 // 获取扩展数据名称的扩展数据。
 struct resbuf *pRb = NULL;
 pRb = pObj->xData(appname);
 if (pRb != NULL) 
{
 //如果有扩展数据的话,打印扩展数据。
 // Notice that there is no -3 group, as there is in
 // LISP. This is ONLY the xdata, so
 // the -3 xdata-start marker isn't needed.
 // 
 printList(pRb);
 acutRelRb(pRb);
 }
 else
 {
 acutPrintf("\n这个扩展数据名称没有扩展数据");
 }
 pObj->close();
}

void addXdata() 
{
 AcDbObject* pObj = selectObject(AcDb::kForRead);
 if (!pObj) 
{
 acutPrintf("选择对象错误!\n");
 return;
 }

 // 获取扩展数据名称,并且添加扩展数据
 char appName[132], resString[200];
 appName[0] = resString[0] = '\0';
 acedGetString(NULL, "请输入扩展数据名称: ",appName);
 acedGetString(NULL, "请输入要添加的字符串: ",resString);

 struct  resbuf  *pRb, *pTemp;
 pRb = pObj->xData(appName);
 if (pRb != NULL) {
 // 如果存在扩展数据,则找到列表最后。
 for (pTemp = pRb; pTemp->rbnext != NULL;
 pTemp = pTemp->rbnext)
 { ; }
 } 
else 
{
 // 如果没有扩展数据, 注册扩展数据名称并且在resbuf 链表的开头添加扩展数据名称
 // Notice that there is no -3 group as there is in
 // AutoLISP. This is ONLY the xdata so
 // the -3 xdata-start marker isn't needed.
 acdbRegApp(appName);
 pRb = acutNewRb(AcDb::kDxfRegAppName);
 pTemp = pRb;
 pTemp->resval.rstring = (char*) malloc(strlen(appName) + 1);
 strcpy(pTemp->resval.rstring, appName);
 }

 // 添加用户指定字符串到扩展数据
 pTemp->rbnext = acutNewRb(AcDb::kDxfXdAsciiString);
 pTemp = pTemp->rbnext;
 pTemp->resval.rstring = (char*) malloc(strlen(resString) + 1);
 strcpy(pTemp->resval.rstring, resString);

 //下面的代码显示了upgradeOpen()函数将实体由读改为写
 pObj->upgradeOpen();
 pObj->setXData(pRb);

 pObj->close();
 acutRelRb(pRb);
}

(4.2)扩展字典

每个对象都可以有一个扩展字典,可以包含任意一组AcDbObject对象。使用这种机制, 多个应用程序可以将数据附加到同一个对象。 扩展字典比扩展数据需要更多的开销,但它也为添加数据提供了一种更灵活,更高效的机制。

例如,使用扩展字典将任意字符串附加到任何AcDbObject,查看ObjectARX示例\数据库\ dataxtsn目录中的edinvent 程序。

本小节内容:

1.ObjectARX扩展字典示例

2.全局函数扩展字典示例

(4.2.1)ObjectARX扩展字典示例

下面这个例子演示,实例化一个扩展记录,并且将它添加到命名对象字典中的扩展字典:

void createXrecord()
{
 AcDbXrecord *pXrec = new AcDbXrecord;
 AcDbObject *pObj = NULL;
 AcDbObjectId dictObjId, xrecObjId;
 AcDbDictionary* pDict = NULL;

 pObj = selectObject(AcDb::kForWrite);
 if (pObj == NULL)
     return;

 // 创建一个对象的扩展字典时,如果扩展字典已经存在时,将是一个空操作
 pObj->createExtensionDictionary();

 // 通过扩展字典得到当前选择对象的对象id
 dictObjId = pObj->extensionDictionary();
 pObj->close();

 // 打开扩展字典,并且添加一个扩展记录
 acdbOpenObject(pDict, dictObjId, AcDb::kForWrite);
 pDict->setAt("ASDK_XREC1", pXrec, xrecObjId);
 pDict->close();

 //创建一个resbuf列表,并且把扩展记录加进去
 struct resbuf* head = NULL;
 ads_point testpt = {1.0, 2.0, 0.0};
 head = acutBuildList(AcDb::kDxfText,"测试字符串",
 AcDb::kDxfXCoord, testpt,
 AcDb::kDxfReal, 3.14159,
 AcDb::kDxfAngle, 3.14159,
 AcDb::kDxfColor, 1,
 AcDb::kDxfInt16, 180,
 0);

 //添加数据到扩展记录.通知成员函数引用resbuf而不是指针,所以在发送之前先释放指针  
 pXrec->setFromRbChain(*head);
 pXrec->close();
 acutRelRb(head);
}

//listXrecord()函数获得扩展记录与key值ASDK_XREC1的记录,并且通过resbuf向printList()列出了内容
void listXrecord()
{
 AcDbObject *pObj = NULL;
 AcDbXrecord *pXrec = NULL;
 AcDbObjectId dictObjId;
 AcDbDictionary *pDict = NULL;
 pObj = selectObject(AcDb::kForRead);
 if (pObj == NULL)
    return;

 //通过对象字典获得对象id
 dictObjId = pObj->extensionDictionary();
 pObj->close();

 //打开对象字典,并且获得key值为 ASDK_XREC1的扩展记录
 acdbOpenObject(pDict, dictObjId, AcDb::kForRead);
 pDict->getAt("ASDK_XREC1", (AcDbObject*&)pXrec, AcDb::kForRead);
 pDict->close();

 //得到扩展记录的数据,并且关闭扩展记录
 struct resbuf *pRbList = NULL;
 pXrec->rbChain(&pRbList);
 pXrec->close();

 printList(pRbList);
 acutRelRb(pRbList);
}

(4.2.2)全局函数扩展字典示例

下面这个例子,用ObjectARX全局函数创建扩展记录,并且将其添加到key值为ASDK_REC相关联的字典中。

int createXrecord()
{
 struct resbuf *pXrec, *pEnt, *pDict, *pTemp, *pTemp2;
 ads_point dummy, testpt = {1.0, 2.0, 0.0};
 ads_name xrecname, ename, extDict = {0L, 0L};

 // 让用户选择一个实体。然后得到数据。
 if (acedEntSel("\n选择实体: ", ename, dummy) != RTNORM)
 {
 acutPrintf("\n没有选中");
 acedRetVoid();
 return RTNORM;
 }

 pEnt = acdbEntGet(ename);

 // 检查实体是否有扩展字典
 for (pTemp = pEnt; pTemp->rbnext != NULL;
 pTemp = pTemp->rbnext)
 {
 if (pTemp->restype == 102)
 {
 if (!strcmp("{ACAD_XDICTIONARY",pTemp->resval.rstring))
 {
 ads_name_set(pTemp->rbnext->resval.rlname, extDict);
 break;
 }
 }
 }

 // 如果没有扩展字典,添加一个
 if (extDict[0] == 0L) 
{
 pDict = acutBuildList(RTDXF0, "DICTIONARY", 100,"AcDbDictionary", 0);
 acdbEntMakeX(pDict, extDict);
 acutRelRb(pDict);

 pDict = acutBuildList(102, "{ACAD_XDICTIONARY", 360,extDict, 102, "}", 0);

 for (pTemp = pEnt; pTemp->rbnext->restype != 100; pTemp = pTemp->rbnext)
 { ; }

 for (pTemp2 = pDict; pTemp2->rbnext != NULL;pTemp2 = pTemp2->rbnext)
 { ; }

 pTemp2->rbnext = pTemp->rbnext;
 pTemp->rbnext = pDict;
 acdbEntMod(pEnt);
 acutRelRb(pEnt);
 }

 // 有扩展字典后,创建resbuf 的扩展记录的实体信息和数据
 pXrec = acutBuildList(RTDXF0, "XRECORD",
 100, "AcDbXrecord",
 1, "测试字符串",                    //AcDb::kDxfText
 10, testpt,                       //AcDb::kDxfXCoord
 40, 3.14159,                      //AcDb::kDxfReal
 50, 3.14159,                      //AcDb::kDxfAngle
 60, 1,                            //AcDb::kDxfColor
 70, 180,                          //AcDb::kDxfInt16
 0);

 //创建没有所有者的扩展记录.扩展记录的新名称将被放入xrecname 
 acdbEntMakeX (pXrec, xrecname);
 acutRelRb (pXrec);

 //设置扩展记录的所有者为扩展字典
 acdbDictAdd(extDict, "ASDK_XRECADS", xrecname);
 acedRetVoid();
 return RTNORM;
}

//访问用户选择实体的扩展字典里,key值为ASDK_XRECADS的扩展记录,用printList()函数列出扩展数据的内容
int listXrecord()
{
 struct resbuf *pXrec, *pEnt, *pTemp;
 ads_point dummy;
 ads_name ename, extDict = {0L, 0L};

 //用户选中实体,然后得到他的数据
 if (acedEntSel("\n选择实体: ", ename, dummy) != RTNORM) 
{
 acutPrintf("\n没有选中");
 acedRetVoid();
 return RTNORM;
 }

 pEnt = acdbEntGet(ename);

 //得到扩展字典中实体的名称
 for (pTemp = pEnt;pTemp->rbnext != NULL;pTemp = pTemp->rbnext)
 {
 if (pTemp->restype == 102)
 {
 if (!strcmp("{ACAD_XDICTIONARY", pTemp->resval.rstring))
{
 ads_name_set(pTemp->rbnext->resval.rlname, extDict);
 break;
 }
 }
 }

 if (extDict[0] == 0L)
 {
 acutPrintf("\n现在没有扩展字典.");
 return RTNORM;
 }

 pXrec = acdbDictSearch(extDict, "ASDK_XRECADS", 0);
 if(pXrec) {
 printList(pXrec);
 acutRelRb(pXrec);
 }

 acedRetVoid();
 return RTNORM;
}

(5)移除对象

数据库中的任何对象都可以用以下函数删除:

Acad::ErrorStatus AcDbObject::erase(Adesk::Boolean Erasing = true);

注:erase()函数对数据库对象和实体有不同的结果,不清除他们的影响:

1.当数据库对象被清除时,与该对象相关的信息也被从字典中移除 ,如果该对象未被erase(kfalse)清除,他的信息不会重新引入,你必须使用setAt()函数重新将信息添加到字典中。

2.当一个实体被清除时,在块表记录中的标识被简单的移除。该实体可以被erase(kfalse)删除。

默认情况下,你不能用acdbOpenObject()函数打开一个已经被删除的对象,如果你试图这样做的话,他将返回一个eWasErased的错误。

extern Acad::ErrorStatus acdbOpenObject( AcDbObject*& obj,AcDbObjectId objId,AcDb::OpenMode openMode,Adesk::Boolean openErasedObject = Adesk::kFalse);

acdbOpenObject()函数的最后一个参数使用kTrue,打开一个已经被删除的对象。

比如多段线polylines和块表记录block table之类的容器对象通常在迭代它们的内容时提供跳过删除元素的选项。这就是跳过删除 默认行为原理。

删除的对象没有保存到DWG或DXF文件。

(6)对象文件读取

对象文件保存是指对象状态到单个数据序列之间的转换过程,用于将其存储在磁盘、复制或记录其状态以进行撤消操作。文件读取有时候也被叫做序列化。一个对象的文件保存是将一个序列数据返回到一个对象的过程,有时候也被称为反序列化。

在AutoCAD中,文件保存的的使用有几种情况:

1.编写和读取DWG文件(使用DWG格式)

2.编写和读取DXF文件(使用DXF格式)

3.在AutoCAD、AutoLISP和ObjectARX之间进行通信(使用DXF格式)

4.还原和撤销(使用DWG格式)

5.复制操作,如INSERT、XREF和COPY(使用DWG格式)

6.分页(使用DWG格式)

AcDbObject有俩个函数用于文件读取:dwgOut()和dxfOut(),并且还有俩个函数用于文件保存dwgIn() 和dxfIn().这些成员函数主要由AutoCAD调用;使用数据库的应用程序几乎从来没有明确地控制对象归档。然而,如果你的应用程序执行了新的数据库对象类,您需要更深入地了解对象归档。看Deriving from AcDbObject(第三章:第四节:AcDbObject的来源)

dwg -和dxf -前缀表示两种完全不同的数据格式,第一个通常用于写入DWG文件,第二个主要用于DXF文件和AutoLISP entget、entmake和entmod函数。这两种格式的主要区别是DWG 文件(将数据写入文件的对象),没有明确地标记数据。与此不同,DXF文件是将数据组代码与每个数据元素相关联的数据格式。看Deriving from AcDbObject(第三章:第四节:AcDbObject的来源)

(7) 嵌入和封装对象

有两种方法可以将对象嵌入到另一个对象中:封装对象有一个数据成员,它实际是一个嵌入对象,或者封装对象有指向对象的指针(在这种情况下,对象被认为是嵌入的)。不论发生何种情况,封装对象负责分配和释放嵌入的对象。封装对象还必须将所有调用的方法转发给嵌入对象,因为AutoCAD不知道嵌入对象。为了显示嵌入对象,封装对象的subWorldDraw()必须调用嵌入对象的worldDraw()。

对于subGetGripPoints()和subGetStretchPoints(),你必须调用嵌入对象的getGripPoints()和getStretchPoints()方法,以使点的索引值高于封装实体的索引。此外,用subMoveGripPointsAt()和subMoveStretchPointsAt()时,如果所传递的指数超过封装实体的范围,你需要减去封装实体的最高索引值,并将结果传递到嵌入对象的moveGripPointsAt()或moveStretchPointsAt()中。例如,以下代码来自于更新jblob示例中的,具有嵌入式的AcDbCircle实体:

Acad::ErrorStatus
Jblob::subGetGripPoints(
 AcGePoint3dArray& gripPoints,
 AcDbIntArray& osnapMasks,
 AcDbIntArray& geomIds) const
{
 assertReadEnabled();

 gripPoints.append(mp);
 gripPoints.append(mp + 0.5 * (mpblob - mp));
 gripPoints.append(mpblob);
 AcGeVector3d xoff(mrblob, 0, 0);
 AcGeVector3d yoff(0, mrblob, 0);
 gripPoints.append(mpblob + xoff);
 gripPoints.append(mpblob + yoff);
 gripPoints.append(mpblob - xoff);
 gripPoints.append(mpblob - yoff);

 return circle.getGripPoints(gripPoints, osnapMasks, geomIds);
}

Acad::ErrorStatus
Jblob::subMoveGripPointsAt(
 const AcDbIntArray& indices,
 const AcGeVector3d& offset)
{
 AcGePoint3d oldquad, newquad;

 assertWriteEnabled();

 AcDbIntArray circleIndices;
 for (int i = 0; i < indices.length(); i++) {
 int idx = indices[i];
 switch(idx) {
 case 0:
 mp += offset;
 continue; // stretch begin point
 case 1:
 mp += offset;
 mpblob += offset;
 continue; // move
 case 2:
 mpblob += offset;
 continue; // stretch blob center

 // stretch blob radius:
 //
 case 3:
 oldquad = mpblob + AcGeVector3d(mrblob, 0, 0);
 break;
 case 4:
 oldquad = mpblob + AcGeVector3d(0, mrblob, 0);
 break;
 case 5:
 oldquad = mpblob - AcGeVector3d(mrblob, 0, 0);
 break;
 case 6:
 oldquad = mpblob - AcGeVector3d(0, mrblob, 0);
 break;
 default:
 if (idx > 6)
 circleIndices.append(idx - 7);
 continue;
 }
 newquad = oldquad + offset;
 mrblob = newquad.distanceTo(mpblob);
 }
 if (circleIndices.length() > 0)
 return circle.moveGripPointsAt(circleIndices, offset);
 else
 return Acad::eOk;
}

对于目标文件保存,封装对象必须调用嵌入对象自己的这些方法dwgOutFields()、dwgInFields()、dxfOutFields()和dxfInFields()。

对于DWG文件,对嵌入对象的dwgOutFields()和dwgInFields()方法的调用可以在封装对象的对应方法的任何一点上发生(在调用基类的方法之后)。以下代码来自更新的jblob示例程序:

Acad::ErrorStatus
Jblob::dwgInFields(AcDbDwgFiler* filer)
{
 assertWriteEnabled();

 AcDbEntity::dwgInFields(filer);

 filer->readItem(&mp);
 filer->readItem(&mpblob);
 filer->readItem(&mrblob);
 filer->readItem(&mnormal);

 return circle.dwgInFields(filer);
}

Acad::ErrorStatus
Jblob::dwgOutFields(AcDbDwgFiler* filer) const
{
 assertReadEnabled();

 AcDbEntity::dwgOutFields(filer);

 filer->writeItem(mp);
 filer->writeItem(mpblob);
 filer->writeItem(mrblob);
 filer->writeItem(mnormal);

 return circle.dwgOutFields(filer);
}

对于DXF文件,嵌入的对象必须在封装对象的所有数据已经被文件保存和文件保存之后进行文件保存;因此,对嵌入对象的dxfOutFields()和dxfInFields()方法的调用应该在封装对象的dxfOutFields()和dxfInFields()方法中最后完成。在封装对象的数据和随后的嵌入对象的数据之间需要一个分隔符。分隔符必须与组的 0或100类似,所以它必须使过滤器停止读取数据。不能使用普通的DXF组代码0,因为DXF代理使用它来确定何时停止读取数据。组代码100可以被使用,但是当手动读取DXF文件时可能会引起混乱,并且需要区分什么时候嵌入的对象要被写出来以便做一些内部的记录。因此,引入了DXF组代码101。

DXF AcDb::DxfCode枚举值组代码101是AcDb::kDxfEmbeddedObjectStart。数据字符串嵌入对象是由过滤器为这个DXF组代码编写的。

在AcDbDxfFiler类中还添加了两个方法:

1.writeEmbeddedObjectStart()

2.atEmbeddedObjectStart()

下面的代码演示了如何在更新的jblob示例程序中使用这些方法:

Acad::ErrorStatus
Jblob::dxfInFields(AcDbDxfFiler* filer)
{
 assertWriteEnabled();

 struct resbuf rb;

 Acad::ErrorStatus es = AcDbEntity::dxfInFields(filer);

 if (es != Acad::eOk) {
 return es;
 }

 if (!filer->atSubclassData(kClassName)) {
 return Acad::eBadDxfSequence;
 }

 mnormal = AcGeVector3d(0, 0, 1); // set default value:

 while (es == Acad::eOk) {
 if ((es = filer->readItem(&rb)) == Acad::eOk) {
 switch(rb.restype) {
 case AcDb::kDxfXCoord:
 mp.set(rb.resval.rpoint[X], rb.resval.rpoint[Y],
 rb.resval.rpoint[Z]);
 break;
 case AcDb::kDxfXCoord+1:
 mpblob.set(rb.resval.rpoint[X], rb.resval.rpoint[Y],
 rb.resval.rpoint[Z]);
 break;
 case AcDb::kDxfReal:
 mrblob = rb.resval.rreal;
 break;
 case AcDb::kDxfNormalX:
 mnormal.set(rb.resval.rpoint[X], rb.resval.rpoint[Y],
 rb.resval.rpoint[Z]);
 }
 }
 }
 if (filer->atEmbeddedObjectStart())
 return circle.dxfInFields(filer);
 else {
 filer->setError(Acad::eMissingDxfField,
 "missing expected embeddedObject marker");
 return filer->filerStatus();
 }
}

Acad::ErrorStatus
Jblob::dxfOutFields(AcDbDxfFiler* filer) const
{
 assertReadEnabled();

 AcDbEntity::dxfOutFields(filer);

 filer->writeItem(AcDb::kDxfSubclass, kClassName);
 filer->writeItem(AcDb::kDxfXCoord, mp);
 filer->writeItem(AcDb::kDxfXCoord + 1, mpblob);
 filer->writeItem(AcDb::kDxfReal, mrblob);
 if (filer->includesDefaultValues()
 || mnormal != AcGeVector3d(0,0,1))
 {
 filer->writeItem(AcDb::kDxfNormalX, mnormal);
 }
 filer->writeEmbeddedObjectStart();
 return circle.dxfOutFields(filer);
}

下面的示例显示了DXF文件中的输出(与310组数据字符串缩短了可读性):

0
JBLOB
 5
52
330
19
100
AcDbEntity
 8
0
 92
 256
310
00010000040000003C0000000600000002000000...
310
000000000000000000000000000000F03F700000...
310
0000
100
Jblob
 10
4.026791
 20
3.172968
 30
0.0
 11
5.916743
 21
5.299622
 31
0.0
 40
1.458724
101
Embedded Object
100
AcDbEntity
100
AcDbCircle
 10
5.916743
 20
5.299622
 30
0.0
 40
0.729362

https://wenku.baidu.com/view/ea48c94769eae009581bec40.html

猜你喜欢

转载自my.oschina.net/u/2930533/blog/1591597