CAD开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

ObjectARX 开发指南

覆盖 deepClone() 函数

2022-12-31 18:05| 发布者: admin| 查看: 320| 评论: 0|来自: AutoCAD

本节中的示例代码是 的默认行为的近似值。深度克隆操作有两个主要阶段:deepClone()

  • 克隆(您可以覆盖此阶段)
  • 翻译(你不需要重新实现这个阶段;它可以通过放入ID映射的内容来控制)

在此示例中的克隆阶段,有关旧对象的信息将使用特定类型的文件管理器复制到新对象,以写出对象并将其读回。文件管理器跟踪主对象拥有的对象,以便也可以复制这些对象。

完成克隆阶段

  1. 创建一个与旧对象类型相同的新对象。
  2. 将新对象追加到其所有者。
    • 如果对象是实体,则其所有者是块表记录,您可以使用该函数。appendAcDbEntity()
    • 如果对象是 an,则其所有者是 anand,您可以使用函数将其添加到字典中。AcDbObjectAcDbDictionarysetAt()

      如果这不是主要对象,则通常会使用 将其添加到数据库中,然后使用 标识其所有者。要建立所有权,所有者必须使用适当的所有权类型归档拥有对象的 ID。addAcDbObject()setOwnerId()

  3. 调用原始对象,使用深层克隆文件管理器 () 写出对象。(或者,如果要重写该函数,请使用 an。dwgOut()AcDbDeepCloneFilerwblockClone()AcDbWblockCloneFiler
  4. 倒带文件管理器,然后调用新对象。dwgIn()
  5. 在将每个新对象的值添加到对象 ID 映射之前调用每个新对象。此重要步骤用于指示新创建的对象是深度克隆操作的一部分,并且其对象 ID 可能会在转换阶段中发生变化。翻译完成后,此标志将自动关闭。setObjectIdsInFlux()
  6. 将新信息添加到。包含,它们是旧的(原始)和新的(克隆的)对象 ID 对。ID 对的构造函数设置原始对象 ID 和标志。此时,您可以设置克隆对象的对象 ID,将标志设置为,并将其添加到 ()。idMapidMapAcDbIdPairsisPrimaryisClonedTRUEassignidMap
  7. 克隆拥有的对象。(此步骤是递归的。
    • 询问文件管理器是否还有更多拥有的对象。(对于 wblock 克隆,询问是否还有更多硬物。
    • 要克隆子对象,请获取其 ID 并打开对象进行读取。
    • 调用对象。(请注意,设置为 ,因为这是一个拥有的对象。该函数克隆对象并设置其所有者。它还会将记录添加到 ID 映射。deepClone()isPrimaryFALSEdeepClone()
    • 如果此时已创建子对象,请将其关闭。

以下示例代码演示了这些步骤:

Acad::ErrorStatus
AsdkPoly::subDeepClone(AcDbObject*    pOwner,
                    AcDbObject*&   pClonedObject,
                    AcDbIdMapping& idMap,
                    Adesk::Boolean isPrimary) const
{
    // You should always pass back pClonedObject == NULL
    // if, for any reason, you do not actually clone it
    // during this call.  The caller should pass it in
    // as NULL, but to be safe, we set it here as well.
    //
    pClonedObject = NULL;

    // If this object is in the idMap and is already
    // cloned, then return.
    //
    bool isPrim = false;
    if (isPrimary)
        isPrim = true;
    AcDbIdPair idPair(objectId(), (AcDbObjectId)NULL,
                      false, isPrim);
    if (idMap.compute(idPair) && (idPair.value() != NULL))
        return Acad::eOk;    

    // Create the clone
    //
    AsdkPoly *pClone = (AsdkPoly*)isA()->create();
    if (pClone != NULL)
        pClonedObject = pClone;    // set the return value
    else
        return Acad::eOutOfMemory;

    AcDbDeepCloneFiler filer;
    dwgOut(&filer);

    filer.seek(0L, AcDb::kSeekFromStart);
    pClone->dwgIn(&filer);
    bool bOwnerXlated = false;
    if (isPrimary)
    {
        AcDbBlockTableRecord *pBTR =
            AcDbBlockTableRecord::cast(pOwner);
        if (pBTR != NULL)
        {
            pBTR->appendAcDbEntity(pClone);
            bOwnerXlated = true;
        }
        else
        {
            pOwner->database()->addAcDbObject(pClone);
        }
    } else {
        pOwner->database()->addAcDbObject(pClone);
        pClone->setOwnerId(pOwner->objectId());
        bOwnerXlated = true;
    }

    // This must be called for all newly created objects
    // in deepClone.  It is turned off by endDeepClone()
    // after it has translated the references to their
    // new values.
    //
    pClone->setAcDbObjectIdsInFlux();
    pClone->disableUndoRecording(true);


    // Add the new information to the idMap.  We can use
    // the idPair started above.
    //
    idPair.setValue(pClonedObject->objectId());
    idPair.setIsCloned(Adesk::kTrue);
    idPair.setIsOwnerXlated(bOwnerXlated);
    idMap.assign(idPair);

    // Using the filer list created above, find and clone
    // any owned objects.
    //
    AcDbObjectId id;
    while (filer.getNextOwnedObject(id)) {

        AcDbObject *pSubObject;
        AcDbObject *pClonedSubObject;

        // Some object's references may be set to NULL, 
        // so don't try to clone them.
        //
        if (id == NULL)
            continue;

        // Open the object and clone it.  Note that we now
        // set "isPrimary" to kFalse here because the object
        // is being cloned, not as part of the primary set,
        // but because it is owned by something in the
        // primary set.
        //
        acdbOpenAcDbObject(pSubObject, id, AcDb::kForRead);
        pClonedSubObject = NULL;
        pSubObject->deepClone(pClonedObject,
                              pClonedSubObject,
                              idMap, Adesk::kFalse);

        // If this is a kDcInsert context, the objects
        // may be "cheapCloned".  In this case, they are
        // "moved" instead of cloned.  The result is that
        // pSubObject and pClonedSubObject will point to
        // the same object.  So, we only want to close
        // pSubObject if it really is a different object
        // than its clone.
        //
        if (pSubObject != pClonedSubObject)
            pSubObject->close();
        
        // The pSubObject may either already have been
        // cloned, or for some reason has chosen not to be
        // cloned.  In that case, the returned pointer will
        // be NULL.  Otherwise, since we have no immediate
        // use for it now, we can close the clone.
        //
        if (pClonedSubObject != NULL)
            pClonedSubObject->close();
    }

    // Leave pClonedObject open for the caller
    //
    return Acad::eOk;
  }

路过

雷人

握手

鲜花

鸡蛋

最新评论

QQ|Archiver|CAD开发者社区 ( 苏ICP备2022047690号-1 )

GMT+8, 2024-5-19 13:11

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

返回顶部