本节中的示例代码是 的默认行为的近似值。深度克隆操作有两个主要阶段:deepClone()
在此示例中的克隆阶段,有关旧对象的信息将使用特定类型的文件管理器复制到新对象,以写出对象并将其读回。文件管理器跟踪主对象拥有的对象,以便也可以复制这些对象。 完成克隆阶段
以下示例代码演示了这些步骤: 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; } |
|Archiver|CAD开发者社区 ( 苏ICP备2022047690号-1 苏公网安备32011402011833)
GMT+8, 2025-1-8 19:42
Powered by Discuz! X3.4
Copyright © 2001-2021, Tencent Cloud.