//

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 "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.

//

acdbOpenAcDbObject(pSubObject, id, AcDb::kForRead);

pClonedSubObject = NULL;

pSubObject->deepClone(pClonedObject,

pClonedSubObject,

idMap, Adesk::kFalse);

// If this is a kDcInsert context, the objects

// may be "cheap" cloned. In this case, they are

// "moved" instead of cloned. The result is that

// pSubObject and pClonedSubObject will point to

// the same object. Therefore, 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;

}

Перегрузка wblockClone () Функция

Когда операция клона wblock выполнена, AutoCAD создает имеющую силу базу данных для нового рисунка, который содержит словарь имен объектов, все таблицы идентификаторов, и полный набор переменных заголовка. Следующий код приближает заданное по умолчанию выполнение wblockClone (). Перечисленные шаги соответствуют, те перечисляли в секции “ Перегрузка deepClone () Функцию ” на странице 484.

НЕ нашли? Не то? Что вы ищете?

WblockClone () функция использует регистратора класса AcDbWblockCloneFiler, который возвращает список жесткого указателя и жестких связей владельца первичного объекта. Прежде, чем Вы вызываете wblockClone () на этих подобъектах, Вы должны проверить владельца подобъекта. В этой точке, вы будете делать одну из двух вещей:

N, если Вы - владелец объекта, заставляет владельца подобъекта быть клоном вас непосредственно.

N, если Вы - не владелец объекта, проход в базе данных клона как pOwner параметр в wBlockClone () функциональный запрос. В это время, объект добавлен в конец к новой базе данных, получает объект ID, и помещен в карту ID. Вход карты ID для этого объекта определит FALSE для isOwnerTranslated поля.

Если pOwner установлен в базу данных, wblockClone () должен установить владельца клонированного объекта тому же самому владельцу как таковой первоначального объекта. Тогда, когда ссылки оттранслированы в соответствии с AutoCAD, это модифицирует ссылку владельца к клонированному объекту в новой базе данных.

Важно гарантировать, что все объекты обладания клонировались. AutoCAD всегда клонирует таблицы идентификаторов, словарь имен объектов, пространство модели, и пространство листа (для клонируемых контекстов других чем AcDb:: kDcXrefBind) в течение клона wblock. Приложения с обладанием объектов ответствены за обеспечение, чтобы эти объекты клонировались{*имитировались*} в случае необходимости. Если объект обладания не клонировался и не найден в карте ID, wblock клонируемыми аварийными прекращениями работы с AcDb:: eOwnerNotSet.

Вы должны пройти в базе данных как владелец объекта, когда Вы копируете примитив, которых ссылок таблица идентификаторов делает запись. Например, предположите, что Вы вызываете wblockClone () на объекте сферы. Запись таблицы блоков - жесткий владелец этого объекта сферы. Объект сферы содержит жесткую ссылку к таблице уровня.

Сначала, в beginDeepClone () стадия, новая база данных создана и основывать с заданными по умолчанию элементами. Следующий рисунок показывает запись таблицы блоков пространства модели и таблицу уровня, потому что они уместны этому разделу. Клонирование, которое происходит в этой стадии всегда, случается в течение wblock операции.

В beginWblock () стадия, набор выборов клонировался, как показано в следующем рисунке. В этом примере, сфера клонировался.

Поскольку сфера содержит жесткий указатель на Уровень 1, Уровень 1 клонирован.

Затем, указатели должны быть оттранслированы, чтобы отнесится к клонированным объектам, как показано в следующем рисунке. BeginDeepCloneXlation() уведомление указывает начало этой стадии.

Карта ID предыдущего рисунка

KEY

VALUE

isCloned

isPrimary

isOwnerXlated

BTR1

BTR2

TRUE

FALSE

TRUE

SPH1

SPH2

TRUE

TRUE

TRUE

LT1

LT2

TRUE

FALSE

*

LTR1

LTR2

TRUE

FALSE

FALSE†

* Владелец таблицы уровня - база данных непосредственно, так что этот вход бессмысленен.

† В течение трансляции, эта установка указывает, что уровень транслирует его владельца от LayerTable 1 к LayerTable 2.

Процесс клона wblock используется для таблицы перекрестных ссылок, связывают также как wblock. Потребности оба очень похожи, но там - несколько различий, которые требуют специального внимания при перегрузке wblockClone ().

Wblock клонирует все отобранные примитивы. Однако, таблица перекрестных ссылок связывает, никогда не клонирует примитивы, которые находятся в пространстве листа. Это оставляет две вещи рассмотреть при создании объектов или примитивов, и использования AcDbHardPointerIds. Сначала, в начале wblockClone любого AcDbEntity (), выясните, если клонируемый контекст - AcDb:: kDcXrefBind и, если так, клонируется ли примитив в пространстве листа. Если это, то никакое клонирование не должно быть сделано, и wblockClone () должен возвратить Acad:: eOk.

Если ваш класс пользователя имеет любой AcDbHardPointerIds, который может указывать на примитивы (типа, мы делаем с AcDbGroup), то примитивы могли бы быть в пространстве листа и не будут поэтому клонироваться. В таком случае, AcDbHardPointerIds будет установлен в NULL.

Wblock не следует за жесткими ссылками указателя поперек баз данных. Однако, таблица перекрестных ссылок связывает, делает это все время. Например, примитив в рисунке таблицы перекрестных ссылок может быть на VISRETAIN уровне в ведущем рисунке. Так, если Вы осуществляете, ваш wblockClone () с циклом, чтобы проверить подобъекты, и базу данных подобъекта - не тот же самый как таковой клонируемого объекта, Вы должны пропустить подобъект, если клонируемый контекст - не AcDb:: kDcXrefBind. Например:

if(pSubObject->database() != database() && idMap. deepCloneContext() != AcDb::kDcXrefBind)

{

pSubObject->close();

continue;

}

Следующие показы кода, перегружающие wblockClone () чтобы осуществить это для заказного примитива (AsdkPoly). Эта функция вызвана с кодом, показанным в “ Редактор Функции Уведомления Реактора ” на странице 504.

Acad::ErrorStatus

AsdkPoly::wblockClone(AcRxObject* 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, it is set here as well.

//

pClonedObject = NULL;

// If this is a fast wblock operation, no cloning

// should take place, so we simply call the base class’s

// wblockClone() and return whatever it returns.

//

// For fast wblock, the source and destination databases

// are the same, so we can use that as the test to see

// if a fast wblock is in progress.

//

AcDbDatabase *pDest, *pOrig;

idMap. destDb(pDest);

idMap. origDb(pOrig);

if (pDest == pOrig)

return AcDbCurve::wblockClone(pOwner, pClonedObject, idMap, isPrimary);

// If this is an xref bind operation and this AsdkPoly

// entity is in paper space, then we don’t want to

// clone because xref bind doesn’t support cloning

// entities in paper space. Simply return Acad::eOk.

//

static AcDbObjectId pspace = AcDbObjectId::kNull;

if (pspace == AcDbObjectId::kNull) {

AcDbBlockTable *pTable;

database()->getSymbolTable(pTable, AcDb::kForRead);

pTable->getAt(ACDB_PAPER_SPACE, pspace);

pTable->close();

}

if ( idMap. deepCloneContext() == AcDb::kDcXrefBind && ownerId() == pspace)

return Acad::eOk;

// 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;

// The owner object can be either an AcDbObject or an

// AcDbDatabase. AcDbDatabase is used if the caller is

// not the owner of the object being cloned (because it

// is being cloned as part of an AcDbHardPointerId

// reference). In this case, the correct ownership

// will be set during reference translation. If

// the owner is an AcDbDatabase, then pOwn will be left

// NULL here, and is used as a "flag" later.

//

AcDbObject *pOwn = AcDbObject::cast(pOwner);

AcDbDatabase *pDb = AcDbDatabase::cast(pOwner);

if (pDb == NULL)

pDb = pOwn->database();

// Step 1: Create the clone.

//

AsdkPoly *pClone = (AsdkPoly*)isA()->create();

Из за большого объема этот материал размещен на нескольких страницах:
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