// not handled here. If all are to be cloned, then
// call setTreatElementsAsHard(Adesk::kTrue) on the
// dictionary. Otherwise, only those entries that
// are referred to by hard references in other
// wblocked objects will have been cloned via
// those references.
// In this example, we will always write out all of
// the records. Since TreatElementsAsHard is not
// currently persistent, we reset it here each time.
//
pSrcDict->upgradeOpen();
pSrcDict->setTreatElementsAsHard(Adesk::kTrue);
pClone = NULL;
pSrcDict->wblockClone(pTo, pClone, idMap,
Adesk::kFalse);
if (pClone!= NULL)
pClone->close();
break;
case AcDb::kDcInsert:
// In INSERT, an entire drawing is cloned, and
// "merged" into a pre-existing drawing. This
// means that the destination drawing may already
// have our dictionary, in which case we have to
// merge our entries into the destination
// dictionary. First we must find out if
// the destination named objects dictionary contains
// our dictionary.
//
AcDbDictionary *pDestNamedDict;
pTo->getNamedObjectsDictionary(pDestNamedDict, AcDb::kForWrite);
// Since INSERT does not clone the destination
// named object dictionary, we can use getAt()
// on it.
//
es = pDestNamedDict->getAt(kpDictionary, dictId);
// If our dictionary does not yet exist in the
// named object dictionary, which is not itself
// cloned, we have to both clone and add our
// dictionary to it. Since dictionary entries are
// ownership references, all of our entries will
// also be cloned at this point, so we are done.
//
if (es == Acad::eKeyNotFound) {
pClone = NULL;
pSrcDict->deepClone(pDestNamedDict, pClone, idMap);
// Unless we have overridden the deepClone()
// of our dictionary, we should expect it to
// always be cloned here.
//
if (pClone == NULL) {
*pRetStat = Acad::eNullObjectId;
break;
}
pDestNamedDict->setAt(kpDictionary, pClone, dictId);
pDestNamedDict->close();
pClone->close();
break;
}
pDestNamedDict->close();
// Our dictionary already exists in the destination
// database, so now we must "merge" the entries
// into it. Since we have not cloned our
// destination dictionary, its object IDs are not in
// flux, and we can use getAt() and setAt() on it.
//
AcDbDictionary *pDestDict;
acdbOpenObject(pDestDict, dictId, AcDb::kForWrite);
AcDbObject *pObj, *pObjClone;
AcDbDictionaryIterator* pIter;
pIter = pSrcDict->newIterator();
for (; !pIter->done(); pIter->next()) {
const char *pName = pIter->name();
pIter->getObject(pObj, AcDb::kForRead);
// If the dictionary contains any references
// and/or other objects have references to it,
// you must either use deepClone() or put the
// ID pairs into the ID map here, so that they
// will be in the map for translation.
//
pObjClone = NULL;
pObj->deepClone(pDestDict, pObjClone, idMap);
// INSERT usually uses a method of cloning
// called CheapClone, where it "moves" objects
// into the destination database instead of
// actually cloning them. When this happens,
// pObj and pObjClone are pointers to the
// same object. We only want to close pObj
// here if it really is a different object.
//
if (pObj!= pObjClone)
pObj->close();
if (pObjClone == NULL)
continue;
// If the name already exists in our
// destination dictionary, it must be changed
// to something unique. In this example, the
// name is changed to an anonymous entry.
// The setAt() method will automatically append
// a unique identifier to each name beginning
// with "*", for example: "*S04".
//
if ( pDestDict->getAt(pName, dictId) == Acad::eKeyNotFound)
pDestDict->setAt(pName, pObjClone, dictId);
else
pDestDict->setAt("*S", pObjClone, dictId);
pObjClone->close();
}
delete pIter;
pDestDict->close();
break;
default:
break;
}
pSrcDict->close();
}
Перегрузка deepClone () Функция
Типовой код в этой секции - приближение к заданному по умолчанию поведению deepClone(). Глубокая клонируемая операция имеет две основных стадии:
§ Клонирование (Вы можете перегружать эту стадию)
§ Трансляция (Вы не будете должны повторно осуществить эту стадию; это может управляться тем, что помещено в карту ID)
В течение клонируемой стадии в этом примере, информация относительно старого объекта скопирована к новому объекту, используя определенный тип регистратора, чтобы выписать объект и читать это назад. Регистратор следит за объектами, принадлежащими первичному объекту так, чтобы они могли быть скопированы также.
Закончить клонируемую стадию
1 Создают новый объект того же самого типа как старый.
2 Добавляют новый объект его владельцу.
§ если объект - примитив, его владелец - запись таблицы блоков, и Вы можете использовать appendAcDbEntity().
§ если объект - AcDbObject, его владелец - AcDbDictionary, и Вы можете использовать setAt (), чтобы добавить это к словарю.
Если бы это - не первичный объект, Вы обычно добавили бы это к базе данных, используя addAcDbObject () и затем идентифицировать ее владельца, использующего setOwnerId ().
Чтобы устанавливать монопольное использование, владелец должен регистрировать из ID находящегося в собственности объекта, используя соответствующий тип монопольного использования.
3 Запрос dwgOut () на первоначальном объекте, используя глубокого клонируемого регистратора (AcDbDeepCloneFiler), чтобы выписать объект. (Или, если Вы перегружаете wblockClone () функция, использует AcDbWblockCloneFiler.)
4 Перематывают регистратора и затем вызывают dwgIn () на новом объекте.
5 Запроса setObjectIdsInFlux () на каждом новом объекте прежде, чем Вы добавляете его значение к карте объекта ID. Этот важный шаг используется, чтобы указать, что недавно созданный объект - часть глубокой клонируемой операции, и ее объект ID подчинен, чтобы измениться как часть стадии трансляции. Этот флажок автоматически выключен, когда трансляция полна.
6 Добавляют новую информацию к idMap. IdMap содержит AcDbIdPairs, которые являются парами старого (оригинала) и новых (клонированных) объектных ID. Конструктор для пары ID устанавливает первоначальный объект ID и флажок isPrimary. В этой точке, Вы устанавливаете объект ID для клонированного объекта, устанавливает флажок isCloned в TRUE, и добавляете (назначают) это на idMap.
7 Клонируют находящиеся в собственности объекты. (Этот шаг рекурсивен.)
§ Спрашивают регистратора, если имеются больше находящиеся в собственности объекты. (Для клона wblock, спросите, если имеются больше жесткие объекты.)
§ чтобы клонировать подобъект, получите его ID, и откройте объект для чтения.
§ Вызывают deepClone () на объекте. (Обратите внимание, что isPrimary установлен в FALSE, потому что это - находящийся в собственности объект.) deepClone () функция клонирует объект и устанавливает его владельца. Это также добавляет запись на карту ID.
§ Закрыли бы подобъект, если это было создано в это время.
§
Следующий типовой код иллюстрирует эти шаги:
Acad::ErrorStatus
AsdkPoly::deepClone(
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 (pute(idPair) && (idPair. value() != NULL))
return Acad::eOk;
// Step 1: Create the clone.
//
AsdkPoly *pClone = (AsdkPoly*)isA()->create();
if (pClone!= NULL)
pClonedObject = pClone; // Set the return value.
else
return Acad::eOutOfMemory;
// Step 2: Append the clone to its new owner. In this
// example, the original object is derived from AcDbEntity,
// so the owner is expected to be an AcDbBlockTableRecord,
// unless an ownership relationship is set up with another
// object. In that case, it is important to establish a
// connection to that owner. This sample shows a generic
// method using setOwnerId().
//
AcDbBlockTableRecord *pBTR =
AcDbBlockTableRecord::cast(pOwner);
if (pBTR!= NULL) {
pBTR->appendAcDbEntity(pClone);
} else {
if (isPrimary)
return Acad::eInvalidOwnerObject;
// Some form of this code is only necessary if
// anyone has set up an ownership for the object
// other than with an AcDbBlockTableRecord.
//
pOwner->database()->addAcDbObject(pClone);
pClone->setOwnerId(pOwner->objectId());
}
// Step 3: Now contents are copied to the clone. This is done
// using an AcDbDeepCloneFiler. This filer keeps a list of all
// AcDbHardOwnershipIds and AcDbSoftOwnershipIds contained in
// the object and its derived classes. This list is then used
// to know what additional, "owned" objects need to be cloned
// below.
//
AcDbDeepCloneFiler filer;
dwgOut(&filer);
// Step 4: Rewind the filer and read the data into the clone.
//
filer. seek(0L, AcDb::kSeekFromStart);
pClone->dwgIn(&filer);
// Step 5: 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();
// Step 6: Add the new information to the ID map. We can use
// the ID pair started above.
//
idPair. setValue(pClonedObject->objectId());
idPair. setIsCloned(Adesk::kTrue);
idMap. assign(idPair);
// Step 7: Using the filer list created above, find and clone
// any owned objects.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |


