天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
楼主: admin1

ObjectArx块操作封装

[复制链接]
  • TA的每日心情
    开心
    7 天前
  • 签到天数: 49 天

    [LV.5]常住居民I

    185

    主题

    150

    回帖

    1695

    积分

    管理员

    积分
    1695
     楼主| 发表于 2024-5-4 11:02:07 | 显示全部楼层
    ObjectARX中如何选择块参照中的对象

    一、全局函数acedNEntSelP介绍
    为了选中块参照中的实体,ObjectARX提供了一个接口:
    int acedNEntSelP(
    const ACHAR * str,
    ads_name entres,
    ads_point ptres,
    int pickflag,
    ads_matrix xformres,
    struct resbuf ** refstkres
    );

    const ACHAR * str:在选择块参照中实体时的提示语,如果为NULL,AutoCAD 显示默认的提示语。
    ads_name entres:选择实体的ads_name名称。
    ads_point ptres:选择实体时点取的点。
    int pickflag:指定acedNEntSelP是否用于和用户交互;如果为假,acedNEntSelP提示用户指定实体并忽略ptres;如果为真,使用ptres的初始值去选择实体。
    ads_matrix xformres:该4×4变换矩阵可以将实体的任意ECS坐标转换为WCS坐标。如果选择的实体不是嵌套实体,该值设为单位矩阵。利用这个矩阵,可以将选中的实体从ECS坐标系转换到WCS坐标系。
    struct resbuf ** refstkres :包含嵌套实体的各级块参照。
    注意,最后一个参数最为重要,它实际记录了选择对象的各级嵌套块参照。

    二、实现方法介绍
    利用acedNEntSelP参数中最后的链表参数,查看选择对象的各级嵌套块参照,并对块参照进行坐标变换,将其坐标转为当前图形的WCS坐标。
    1. BOOL SelectEntsFromBlock(CString csPrompt, PickSet &ssResult,AcGePoint3d& ptBase)
    2. {
    3.         ads_name ent;
    4.         ads_point pt;
    5.         ads_matrix mat;
    6.         struct resbuf* pHead = NULL;
    7.         int iRet = acedNEntSelP(csPrompt, ent, pt, FALSE, mat, &pHead);

    8.         ads_name entOuterBlock;
    9.         if (iRet == RTNORM)
    10.         {
    11.                 if (!pHead)
    12.                 {
    13.                         acutPrintf(_T("这并不是一个块参照中的对象"));
    14.                         return FALSE;
    15.                 }

    16.                 ptBase.x = pt[0];
    17.                 ptBase.y = pt[1];
    18.                 ptBase.z = pt[2];

    19.                 //如果ent为块参照中的嵌套块参照对象,例如块参照A嵌套块参照B,块参照B嵌套块参照C,
    20.                 //用户点取了嵌套块C的某个实体,以下循环可以将ent修改为块参照B;并且获得最外层的块参照的ads_name
    21.                 while (pHead && pHead->restype == RTENAME)
    22.                 {
    23.                         if (pHead && !pHead->rbnext)        //如果点取的是块参照中的非嵌套对象
    24.                         {
    25.                                 ads_name_set(pHead->resval.rlname, entOuterBlock);
    26.                                 break;
    27.                         }
    28.                         else if (pHead->rbnext && !pHead->rbnext->rbnext)        //如果点取的是块参照的嵌套对象
    29.                         {
    30.                                 ads_name_set(pHead->resval.rlname, ent);
    31.                                 ads_name_set(pHead->rbnext->resval.rlname, entOuterBlock);
    32.                                 break;
    33.                         }
    34.                         pHead = pHead->rbnext;
    35.                 }

    36.                 //求解块参照的变换矩阵
    37.                 AcGeMatrix3d matBlockRef;
    38.                 AcDbObjectId id;
    39.                 acdbGetObjectId(id, entOuterBlock);                //获取最外层块参照的ID
    40.                 AcDbBlockReference* pOuterBlockRef = NULL;
    41.                 if (Acad::eOk == acdbOpenObject(pOuterBlockRef, id, AcDb::kForRead))
    42.                 {
    43.                         if (pOuterBlockRef)
    44.                         {
    45.                                 //获取转换矩阵,从块表记录中的MCS坐标转为当前图形的WCS坐标
    46.                                 matBlockRef = pOuterBlockRef->blockTransform();
    47.                         }
    48.                         pOuterBlockRef->close();
    49.                 }
    50.                
    51.                 acdbGetObjectId(id, ent);        //获取用户选中实体的ID
    52.                 AcDbEntity* pEnt = NULL;
    53.                 AcDbEntity* pEntClone = NULL;
    54.                 if (Acad::eOk == acdbOpenObject(pEnt, id, AcDb::kForRead))
    55.                 {
    56.                         if (pEnt)
    57.                         {
    58.                                 pEntClone = (AcDbEntity*)pEnt->clone();
    59.                                 //此步骤是关键,复制出来实体以后,将实体从块参照自己的WCS坐标系转换为当前数据库的WCS
    60.                                 pEntClone->transformBy(matBlockRef);
    61.                                 AddToCurrentSpace(pEntClone, true);        //加入到当前数据库
    62.                         }
    63.                         pEnt->close();
    64.                 }

    65.                 //这里省略了对选择对象进行拖动的代码
    66.                 //...........
    67.                
    68.                 return TRUE;
    69.         }
    70.         else
    71.                 return FALSE;
    72. }
    复制代码

     

     

     

     

    ObjectArx块操作封装
    哎...膜结构车棚,签到来了1...
  • TA的每日心情
    开心
    7 天前
  • 签到天数: 49 天

    [LV.5]常住居民I

    185

    主题

    150

    回帖

    1695

    积分

    管理员

    积分
    1695
     楼主| 发表于 2024-5-4 11:05:22 | 显示全部楼层
    关于objectArx /CAD二次开发中“属性块”操作


    objectArx /CAD二次开发中常见的“属性块”操作有
    1.创建属性块
    2.插入属性块
    3.向现有的块参照中追加属性
    4.读取块中属性值
    5.修改块中属性值
    6.判断块中是否包含某标识的属性
    1.创建属性块
    创建一个带属性的块定义时,可直观地将“属性”看成一个直线一样的“实体”,将其附加到块表记录中即可。下面函数演示的是创建包含两条直线,一个圆以及属性标志为“直径”,值为“20”的属性块定义。
    1. bool yBlock::createBlockWithAtt(CString blkName)
    2. {
    3.         // 获得当前图形数据库的块表
    4.         AcDbBlockTable *pBlkTbl = NULL;
    5.         acdbHostApplicationServices()->workingDatabase()
    6.                 ->getBlockTable(pBlkTbl, AcDb::kForWrite);

    7.         // 创建新的块表记录
    8.         AcDbBlockTableRecord *pBlkTblRcd ;
    9.         Acad::ErrorStatus es = pBlkTbl->getAt(blkName, pBlkTblRcd, AcDb::kForRead);
    10.         if (es == Acad::eOk)
    11.         {
    12.                 pBlkTbl->close();
    13.                 acutPrintf(_T("记录已经存在"));
    14.                 return false;
    15.         }
    16.         pBlkTblRcd->setName(blkName);

    17.         // 将块表记录添加到块表中
    18.         AcDbObjectId blkDefId;
    19.         pBlkTbl->add(blkDefId, pBlkTblRcd);
    20.         pBlkTbl->close();

    21.         // 向块表记录中添加实体
    22.         AcGePoint3d ptStart(-10, 0, 0), ptEnd(10, 0, 0);
    23.         AcDbLine *pLine1 = new AcDbLine(ptStart, ptEnd);        // 创建一条直线
    24.         ptStart.set(0, -10, 0);
    25.         ptEnd.set(0, 10, 0);
    26.         AcDbLine *pLine2 = new AcDbLine(ptStart, ptEnd);        // 创建一条直线
    27.         AcGeVector3d vecNormal(0, 0, 1);
    28.         AcDbCircle *pCircle = new AcDbCircle(AcGePoint3d::kOrigin, vecNormal, 6);

    29.         // 创建一个属性  输入直径
    30.         AcDbAttributeDefinition *pAttDef = new AcDbAttributeDefinition(
    31.                 ptEnd, TEXT("20"), TEXT("直径"), TEXT("输入直径"));

    32.         AcDbObjectId entId;
    33.         pBlkTblRcd->appendAcDbEntity(entId, pLine1);
    34.         pBlkTblRcd->appendAcDbEntity(entId, pLine2);
    35.         pBlkTblRcd->appendAcDbEntity(entId, pCircle);
    36.         pBlkTblRcd->appendAcDbEntity(entId, pAttDef);

    37.         // 关闭实体和块表记录
    38.         pLine1->close();
    39.         pLine2->close();
    40.         pCircle->close();
    41.         pAttDef->close();
    42.         pBlkTblRcd->close();
    43.         return true;
    44. }
    复制代码




    2.插入属性块
    当数据库内存在属性块时,插入属性块与插入普通快有较大区别,其过程可描述为:
    1.插入一个普通的块参照
    2.遍历块参照中对应的块表记录,如果找到的记录是属性定义,则创建一个属性,属性参数来自于块记录,最后附加到块参照中。
    下面函数展示的是掺入一个属性块,参数idBlkDef(块定义ID),ptInsert(属性块插入位置),返回属性块参照。
    1. AcDbBlockReference* CreateAttBlkRef(const AcDbObjectId& idBlkDef, const AcGePoint3d& ptInsert)
    2. {
    3.         AcDbBlockReference* pBlkRef = new AcDbBlockReference(ptInsert, idBlkDef);
    4.         //判断指定的块表是否包含属性定义
    5.         AcDbBlockTableRecordPointer pBlkTblRcd(idBlkDef, AcDb::kForWrite);
    6.         if (Acad::eOk != pBlkTblRcd.openStatus())
    7.                 return pBlkRef;
    8.         if (!pBlkTblRcd->hasAttributeDefinitions())
    9.                 return pBlkRef;
    10.         //创建块表记录遍历器,用于访问块定义中的所有实体
    11.         AcDbBlockTableRecordIterator* pIter = NULL;
    12.         Acad::ErrorStatus es = pBlkTblRcd->newIterator(pIter);
    13.         if (Acad::eOk != es)
    14.                 return pBlkRef;
    15.         for (pIter->start(); !pIter->done(); pIter->step())
    16.         {
    17.                 AcDbEntity* pEnt = NULL;
    18.                 if (Acad::eOk != pIter->getEntity(pEnt, AcDb::kForRead))
    19.                         continue;
    20.                 //如果是属性定义,就向块参照添加属性
    21.                 AcDbAttributeDefinition* pAttDef = AcDbAttributeDefinition::cast(pEnt);
    22.                 if (pAttDef != NULL)
    23.                 {
    24.                         //创建一个新的属性对象
    25.                         AcDbAttribute* pAtt = new AcDbAttribute();
    26.                         //从属性定义获得属性对象的对象特征
    27.                         pAtt->setPropertiesFrom(pBlkRef);
    28.                         pAtt->setLayer(pBlkRef->layerId());
    29.                         //设置属性对象的其它特性
    30.                         pAtt->setInvisible(pAttDef->isInvisible());
    31.                         pAtt->setPosition(pAttDef->position());
    32.                         pAtt->setHeight(pAttDef->height());
    33.                         pAtt->setWidthFactor(pAttDef->widthFactor());
    34.                         pAtt->setRotation(pAttDef->rotation());
    35.                         pAtt->setHorizontalMode(pAttDef->horizontalMode());
    36.                         pAtt->setVerticalMode(pAttDef->verticalMode());
    37.                         pAtt->setAlignmentPoint(pAttDef->alignmentPoint());
    38.                         pAtt->setTextStyle(pAttDef->textStyle());
    39.                         pAtt->setAttributeFromBlock(pBlkRef->blockTransform());
    40.                         //获得属性对象的Tag、Prompt和TextString
    41.                         pAtt->setTag(pAttDef->tagConst());
    42.                         pAtt->setFieldLength(pAttDef->fieldLength());
    43.                         pAtt->setTextString(pAttDef->textStringConst());
    44.                         //设置颜色
    45.                         pAtt->setColorIndex(pAttDef->colorIndex());
    46.                         //向块参照追加属性对象
    47.                         pBlkRef->appendAttribute(pAtt);
    48.                         pAtt->close();
    49.                 }
    50.                 pEnt->close();
    51.         }
    52.         DEL(pIter);

    53.         return pBlkRef;
    54. }
    复制代码




    3.向现有的块参照中追加属性
    当数据库中已经创建了块参照,而块参照中并无属性,以下函数展示了像现有的块参照中追加属性,注意,该块参照追加属性后,再插入一个新的同名块时,属性也存在块定义中了。
    参数:blkRefId(块参照ID),ptPos(属性在块参照中的位置),strTag(属性标志)
    prompt(属性提示字符串),strValue(属性值),textHeight(属性文字高度),textStyle(属性文字样式)
    1. bool AppendBlkAttribute(AcDbObjectId &blkRefId, AcGePoint3d ptPos, CString strTag, CString prompt, CString strValue,double textHeight, AcDbObjectId textStyle)
    2. {
    3.         if (!blkRefId.isValid())
    4.         {
    5.                 return false;
    6.         }
    7.         //
    8.         AcDbObjectPointer<AcDbBlockReference> pBlkRef(blkRefId, AcDb::kForWrite);
    9.         if (pBlkRef == NULL)
    10.         {
    11.                 return false;
    12.         }
    13.         AcDbObjectId blkTblRcdId = pBlkRef->blockTableRecord();
    14.         AcDbObjectPointer<AcDbBlockTableRecord> pBlkTblRcd(blkTblRcdId, AcDb::kForWrite);

    15.         AcDbBlockTableRecordIterator* pIter = NULL;
    16.         if (Acad::eOk != pBlkTblRcd->newIterator(pIter) || NULL == pIter)
    17.                 return false;


    18.         int nRs = 0;
    19.         for (pIter->start(); !pIter->done(); pIter->step())
    20.         {
    21.                 AcDbObjectId attId;
    22.                 if (Acad::eOk != pIter->getEntityId(attId))
    23.                         continue;

    24.                 AcDbObjectPointer<AcDbAttributeDefinition> pDef(attId, AcDb::kForRead);
    25.                 if (Acad::eOk != pDef.openStatus())
    26.                         continue;
    27.                 CString strText;
    28.                 CString strTagT = pDef->tagConst();
    29.                 if (strTagT.Compare(strTag) == 0)
    30.                 {
    31.                         //pDef->setPrompt(strPro);
    32.                         strText = pDef->textStringConst();
    33.                         return true;
    34.                 }
    35.         }
    36.         //添加属性
    37.         AcDbAttributeDefinition *pAttDef = new AcDbAttributeDefinition(ptPos, strValue, strTag,prompt);
    38.         pAttDef->setHeight(textHeight);
    39.         pAttDef->setInvisible(false);
    40.         pAttDef->setTextStyle(textStyle);
    41.         //pAttDef->setVisibility(AcDb::Visibility::kInvisible);
    42.         Acad::ErrorStatus es = pBlkTblRcd->appendAcDbEntity(pAttDef);
    43.         pAttDef->close();
    44.         if (es == Acad::eOk)
    45.         {
    46.                 AcDbAttribute *pAtt = new AcDbAttribute(ptPos, strValue, strTag);
    47.                 pAtt->setInvisible(false);
    48.                 pBlkRef->appendAttribute(pAtt);

    49.                 pAtt->close();
    50.         }
    51.         return false;
    52. }
    复制代码



    4.读取块中属性值
    以下函数展示了获取块参照的属性标志以及对应的属性值
    参数:idRef(块参照ID)

    1. std::map<CString, CString> GetAttInfoOnBlkRef(const AcDbObjectId& idRef)
    2. {
    3.         std::map<CString, CString> maptag;
    4.         AcDbObjectPointer<AcDbBlockReference> pBlkRef(idRef, AcDb::kForRead);
    5.         if (pBlkRef.openStatus() != Acad::eOk)
    6.                 return maptag;

    7.         AcDbObjectIterator* pIter = pBlkRef->attributeIterator();
    8.         if (!pIter)
    9.                 return maptag;

    10.         for (pIter->start(); !pIter->done(); pIter->step())
    11.         {
    12.                 AcDbObjectId attId = pIter->objectId();
    13.                 AcDbAttribute* pAtt = NULL;
    14.                 if (pBlkRef->openAttribute(pAtt, attId, AcDb::kForRead) != Acad::eOk)
    15.                         continue;
    16.                 maptag.insert(std::pair<CString, CString>(pAtt->tagConst(), pAtt->textStringConst()));
    17.                 pAtt->close();
    18.         }
    19.         DEL(pIter);
    20.         return maptag;
    21. }
    复制代码



    5.修改块中属性值
    以下函数展示了设置属性块某个标志的值
    参数:idRef(块参照ID),szTag(属性标志),szText(属性值)
    1. bool SetAttTextOnBlkRef(const AcDbObjectId& idRef, LPCTSTR szTag, LPCTSTR szText)
    2. {
    3.         AcDbObjectPointer<AcDbBlockReference> pBlkRef(idRef, AcDb::kForWrite);
    4.         if (pBlkRef.openStatus() != Acad::eOk)
    5.                 return false;
    6.         AcDbObjectIterator* pIter = pBlkRef->attributeIterator();
    7.         if (!pIter)
    8.                 return false;
    9.         bool bFlag = false;
    10.         for (pIter->start(); !pIter->done(); pIter->step())
    11.         {
    12.                 AcDbObjectId attId = pIter->objectId();
    13.                 AcDbAttribute* pAtt = NULL;
    14.                 if (pBlkRef->openAttribute(pAtt, attId, AcDb::kForWrite) != Acad::eOk)
    15.                         continue;
    16.                 CString strTempTag = pAtt->tagConst();
    17.                 if (_tcsicmp(szTag, strTempTag) == 0)
    18.                 {
    19.                         pAtt->setTextString(szText);
    20.                         pAtt->close();
    21.                         bFlag = true;
    22.                         break;
    23.                 }
    24.                 pAtt->close();
    25.         }
    26.         DEL(pIter);
    27.         return bFlag;
    28. }
    复制代码



    6.判断块中是否包含某个标识的属性
    以下函数展示了判断一个块中是否包含了标识为szTag的属性
    参数:pBlkRef(块参照),szAttName(属性标志)
    1. bool IsExistAtt(AcDbBlockReference* pBlkRef, LPCTSTR szAttName)
    2. {
    3.         AcDbObjectIterator* pIter = pBlkRef->attributeIterator();
    4.         if (!pIter)
    5.                 return false;
    6.         for (pIter->start(); !pIter->done(); pIter->step())
    7.         {
    8.                 AcDbObjectId attId = pIter->objectId();
    9.                 AcDbAttribute* pAtt = NULL;
    10.                 if (pBlkRef->openAttribute(pAtt, attId, AcDb::kForRead) != Acad::eOk)
    11.                         continue;
    12.                 CString strTempTag = pAtt->tagConst();
    13.                 if (_tcsicmp(szAttName, strTempTag) == 0)
    14.                 {
    15.                         pAtt->close();
    16.                         DEL(pIter);
    17.                         return true;
    18.                 }
    19.                 pAtt->close();
    20.         }
    21.         DEL(pIter);
    22.         return false;
    23. }
    复制代码



     

     

     

     

    ObjectArx块操作封装
    哎...膜结构车棚,签到来了1...
  • TA的每日心情
    开心
    7 天前
  • 签到天数: 49 天

    [LV.5]常住居民I

    185

    主题

    150

    回帖

    1695

    积分

    管理员

    积分
    1695
     楼主| 发表于 2024-5-4 11:06:24 | 显示全部楼层
    objectARX中如何插入动态块

    最近遇到一个任务:提示用户选择一个动态块参照,然后复制这个块参照后提示用户插入到令一个地方。最开始,我将动态块参照复制到内存,然后插入到CAD图形数据库,发现动态属性都丢失了;后来,将块参照的blockTableRecord的ID找到,利用这个ID将块参照插入图形中,动态属性依然丢失。
    后经反复验证,发现:
    方法AcDbBlockReference::blockTableRecord返回的ID并不是动态块参照块定义的ID,只是图形中显示实体的块定义的ID;
    方法AcDbDynBlockReference::dynamicBlockTableRecord()返回的才是动态块定义的ID。
      


    代码实现
    以下代码仅仅是插入了一个自定义属性为初始状态的动态块参照,如果需要修改动态块参照的自定义属性,可以通过AcDbDynBlockReference 类中的AcDbDynBlockReference::getBlockProperties获取相关属性,然后再利用自定义属性的方法对属性进行设置。
    1. void CopyDynBlockRef()
    2. {
    3.         //提示用户选择一个动态块
    4.         struct resbuf * rb = acutBuildList(RTDXF0, _T("INSERT"), RTNONE);
    5.         ads_name ss;
    6.         CString arPrompt[2] = { _T("\n请选择一个块参照对象"),_T("\n删除了一个块参照对象") };
    7.         if (RTNORM == acedSSGet(_T(":S:$-M"), &arPrompt, NULL, rb, ss))
    8.         {
    9.                 //查看此块参照是否是动态块参照
    10.                 ads_name ent;
    11.                 acedSSName(ss, 0, ent);
    12.                 AcDbObjectId idBlk;
    13.                 acdbGetObjectId(idBlk, ent);

    14.                 //查看是否为动态块参照
    15.                 AcDbDynBlockReference cDynBlkRef(idBlk);
    16.                 if (cDynBlkRef.isDynamicBlock())
    17.                 {
    18.                         //打开块参照对象
    19.                         AcGeMatrix3d mat;
    20.                         AcGePoint3d ptInset;
    21.                         AcDbEntity* pEnt = NULL;
    22.                         if (Acad::eOk != acdbOpenObject(pEnt, idBlk, AcDb::kForRead))
    23.                         {
    24.                                 acedSSFree(ss);
    25.                                 acutRelRb(rb);
    26.                                 return;
    27.                         }

    28.                         AcDbBlockReference* pRef = AcDbBlockReference::cast(pEnt);
    29.                         if (pRef)
    30.                         {
    31.                                 mat = pRef->blockTransform();
    32.                                 ptInset = pRef->position();
    33.                         }
    34.                         pEnt->close();

    35.                         //取出动态块定义的ID
    36.                         AcDbObjectId idBlkDef = AcDbObjectId::kNull;
    37.                         idBlkDef = cDynBlkRef.dynamicBlockTableRecord();
    38.                         if (idBlkDef)
    39.                         {
    40.                                 //插入新的动态块
    41.                                 AcDbBlockReference* pBlkRef = new AcDbBlockReference(AcGePoint3d(0, 0, 0), idBlkDef);
    42.                                 pBlkRef->transformBy(mat);
    43.                                 pBlkRef->setPosition(ptInset);
    44.                                 if (AcDbObjectId::kNull == AddToModelSpace(pBlkRef))
    45.                                 {
    46.                                         delete pBlkRef;
    47.                                         acedSSFree(ss);
    48.                                         acutRelRb(rb);
    49.                                         return;
    50.                                 }

    51.                                 //此处省略拖动代码
    52.                                 //.....
    53.                         }
    54.                 }
    55.                 acedSSFree(ss);
    56.         }
    57.         acutRelRb(rb);
    58. }
    复制代码

     

     

     

     

    ObjectArx块操作封装
    哎...膜结构车棚,签到来了1...
  • TA的每日心情
    开心
    7 天前
  • 签到天数: 49 天

    [LV.5]常住居民I

    185

    主题

    150

    回帖

    1695

    积分

    管理员

    积分
    1695
     楼主| 发表于 2024-5-4 11:08:01 | 显示全部楼层
    ObjectARX的对象引用关系以及深克隆(deepClone)
    1. https://blog.csdn.net/mary288267/article/details/128083520?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171479098616800185876283%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=171479098616800185876283&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-15-128083520-null-null.nonecase&utm_term=objectarx%20%20%E5%9D%97&spm=1018.2226.3001.4450
    复制代码

    1. // THE FOLLOWING CODE APPEARS IN THE SDK DOCUMENT.

    2. // Class declarations
    3. //
    4. class AsdkOwnerDemo : public AcDbObject

    5. // This is a custom object class to demonstrate what is
    6. // necessary to create ownership trees.
    7. //
    8. // To keep it simple, this class has two data members: a
    9. // simple integer to represent normal data, and a hard
    10. // ownership ID data member to hold the object ID of an owned
    11. // object.
    12. //
    13. // Get and set functions are provided for both data members.
    14. //
    15. {
    16. public:
    17.     ACRX_DECLARE_MEMBERS(AsdkOwnerDemo);
    18.     AsdkOwnerDemo(): mIntval(0) {};
    19.     AsdkOwnerDemo(const Adesk::Int16& val): mIntval(val) {};

    20.     Adesk::Int16 intData();
    21.     Acad::ErrorStatus setIntData(const Adesk::Int16&);

    22.     AcDbHardOwnershipId idData();
    23.     Acad::ErrorStatus setIdData(const AcDbHardOwnershipId&);

    24.     Acad::ErrorStatus dwgInFields (AcDbDwgFiler*);
    25.     Acad::ErrorStatus dwgOutFields(AcDbDwgFiler*) const;
    26.     Acad::ErrorStatus dxfInFields (AcDbDxfFiler*);
    27.     Acad::ErrorStatus dxfOutFields(AcDbDxfFiler*) const;
    28. private:
    29.     Adesk::Int16 mIntval;
    30.     AcDbHardOwnershipId mObjId;
    31. };

    32. ACRX_DXF_DEFINE_MEMBERS(AsdkOwnerDemo, AcDbObject,
    33. AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, 0,
    34.     ASDKOWNERDEMO, OWNERSHIP);

    35. // Gets the value of the integer data member.
    36. //
    37. Adesk::Int16 AsdkOwnerDemo::intData()
    38. {
    39.     assertReadEnabled();
    40.     return mIntval;
    41. }

    42. // Sets the value of the integer data member.
    43. //
    44. Acad::ErrorStatus AsdkOwnerDemo::setIntData(const Adesk::Int16& val)
    45. {
    46.     assertWriteEnabled();
    47.     mIntval = val;
    48.     return Acad::eOk;
    49. }

    50. // Returns a copy of the ownership ID data member.
    51. //
    52. AcDbHardOwnershipId AsdkOwnerDemo::idData()
    53. {
    54.     assertReadEnabled();
    55.     return mObjId;
    56. }

    57. // Sets the value of the ownership ID data member.
    58. //
    59. Acad::ErrorStatus AsdkOwnerDemo::setIdData(const AcDbHardOwnershipId& ownedId)
    60. {
    61.     if (ownedId.asOldId() == 0L) {
    62.         return Acad::eInvalidInput;
    63.     }
    64.     assertWriteEnabled();

    65.     mObjId = ownedId;

    66.     // Now set the backpointer.  A transaction is used for
    67.     // opening the object, so if the object is already
    68.     // open it won't prevent this setting from taking place.
    69.     //
    70.     AcDbObject *pObj;
    71.     AcTransaction *pTrans
    72.         = actrTransactionManager->startTransaction();
    73.     pTrans->getObject(pObj, ownedId, AcDb::kForWrite);
    74.     pObj->setOwnerId(objectId());
    75.     actrTransactionManager->endTransaction();

    76.     return Acad::eOk;
    77. }

    78. // Files data in from a DWG file.
    79. //
    80. Acad::ErrorStatus AsdkOwnerDemo::dwgInFields(AcDbDwgFiler* filer)
    81. {
    82.     assertWriteEnabled();
    83.     AcDbObject::dwgInFields(filer);
    84.     // For wblock filing we wrote out our owner as a hard
    85.     // pointer Id so now we need to read it in to keep things
    86.     // in sync.
    87.     //
    88.     if (filer->filerType() == AcDb::kWblockCloneFiler) {
    89.         AcDbHardPointerId id;
    90.         filer->readItem(&id);
    91.     }
    92.     filer->readItem(&mIntval);
    93.     filer->readItem(&mObjId);
    94.     return filer->filerStatus();
    95. }

    96. // Files data out to a DWG file.
    97. //
    98. Acad::ErrorStatus AsdkOwnerDemo::dwgOutFields(AcDbDwgFiler* filer) const
    99. {
    100.     assertReadEnabled();
    101.     AcDbObject::dwgOutFields(filer);
    102.     // Since objects of this class will be in the Named
    103.     // Objects Dictionary tree and may be hard referenced
    104.     // by some other object, to support wblock we need to
    105.     // file out our owner as a hard pointer Id so that it
    106.     // will be added to the list of objects to be wblocked
    107.     //
    108.     if (filer->filerType() == AcDb::kWblockCloneFiler)
    109.         filer->writeHardPointerId((AcDbHardPointerId)ownerId());
    110.     filer->writeItem(mIntval);
    111.     filer->writeItem(mObjId);
    112.     return filer->filerStatus();
    113. }

    114. // Files data in from a DXF file.
    115. //
    116. Acad::ErrorStatus AsdkOwnerDemo::dxfInFields(AcDbDxfFiler* filer)
    117. {
    118.     assertWriteEnabled();

    119.     Acad::ErrorStatus es;
    120.     if ((es = AcDbObject::dxfInFields(filer))
    121.         != Acad::eOk)
    122.     {
    123.         return es;
    124.     }

    125.     // Check if we're at the right subclass data marker.
    126.     //
    127.     if (!filer->atSubclassData(_T("AsdkOwnerDemo"))) {
    128.         return Acad::eBadDxfSequence;
    129.     }

    130.     struct resbuf inbuf;
    131.     while (es == Acad::eOk) {
    132.         if ((es = filer->readItem(&inbuf)) == Acad::eOk) {
    133.             if (inbuf.restype == AcDb::kDxfInt16) {
    134.                 mIntval = inbuf.resval.rint;
    135.             } else if (inbuf.restype
    136.                 == AcDb::kDxfHardOwnershipId)
    137.             {
    138.                 acdbGetObjectId(mObjId,
    139.                     inbuf.resval.rlname);
    140.             }
    141.         }
    142.     }
    143.     return filer->filerStatus();
    144. }

    145. // Files data out to a DXF file.
    146. //
    147. Acad::ErrorStatus AsdkOwnerDemo::dxfOutFields(AcDbDxfFiler* filer) const
    148. {
    149.     assertReadEnabled();

    150.     AcDbObject::dxfOutFields(filer);
    151.     filer->writeItem(AcDb::kDxfSubclass, _T("AsdkOwnerDemo"));
    152.     filer->writeItem(AcDb::kDxfInt16, mIntval);

    153.     // Null object IDs are invalid: don't write them out.
    154.     //
    155.     if (mObjId.asOldId() != 0L) {
    156.         filer->writeItem(AcDb::kDxfHardOwnershipId, mObjId);
    157.     }
    158.     return filer->filerStatus();
    159. }

    160. // Creates an AsdkOwnerDemo object (pObjC) and adds data to
    161. // it.  Then, AsdkOwnerDemo pObjB is created and set to be
    162. // the owner of pObjC.  Next, AsdkOwnerDemo pObjA is created
    163. // and added to a dictionary in the named object dictionary.
    164. // Finally, pObjA is set to own pObjB. Technically, we could
    165. // just add pObjA to the named object dictionary itself, but
    166. // that's not appropriate because it would clutter up the
    167. // named object dictionary.
    168. //

    169. void createObjs()
    170. {
    171.     AcDbObjectId objIdA, objIdB, objIdC;
    172.     AcDbDictionary *pNamedobj;
    173.     AcDbDictionary *pDict = NULL;
    174.     AcDbDatabase *pCurDwg = acdbHostApplicationServices()->workingDatabase();

    175.     // Create object C with a dummy integer data value of 3.
    176.     //
    177.     AsdkOwnerDemo *pObjC = new AsdkOwnerDemo(3);

    178.     // Append object C to database without setting an owner.
    179.     //
    180.     pCurDwg->addAcDbObject(objIdC, pObjC);

    181.     pObjC->close();

    182.     // Create object B with a dummy integer data value of 2.
    183.     //
    184.     AsdkOwnerDemo *pObjB = new AsdkOwnerDemo(2);

    185.     // Append object B to the database without setting an owner.
    186.     //
    187.     pCurDwg->addAcDbObject(objIdB, pObjB);

    188.     // Now set up ownership for object C.  The
    189.     // AsdkOwnerDemo::setIdData() function takes the
    190.     // objectId parameter and copies it into the
    191.     // AcDbHardOwnershipId data member.  This places the
    192.     // object ID in a position to be filed out/in via the
    193.     // dwgInFields/dwgOutFields/dxfInFields/dxfOutFields
    194.     // member functions.  This constitutes primary
    195.     // "ownership."  The AsdkOwnerDemo::setIdData() function
    196.     // also calls each owned object's setOwnerId() member
    197.     // function to set the backpointer and establish the
    198.     // full two-way ownership link.
    199.     //
    200.     pObjB->setIdData(objIdC);

    201.     pObjB->close();

    202.     // Create object A with a dummy integer data value of 1.
    203.     //
    204.     AsdkOwnerDemo *pObjA = new AsdkOwnerDemo(1);

    205.     // Next, add objA to a dictionary in the named object
    206.     // dictionary.  This will establish ownership for objA,
    207.     // set the ownership backlink, and add it to the
    208.     // database.
    209.     //
    210.     pCurDwg->getNamedObjectsDictionary(pNamedobj,
    211.         AcDb::kForWrite);

    212.     // Get a pointer to the ASDK_DICT dictionary.  If it
    213.     // doesn't exist, then create it and add it to the
    214.     // named object dictionary.
    215.     //
    216.     if (pNamedobj->getAt(_T("ASDK_DICT"), (AcDbObject*&) pDict,
    217.         AcDb::kForWrite) == Acad::eKeyNotFound)
    218.     {
    219.         pDict = new AcDbDictionary;
    220.         AcDbObjectId DictId;
    221.         pNamedobj->setAt(_T("ASDK_DICT"), pDict, DictId);
    222.     }
    223.     pNamedobj->close();

    224.     // add object A to the ASDK_DICT dictionary
    225.     //
    226.     pDict->setAt(_T("OBJA"), pObjA, objIdA);
    227.     pDict->close();

    228.     // Now set up ownership for object B.
    229.     //
    230.     pObjA->setIdData(objIdB);

    231.     pObjA->close();
    232. }
    复制代码



    1. Acad::ErrorStatus AsdkOwnerDemo::dwgOutFields(AcDbDwgFiler* filer) const
    2. {
    3.     assertReadEnabled();
    4.     AcDbObject::dwgOutFields(filer);
    5.     // Since objects of this class will be in the Named
    6.     // Objects Dictionary tree and may be hard referenced
    7.     // by some other object, to support wblock we need to
    8.     // file out our owner as a hard pointer Id so that it
    9.     // will be added to the list of objects to be wblocked
    10.     //
    11.     if (filer->filerType() == AcDb::kWblockCloneFiler)
    12.         filer->writeHardPointerId((AcDbHardPointerId)ownerId());
    13.     filer->writeItem(mIntval);
    14.     filer->writeItem(mObjId);
    15.     return filer->filerStatus();
    16. }
    复制代码


    1. Acad::ErrorStatus AsdkOwnerDemo::setIdData(const AcDbHardOwnershipId& ownedId)
    2. {
    3.     if (ownedId.asOldId() == 0L) {
    4.         return Acad::eInvalidInput;
    5.     }
    6.     assertWriteEnabled();
    7.     mObjId = ownedId;        //设置拥有对象的ID,硬拥有

    8.     // Now set the backpointer.  A transaction is used for
    9.     // opening the object, so if the object is already
    10.     // open it won't prevent this setting from taking place.
    11.     //现在,设置被拥有对象的拥有者是this指针指向对象的ID
    12.     AcDbObject *pObj;
    13.     AcTransaction *pTrans = actrTransactionManager->startTransaction();
    14.     pTrans->getObject(pObj, ownedId, AcDb::kForWrite);
    15.     pObj->setOwnerId(objectId());
    16.     actrTransactionManager->endTransaction();

    17.     return Acad::eOk;
    18. }
    复制代码



     

     

     

     

    ObjectArx块操作封装
    哎...膜结构车棚,签到来了1...
  • TA的每日心情
    开心
    7 天前
  • 签到天数: 49 天

    [LV.5]常住居民I

    185

    主题

    150

    回帖

    1695

    积分

    管理员

    积分
    1695
     楼主| 发表于 2024-5-4 11:08:43 | 显示全部楼层
    2 关于深克隆(Deep Clone)
    2.1 深克隆基础
    深克隆(deepClone)函数复制对象和它的的所有权引用,所有的指针引用会被忽略。而wBlock函数复制硬所有权引用以及硬指针引用,忽略软所有权引用和软指针引用。为了复制引用层次关系,所有的深克隆函数和wBlock函数同时处理对象和引用(包括所有权引用和指针引用),必要时将引用指向新的对象。
    深克隆操作需要用到以后函数之一:

    AcDbDatabase::deepCloneObjects()
    AcDbDatabase::wblock()
    AcDbDatabase::insert()

    AcDbDatabase::deepCloneObjects()仅支持在一个数据库内克隆。如果你需要在数据库之间克隆对象,使用wblock()或insert()(比如,使用wblock()将对象复制到一个临时数据库,然后用insert() 将这个新数据库插入到目标数据库当中)。
    通常情况下,你应当使用AcDbDatabase::deepCloneObjects(),AcDbDatabase::wblock(),AcDbDatabase::insert() ,你不需要知道如何生成ID映射,或者深复制的每个阶段详情。如果你创建了一个新类,并且你想要重载AcDbObject::deepClone() 或者AcDbObject::wblockClone(),你需要熟悉这些函数的细节。
    在应用程序代码中,不应当直接调用对象的AcDbObject::deepClone() 和AcDbObject::wblockClone() 。他们仅仅作为更高层次克隆操作链中的一环。

    2.2 clone() 和deepClone()
    AcRxObject::clone() 函数仅仅克隆单一实体。AcDbObject::deepClone() 函数克隆该对象以及该对象拥有的其他对象。AcDbObject::deepClone()还会转换被克隆对象的引用关系。通常,deepClone函数更加安全。

    2.3 关键概念
    2.3.1 克隆和存档
    深度克隆和wblock克隆操作都使用对象存档来复制(克隆)对象。创建一个新对象(即克隆对象)后,使用dwgOut()将原始对象存档到内存中。最后,使用dwgIn()将数据存到到到新的克隆对象中。

    2.3.2 克隆和所有权
    对象关系作为一个AcDbObjectId成员变量存在对象当中。在对象中存在四种不同关系类型——硬拥有者、软拥有者、硬指针、软指针。比如,如果你创建了一个需要文本样式的实体,这个实体对象应当会有一个AcDbObjectId类型的数据成员,指向某个AcDbTextStyleTableRecord对象;它应当会被作为硬指针被存档。这个AcDbObjectId成员被存档的方式决定了deepClone和wblock使用它的方式。
    深克隆处理所有硬所有权和软所有权连接;wblock写块操作处理所有硬所有权和硬指针连接。


    2.3.3 克隆和ID映射
    ID映射是追踪克隆操作的一种机制。映射包含对象的ID对——源对象的ID(被称作"Key ID")和克隆对象或者目标对象ID(被称为"value ID")。ID映射也包含额外的ID对,在ID转换时需要这些非克隆的额外的ID。
    当对某些对象调用deepCloneObjects()时,会克隆其他对象,因为这些对象与克隆对象的主集合具有所有权关系。您可以查看ID映射以查看克隆了哪些其他对象。

    2.3.4 克隆和转换
    深克隆和wblock克隆操作实际上包含两个步骤:克隆和转换。克隆步骤是调用dwgOut()和dwgIn()并复制对象的步骤。第二步是转换步骤,在这一步会使用ID映射来重新连接所有的对象,以反应新的对象引用关系。
    在转换过程中,必须转换所有四种类型的对象ID。一些对象已克隆并位于ID映射中,而其他对象尚未克隆且不在映射中。在ID转换过程中,如果在ID映射中找不到与引用对应的ID对,则会发生以下两种情况之一。如果引用与引用它的对象位于同一数据库中,则不处理。否则,设置为NULL。

    2.4 典型的deepClone操作
    如何启动一个深克隆

    获取所有需要克隆的对象集
    将每个对象的ID放置于数组中(AcDbObjectIdArray)
    创建一个新的ID映射(AcDbIdMapping),作为deepCloneObjects的输出参数
    调用deepCloneObjects。
    1. void cloneSameOwnerObjects()
    2. {
    3.     // Step 1:  Obtain the set of objects to be cloned
    4.         // 步骤一:获取即将深克隆对象的集合
    5.     ads_name sset;
    6.     if (acedSSGet(NULL, NULL, NULL, NULL, sset) != RTNORM) {
    7.         acutPrintf(_T("\nNothing selected"));
    8.         return;
    9.     }

    10.     // Step 2: Add obtained objectIds to list of objects to be cloned
    11.         // 步骤二:将对象ID放置于容器中
    12.     AdInt32 length = 0;
    13.     acedSSLength(sset, &length);

    14.     AcDbObjectIdArray  objList;
    15.     AcDbObjectId ownerId = AcDbObjectId::kNull;
    16.     for (int i = 0; i < length; i++) {
    17.         ads_name ent;
    18.         acedSSName(sset, i, ent);
    19.         AcDbObjectId objId;
    20.         acdbGetObjectId(objId, ent);

    21.         // check to be sure same owner as first object
    22.         AcDbObject *pObj;
    23.         acdbOpenObject(pObj, objId, AcDb::kForRead);

    24.         if (pObj->ownerId() == ownerId)
    25.             objList.append(objId);
    26.         else if (i == 0) {
    27.             ownerId = pObj->ownerId();
    28.             objList.append(objId);
    29.         }
    30.         pObj->close();
    31.     }
    32.     acedSSFree(sset);

    33.     // Step 3: Get the objectId of the desired owner for
    34.     // the cloned objects.  We'll use Model Space for
    35.     // this example.
    36.         //步骤三:获取这些复制后对象的新的拥有者ID,实际上就是模型空间
    37.     AcDbBlockTable *pBlockTable;
    38.     acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForRead);
    39.     AcDbObjectId  modelSpaceId;
    40.     pBlockTable->getAt(ACDB_MODEL_SPACE, modelSpaceId);
    41.     pBlockTable->close();

    42.     // Step 4:  Create a new ID map
    43.     // 步骤4:新建一个ID映射
    44.     AcDbIdMapping idMap;

    45.     // Step 5: Call deepCloneObjects()
    46.     // 步骤4:调用deepCloneObjects
    47.     acdbHostApplicationServices()->workingDatabase()->deepCloneObjects(objList, modelSpaceId, idMap);

    48.     // Now we can go through the idMap and do whatever we'd
    49.     // like to the original and/or clone objects.
    50.     //
    51.     // For this example we'll print out the objectId's of
    52.     // the new objects resulting from the cloning process
    53.     // 现在,通过idMap,我们可以找到克隆后的对象了(AcDbIdPair中的key获取源对象ID,value获取克隆后的对象ID),然后对它任意操作。
    54.     AcDbIdMappingIter iter(idMap);
    55.     for (iter.start(); !iter.done(); iter.next()) {
    56.         AcDbIdPair idPair;
    57.         iter.getMap(idPair);
    58.         if (!idPair.isCloned())
    59.             continue;
    60.        
    61.         // 这里面有个有用的接口AcDbIdPair::isPrimary,用来判断ID对是否是主要对象(换句话说,不是因为被其他对象拥有才被克隆)。       
    62.         acutPrintf(_T("\nObjectId is: %Ld"),
    63.             idPair.value().asOldId());
    64.     }
    65. }
    复制代码



    深克隆很有用处,比如复制动态块参照:一般的clone只会复制动态块转换而成的静态块;而deepClone则会原原本本的复制动态块参照。wblock写块操作用于数据库之间的数据写入,也非常有用。

     

     

     

     

    ObjectArx块操作封装
    哎...膜结构车棚,签到来了1...
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|中国膜结构网_中国空间膜结构协会

    GMT+8, 2024-5-18 17:58 , Processed in 0.063325 second(s), 21 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表