【ObjectARX】关于wblockCloneObjects函数的使用

用了很久的wblockCloneObjects函数进行跨图纸的图块拷贝,但一直对调用这个函数的AcDbDatabase应该是源图纸的还是目标图纸的不是很明白,在查到的资料中大多都是关于参数的说明:

ACDBCORE2D_PORT Acad::ErrorStatus wblockCloneObjects(
    const AcDbObjectIdArray& objectIds,
    const AcDbObjectId& owner,
    AcDbIdMapping& idMap,
    AcDb::DuplicateRecordCloning drc,
    bool deferXlation = false);

其中各个参数的意义如下:

  1. objectIds:类型为AcDbObjectIdArray的输入参数,指定需要拷贝的对象数组;
  2. owner:类型为AcDbObjectId的输入参数,指定目标数据库中新对象的所属者对象id;
  3. idMap:类型为AcDbIdMapping的输入/输出参数,用于存储源数据库中拷贝对象id与目标数据库中新对象id之间的映射关系;
  4. drc:类型为AcDb::DuplicateRecordCloning的输入参数,指定重复记录处理方式,包括kDrcIgnore、kDrcReplace、kDrcMangleName等;
  5. deferXlation:类型为bool的输入参数,表示是否延迟翻译,即是否在函数执行期间检查块内嵌块和参照等对象。 该函数的返回值为Acad::ErrorStatus类型,表示函数执行的状态码,包括但不限于Acad::eOk、Acad::eNotImplementedYet、Acad::eOutOfRange等。

于是写了一个测试函数对调用函数的AcDbDatabase进行了测试,只是没想到测试结果有点出乎意料,似乎调用的AcDbDatabase只要是一个有效值就可以,可以是源图纸的DB,也可以目标图纸的DB,也可以是第三方的DB:

// 测试wblockCloneObjects函数
void WblockCloneTest()
{
    // 获取当前图纸块表中所有的图块
    acDocManager->lockDocument(acDocManager->curDocument());
    AcDbDatabase* pDb = acdbCurDwg();
    AcDbBlockTable* pBlkTab = NULL;
    Acad::ErrorStatus es = pDb->getBlockTable(pBlkTab, AcDb::kForRead);
    if (Acad::eOk != es)
    {
        acutPrintf(L"\n【ERR 01】:%s\n", acadErrorStatusText(es));
        return;
    }

    AcDbBlockTableIterator* pIter = NULL;
    es = pBlkTab->newIterator(pIter);
    pBlkTab->close();    // 在这里就关闭块表并不影响指针便利访问
    if (Acad::eOk != es)
    {
        acutPrintf(L"\n【ERR 02】:%s\n", acadErrorStatusText(es));
        return;
    }

    AcDbObjectIdArray arsIdBlk;
    for ( pIter->start(); !pIter->done(); pIter->step() )
    {
        AcDbBlockTableRecord* pRec = NULL;
        es = pIter->getRecord(pRec, AcDb::kForRead);
        if ( Acad::eOk != es )
        {
            acutPrintf(L"\n【ERR 03】:%s\n", acadErrorStatusText(es));
            continue;
        }
        AcString sName;
        es = pRec->getName(sName);
        if (Acad::eOk == es)
        {
            acutPrintf(L"\n【块名称】:%s", sName);

            // 图纸自带的模型空间和图纸空间需要剔除不拷贝
            if (sName != ACDB_MODEL_SPACE && sName.find(ACDB_PAPER_SPACE) == CB_ERR)
            {
                arsIdBlk.append(pRec->id());
            }
        }
        pRec->close();
    }
    delete pIter;

    // 拷贝图纸(使用目标DB调用拷贝函数)
    AcDbDatabase* pDbNew1 = new AcDbDatabase;
    AcDbBlockTable* pTab1 = NULL;
    es = pDbNew1->getBlockTable(pTab1, AcDb::kForRead);
    if (Acad::eOk != es)
    {
        delete pDbNew1;
        acutPrintf(L"\n【ERR 04】:%s\n", acadErrorStatusText(es));
        return;
    }
    AcDbObjectId idTab1 = pTab1->id();
    pTab1->close();

    AcDbIdMapping idMap1;
    es = pDbNew1->wblockCloneObjects(arsIdBlk, idTab1, idMap1, AcDb::kDrcIgnore);
    if (Acad::eOk != es) 
    {
        delete pDbNew1;

        acutPrintf(L"\n【ERR 05】:%s\n", acadErrorStatusText(es));
        return;
    }
    pDbNew1->saveAs(L"\nE:\\ARX练习\\001\\001.dwg");
    delete pDbNew1;

    // 拷贝图纸(使用源DB调用拷贝函数)
    AcDbDatabase* pDbNew2 = new AcDbDatabase;
    AcDbBlockTable* pTab2 = NULL;
    es = pDbNew2->getBlockTable(pTab2, AcDb::kForRead);
    if (Acad::eOk != es)
    {
        delete pDbNew2;

        acutPrintf(L"\n【ERR 06】:%s\n", acadErrorStatusText(es));
        return;
    }
    AcDbObjectId idTab2 = pTab2->id();
    pTab2->close();

    AcDbIdMapping idMap2;
    es = pDb->wblockCloneObjects(arsIdBlk, idTab2, idMap2, AcDb::kDrcIgnore);
    if (Acad::eOk != es)
    {
        delete pDbNew2;

        acutPrintf(L"\n【ERR 07】:%s\n", acadErrorStatusText(es));
        return;
    }
    pDbNew2->saveAs(L"\nE:\\ARX练习\\001\\002.dwg");

    // 拷贝图纸(使用完全无关的DB调用拷贝函数)
    AcDbDatabase* pDbNew3 = new AcDbDatabase;
    AcDbBlockTable* pTab3 = NULL;
    es = pDbNew3->getBlockTable(pTab3, AcDb::kForRead);
    if (Acad::eOk != es)
    {
        delete pDbNew2;
        delete pDbNew3;

        acutPrintf(L"\n【ERR 08】:%s\n", acadErrorStatusText(es));
        return;
    }
    AcDbObjectId idTab3 = pTab3->id();
    pTab3->close();

    AcDbIdMapping idMap3;
    es = pDbNew2->wblockCloneObjects(arsIdBlk, idTab3, idMap3, AcDb::kDrcIgnore);
    if (Acad::eOk != es)
    {
        delete pDbNew2;
        delete pDbNew3;

        acutPrintf(L"\n【ERR 09】:%s\n", acadErrorStatusText(es));
        return;
    }
    pDbNew3->saveAs(L"\nE:\\ARX练习\\001\\003.dwg");
    delete pDbNew2;
    delete pDbNew3;

    acDocManager->unlockDocument(acDocManager->curDocument());
}

额……(我不能上传图片)(嘻嘻,换了个浏览器我又可以上传图片了)
我在当前图纸中创建了三个图块(“001-1”,“002-1”, “003-1”):
在这里插入图片描述

命令: TWB01
【块名称】:*Model_Space
【块名称】:*Paper_Space
【块名称】:*Paper_Space0
【块名称】:001-1
【块名称】:002-1
【块名称】:003-1

命令执行结束,上面是命令行输出的所有的图块名称。另外图纸也全部都生成成功,每一张图纸中都包含了上面最后三个图块(如下图所示)。
这是生成的三张图纸
可以在图纸001.dwg的块表中看到拷贝成功的三个图块。
图纸002.dwg的块表中查看拷贝成功的图块
图纸003.dwg的块表中查看拷贝成功的三个图块

所以我在猜想只要参数是正确的,无论使用哪一个DB,都会正确的拷贝到“owner”的图纸上;不知道是否有厉害的人能解释一下这个现象呢。

PS:这个函数处理中只拷贝了图块到新的图纸中,没有考虑图块属性以及样式,也不考虑块引用的拷贝。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
ObjectARX 是 AutoCAD 的编程接口,可以使用 C++ 编程语言来扩展 AutoCAD 的功能。要实现对称函数,可以使用 ObjectARX 提供的实体对象类 AcDbEntity 和 AcDbMirrorEntityPE 类。 首先,创建一个派生自 AcDbEntity 的实体类,例如 MyEntity。然后在 MyEntity 类中重载 AcDbEntity 类的 mirror() 函数,实现对称的操作。mirror() 函数的定义如下: ``` virtual Acad::ErrorStatus mirror(const AcGePlane& plane, AcDbObject*& pMirrorObj) override; ``` 在 mirror() 函数中,可以使用 AcDbMirrorEntityPE 类的成员函数 mirror() 来实现对称操作。mirror() 函数的定义如下: ``` virtual Acad::ErrorStatus mirror(AcDbEntity* pEnt, const AcGePlane& plane) override; ``` 其中,pEnt 是需要对称的实体对象指针,plane 是对称的平面。mirror() 函数将对称后的实体对象保存在 pMirrorObj 中,并返回 Acad::eOk 表示操作成功。 下面是一个简单的示例代码: ``` class MyEntity : public AcDbEntity { public: ACDB_DECLARE_MEMBERS(MyEntity); virtual Acad::ErrorStatus mirror(const AcGePlane& plane, AcDbObject*& pMirrorObj) override { AcDbMirrorEntityPE* pMirrorPE = AcDbMirrorEntityPE::cast(this); if (pMirrorPE == nullptr) return Acad::eNotImplementedYet; AcDbEntity* pMirrorEnt = nullptr; Acad::ErrorStatus es = pMirrorPE->mirror(this, plane, pMirrorEnt); if (es != Acad::eOk) return es; pMirrorObj = pMirrorEnt; return Acad::eOk; } }; ACDB_REGISTER_OBJECT_ENTRY_AUTO(MyEntity) ``` 在上面的示例中,MyEntity 类派生自 AcDbEntity,重载了 mirror() 函数。在 mirror() 函数中,首先使用 AcDbMirrorEntityPE::cast() 函数获取 AcDbMirrorEntityPE 类的指针。如果获取失败,说明当前实体对象不支持对称操作,返回 Acad::eNotImplementedYet。否则,调用 pMirrorPE->mirror() 函数实现对称操作,将对称后的实体对象保存在 pMirrorEnt 中,并将 pMirrorEnt 的指针保存在 pMirrorObj 中,最后返回 Acad::eOk 表示操作成功。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值