if (pClone!= NULL)
pClonedObject = pClone; // Set the return value.
else
return Acad::eOutOfMemory;
// Step 2: If the owner is an AcDbBlockTableRecord, go ahead
// and append the clone. If not, but we know who the
// owner is, set the clone’s ownerId to it. Otherwise,
// we set the clone’s ownerId to our own ownerId (in
// other words, the original ownerId). This ID will
// then be used later, in reference translation, as
// a key to finding who the new owner should be. This
// means that the original owner must also be cloned at
// some point during the wblock operation.
// EndDeepClone’s reference translation aborts if the
// owner is not found in the ID map.
//
// The most common situation where this happens is
// AcDbEntity references to symbol table records, such
// as the layer an entity is on. This is when you will
// have to pass in the destination database as the owner
// of the layer table record. Since all symbol tables
// are always cloned in wblock, you do not need to make
// sure that symbol table record owners are cloned.
//
// However, if the owner is one of your own classes,
// then it is up to you to make sure that it gets
// cloned. This is probably easiest to do at the end
// of this function. Otherwise you may have problems
// with recursion when the owner, in turn, attempts
// to clone this object as one of its subobjects.
//
AcDbBlockTableRecord *pBTR = NULL;
if (pOwn!= NULL)
pBTR = AcDbBlockTableRecord::cast(pOwn);
if (pBTR!= NULL) {
pBTR->appendAcDbEntity(pClone);
} else {
pDb->addAcDbObject(pClonedObject);
pClone->setOwnerId( (pOwn!= NULL) ? pOwn->objectId() : ownerId());
}
// Step 3: The AcDbWblockCloneFiler makes a list of
// AcDbHardOwnershipIds and AcDbHardPointerIds. These
// are the references that must be cloned during a
// wblock operation.
//
AcDbWblockCloneFiler 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 wblockClone. 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. We must also let the
// idMap entry know whether the clone’s owner is
// correct, or needs to be translated later.
//
idPair. setIsOwnerXlated((Adesk::Boolean)(pOwn!= NULL));
idPair. setValue(pClonedObject->objectId());
idPair. setIsCloned(Adesk::kTrue);
idMap. assign(idPair);
// Step 7: Using the filer list created above, find and clone
// any hard references.
//
AcDbObjectId id;
while (filer. getNextHardObject(id)) {
AcDbObject *pSubObject;
AcDbObject *pClonedSubObject;
// Some object references may be set to NULL,
// so don’t try to clone them.
//
if (id == NULL)
continue;
// If the referenced object is from a different
// database, such as an xref, do not clone it.
//
acdbOpenAcDbObject(pSubObject, id, AcDb::kForRead);
if (pSubObject->database() != database()) {
pSubObject->close();
continue;
}
// To find out if this is an AcDbHardPointerId
// versus an AcDbHardOwnershipId, check if we are the
// owner of the pSubObject. If we are not,
// then we cannot pass our clone in as the owner
// for the pSubObject’s clone. In that case, we
// pass in our clone’s database (the destination
// database).
//
// Note that "isPrimary" is set 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.
//
pClonedSubObject = NULL;
if (pSubObject->ownerId() == objectId()) {
pSubObject->wblockClone(pClone,
pClonedSubObject,
idMap, Adesk::kFalse);
} else {
pSubObject->wblockClone(
pClone->database(),
pClonedSubObject,
idMap, Adesk::kFalse);
}
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 there is no immediate
// use for it now, the clone can be closed.
//
if (pClonedSubObject!= NULL)
pClonedSubObject->close();
}
// Leave pClonedObject open for the caller.
//
return Acad::eOk;
}
ПРИМЕЧАНИЕ Помните, что, когда wblock () функция находится в процессе выполнения, ссылки указателя в базе данных адресата еще не были оттранслированы. Следующий код не работает правильно, потому что, хотя это пробует открывать запись таблицы блоков пространства модели базы данных адресата, запись таблицы блоков пространства модели исходной базы данных открыта вместо этого. Неоттранслированная ссылка в таблице блоков базы данных адресата - все еще что касается пространства модели исходной базы данных.
void
AsdkWblockReactor::otherWblock(
AcDbDatabase* pDestDb,
AcDbIdMapping& idMap,
AcDbDatabase* pSrcDb)
{
AcDbBlockTable *pDestBlockTable;
AcDbBlockTableRecord *pDestBTR;
pDestDb->getSymbolTable(pDestBlockTable, AcDb::kForRead);
pDestBlockTable->getAt(ACDB_MODEL_SPACE, pDestBTR, AcDb::kForRead);
pDestBlockTable->close();
// Now pDestBTR is pointing to pSrcDb database’s model
// space, not to the destination database’s model space!
// The code above is not correct!
}
Чтобы находить пространство модели адресата, Вы должны смотреть это в карте ID:
void
AsdkWblockReactor::otherWblock(
AcDbDatabase* pDestDb,
AcDbIdMapping& idMap,
AcDbDatabase* pSrcDb)
{
// To find the destination model space, you must look
// it up in the ID map:
AcDbBlockTable *pSrcBlockTable;
pSrcDb->getSymbolTable(pSrcBlockTable, AcDb::kForRead);
AcDbObjectId srcModelSpaceId;
pSrcBlockTable->getAt(ACDB_MODEL_SPACE, srcModelSpaceId);
pSrcBlockTable->close();
AcDbIdPair idPair;
idPair. setKey(srcModelSpaceId);
pute(idPair);
AcDbBlockTableRecord *pDestBTR;
acdbOpenAcDbObject((AcDbObject*&)pDestBTR,
idPair. value(), AcDb::kForRead, Adesk::kTrue);
}
Использование appendAcDbEntity () В течение Клонирования
AcDbBlockTableRecord:: appendAcDbEntity () требует имеющий силу AcDbObjectIds, чтобы делать добавляющийся должным образом. В течение клонирования, примитив может быть добавлен в конец к AcDbBlockTableRecord только если
AcDbBlockTableRecord:: isObjectIdsInFlux () возвращает Adesk:: kFalse. Это указывает, что сам AcDbBlockTableRecord в настоящее время не клонируется.
Одно исключение к этому правилу происходит, когда клонированный AcDbBlockTableRecord пуст. Поскольку пустой AcDbBlockTableRecord не содержит никакой неоттранслированный AcDbObjectIds, добавляющийся будет работать должным образом.
Эта ситуация возникает в течение некоторых форм wblock (), и описана более подробно коротко{*вскоре*}.
Если глубоко клонируются, - обратился к индивидуальным примитивам, то их имитирует, должен быть добавлен в конец адресату АкДбБлокТаблеРекорду. Однако, когда сам AcDbBlockTableRecord глубоко клонируется, тогда все его примитивы клонированы с этим, и запрос к AcDbBlockTableRecord:: appendAcDbEntity () не будет только ненужен, но разрушил бы клонированный AcDbBlockTableRecord.
Заданные по умолчанию выполнение deepClone () и wblockClone () знают, когда вызвать AcDbBlockTableRecord:: appendAcDbEntity () проверяя значение isPrimary. Когда примитив глубоко клонируется отдельно, isPrimary истинен, и добавлять, вызван. Если примитив клонируется как результат глубокого клонирования AcDbBlockTableRecord, то isPrimary ложный, и добавлять, не вызван.
Обычно, приложения не должны быть обеспокоены этой подробностью и могут полагаться на заданное по умолчанию выполнение deepClone () и wblockClone () чтобы обработать примитивы. Однако, ситуации могут возникать, когда приложения могут хотеть добавить примитивы в течение клонирования, или использовать жесткие ссылки к примитивам. Жесткий упомянутый примитив будет иметь значение isPrimary Adesk:: kFalse и не будет вызывать, добавляют, даже, когда можете требоваться делать так. Эта ситуация охвачена в следующей секции.
Следующие примеры и правила иллюстрируют важные аспекты клонирования.
DeepClone ()
AcDbHardPointerId проблема ссылки, упомянутая выше не будет происходить в этом случае, потому что deepClone () не следует За AcDbHardPointerId ссылками для клонирования.
Приложение может создавать проблемы в течение deepClone () если это пытается добавлять новые примитивы, в то время как AcDbObjectIds - все еще в состоянии непрерывного изменения. Поэтому, никогда не пытайтесь вызывать AcDbBlockTableRecord:: appendAcDbEntity () на любом клонированном, определяемом пользователем AcDbBlockTableRecords до окончания AcEditorReactor:: endDeepClone () уведомление далось. Напротив, Вы можете безопасно добавлять к пространству модели и пространству листа AcDbBlockTableRecords, потому что они никогда не клонированы в deepClone ().
Никогда попытка добавлять вершину к клонированный AcDb2dPolylines, AcDb3dPolylines, AcDbPolyFaceMeshes, или AcDbPolygonMeshes, приписывает клонированному AcDbBlockReferences, или вхождения в клонированные словари, до окончания AcEditorReactor:: endDeepClone () уведомление.
Если Вы создали примитивы в течение клонирования, то Вы будете должны сохранить их в памяти, наряду с ID их будущего владельца, до окончания AcEditorReactor:: endDeepClone () уведомлением. Они могут быть безопасно добавлены в конец, как только глубокий клон закончен.
WblockClone ()
Имеются три версии AcDbDatabase:: wblock ():
1 WBLOCK*
Acad:: ErrorStatus
AcDbDatabase::wblock(AcDbDatabase*& POutputDatabase)
2 WBLOCK определяемого пользователем блока
Acad:: ErrorStatus
AcDbDatabase::wblock(AcDbDatabase*& POutputDatabase, AcDbObjectId nObjId)
3 WBLOCK набора выборов
Acad:: ErrorStatus
|
Из за большого объема этот материал размещен на нескольких страницах:
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 |


