AcDbDatabase::wblock(AcDbDatabase*& POutputDatabase, const AcDbObjectIdArray& PIdSet, const AcGePoint3d& PPoint3d)
Одно из основных внутренних различий между этими тремя версиями wblock - их обработка пространства модели и пространства листа AcDbBlockTableRecords. Поскольку полная база данных клонируется в одной версии, все примитивы в пространстве модели и пространстве листа клонированы наряду с их содержащей бумагой и пространством модели AcDbBlockTableRecords. Однако, в версиях два и три, намерение должно клонировать только отобранный набор примитивов. Хотя пространство модели и пространство листа AcDbBlockTableRecords обработаны, они используют “ поверхностный клон, ”, который в свою очередь не клонирует все примитивы, содержащиеся в пространстве модели и пространстве листа.
Даже при том, что пространство модели и блоки пространства листа были клонированы в версиях два и три, они пусты. Поэтому, не только приемлемо вызвать AcDbBlockTableRecord:: AppendAcDbEntity () чтобы разместить клонированные примитивы в них, необходимо делать так. (Это - исключение к использованию AcDbBlocKTableRecord:: AppendAcDbEntity () на AcDbBlockTableRecords, чей ID - в состоянии непрерывного изменения). Также, в обеих версиях два и три, примитивы будут иметь набор isPrimary к Adesk:: kTrue, когда они получают их wblockClone () запрос.
Это - то, потому что внутренний код индивидуально клонирует примитивы набора выборов, или примитивов отобранного AcDbBlockTableRecord. Это не клонирует AcDbBlockTableRecord непосредственно. (Примитивы во вложенных блоках, однако, будут все еще иметь набор isPrimary к Adesk:: kFalse). Это поведение полезно, как будет замечено в следующей секции в случае 1. Это сохраняет приложения от необходимости знать, что какая операция WBLOCK встречается.
Имеются несколько основных правила, чтобы иметь в виду:
1 Никогда не использовать AcDbBlocKTableRecord::AppendAcDbEntity() в течение WBLOCK*. Если Вы создали новые примитивы, Вы должны сохранить их в памяти, наряду с ID их будущего владельца, и затем добавлять их после AcEdItorReactor::endDeepClone(). Это также применяется к добавлению в конец объектов к AcDbDictionaries, ломаным линиям, polyfacemeshes, polygonmeshes, и блок-ссылкам.
2 В других двух формах WBLOCK, только используют AcDbBlocKTableRecord::ApPendAcDbEntity() при добавлении в конец к пространству модели или пространству листа. Но с тем исключением, все другие ограничения, упомянутые для WBLOCK* все еще применяются.
Обработка жестких ссылок к AcDbEntities в течение wblockClone()
Если Вы создаете заказной объект или с AcDbHardPointerId или жестко закодированной ссылкой AcDbEntity, Вы ответствены за запрос AcDbBlockTableRecord:: appendAcDbEntity () на упомянутом примитиве, когда необходимо в течение wblock (). В этом контексте, жестко закодированная ссылка - любая ситуация, в которой объект заставляет примитив быть включенным в wblockClone () через некоторый заказной код, написанный в приложении.
Необходимо делать добавление в конец вручную, потому что заданное по умолчанию выполнение AcDbDatabase:: wblockClone () будет всегда устанавливать isPrimary в Adesk:: kFalse при запросе wblockClone() на упомянутых объектах. Если объект - AcDbEntity, эта установка сообщает wblockClone() не добавлять примитив. Однако, как обозначено в предыдущей секции, если мы не делаем WBLOCK* и клонированный примитив должен занять пространство модели или пространство листа, тогда заданное по умолчанию поведение должно быть перегружено, и добавляющийся должен быть вызван.
Если Вы позволяете заданному по умолчанию поведению происходить в запросе к wblockClone () примитив, его клон закончится в базе данных, но это будет ownerless. Это не будет добавлено в конец его новому владельцу, и не имеется никакого текущего способа закончить его, чтобы добавить через API. Для упомянутого примитива, который будет добавлен в конец, значение isPrimary должно быть сброшено к Adesk::kTrue перед запросом его wblockClone() функция.
Следующий два случая показывают, как можно было обрабатывать жесткую ссылку от заказного объекта до другого примитива. Первый случай более простой, но это требует, чтобы обращение и упомянутые примитивы всегда существовали в том же самом AcDbBlockTableRecord. Второй показывает то, что должно рассмотреться, могут ли эти два примитива существовать в различных записях, или когда ссылка находится в AcDbObject вместо AcDbEntity.
Обработка жестких ссылок к AcDbEntities в течение WblockClone (): СЛУЧАЙ 1
Если обращение и упомянутые примитивы всегда существуют в том же самом AcDbBlockTableRecord, это достаточно для обращающегося перегруженного примитива wblock () чтобы отправить isPrimary, оценивают полученное, чтобы вызвать wblock упомянутого примитива (). Это воспользуется преимуществом заданного по умолчанию поведения из всех трех форм WBLOCK, как отмечено в предыдущей секции. Мы не должны быть обеспокоены, с которым тип WBLOCK встречается.
Имеются два способа перегрузить заданное по умолчанию поведение клона wblock для этого случая. Сначала, Вы могли записывать поверх полный wblockClone () для обращающегося примитива. В типовом коде для заданного по умолчанию выполнения wblockClone () (в предыдущей секции), вы будете видеть цикл на getNextHardObject (). В пределах этого цикла Вы были бы должны прервать упомянутый объект ID и изменять значение isPrimary от Adesk:: kFalse, чтобы быть тем же самый, поскольку значение isPrimary прошло в.
Однако, намного более простой способ делать это состоит в том, чтобы продолжить использовать по умолчанию wblockClone () для вашего заказного примитива, но клонировать упомянутый примитив сначала, с правильными назначениями, когда настройка по умолчанию isPrimary не была бы правильна. Как только вы клонировали упомянутый примитив, когда Вы вызываете ваш собственный wblockClone (), это будет видеть, что упомянутый примитив уже клонирован и не будет пытаться клонировать это, используя настройки по умолчанию. Следующая выборка демонстрирует это. Компонент данных, mRefEnt, является ссылкой AcDbHardPointerId.
Acad::ErrorStatus
AsdkEntity::wblockClone(AcRxObject* pOwner,
AcDbObject*& pClone,
AcDbIdMapping& idMap,
Adesk::Boolean isPrimary) const
{
// If isPrimary is kTrue, then override the default cloning
// within our own cloning, which would set it to kFalse,
// by cloning our referenced entity first.
//
if (isPrimary) {
Acad::ErrorStatus es;
AcDbEntity* pEnt;
es = acdbOpenAcDbEntity(pEnt, mRefEnt, AcDb::kForRead);
if (es!= Acad::eOk)
return es;
// Use the same owner, and pass in the same isPrimary
// value.
//
AcDbObject* pSubClone = NULL;
es = pEnt->wblockClone(pOwner, pSubClone, idMap, kTrue);
if (pSubClone!= NULL)
pSubClone->close();
pEnt->close();
if (es!= Acad::eOk)
return es;
}
// Now we can clone ourselves by calling our parent’s method.
//
return AcDbEntity::wblockClone(pOwner, pClone, idMap, isPrimary);
}
Обработка жестких ссылок к AcDbEntities в течение wblockClone(): СЛУЧАЙ 2
Предыдущий пример будет только работать, когда ссылка находится в примитиве, и тот примитив - всегда в той же самой записи таблицы блоков как упомянутый примитив. Поскольку они находятся в той же самой записи таблицы блоков, установка isPrimary для относящегося примитива будет также иметь силу для упомянутого примитива. Однако, если упомянутый примитив может существовать в различной записи таблицы блоков, или если относящийся примитив - AcDbObject, Вы использовали бы другие средства, чтобы определить, было ли добавление в конец сделано.
Сначала, Вы будете должны проверить WBLOCK уведомление, чтобы определить, который тип WBLOCK встречается, вероятно, устанавливая глобальный флажок, котором можно тогда делать запрос вашим wblockClone () функция:
§ если это - WBLOCK *, не используют AcDbBlockTableRecord:: appendAcDbEntity () в перегрузке заказного класса wblockClone (), в течение повторных вызовов, или в любом другом месте.
§ если это - WBLOCK определяемого пользователем блока, это может зависеть от того, где упомянутый примитив в настоящее время существует. Сначала, помните, что отобранный блок становится вырезанным в пространство модели рисунка адресата. Вы можете хотеть определить это поведение в другим способом, но сценарии пары могут быть следующие:
1) Всегда клонируйте упомянутые примитивы в пространство модели также. В этом случае, Вы всегда установили бы isPrimary в Adesk:: kTrue, или,
2) Проверить{*отметить*} текущее местоположение упомянутого примитива. Если это находится в пространстве модели или пространстве листа, клон это к соответствующему пространству и устанавливает isPrimary в Adesk:: kTrue. Если это находится в отобранном блоке, также клонировать это к пространству модели. Если это находится в некотором другом определяемом пользователем блоке, то вызовите wblockClone () на той блочной записи. Только убедитесь, что Вы не пробуете клонировать отобранный блок. В этом случае, запись таблицы блоков будет заботиться о клонировании ваш упомянутый примитив.
§ если это - WBLOCK набора выборов, только сбрасывают isPrimary к Adesk:: kTrue, если упомянутый примитив входит в пространство модели или пространство листа. Если это находится в определяемом пользователем блоке, назовите wblockClone () на этом AcDbBlockTableRecord, вместо на вашем упомянутом примитиве.
Наконец, должно быть отмечено, что введение жесткой ссылки AcDbEntity в настоящее время не поддержано AcDbProxyObject системой, даже если Вы используете AcDbHardPointerId для ссылки. AcDbProxyObject использует по умолчанию wblockClone () выполнение, и таким образом не будет делать добавляющийся из любых упомянутых примитивов в течение любой формы WBLOCK. Если WBLOCK случается, когда ваши примитивы - proxies, ссылки клонируются, но без добавляющегося они будут ownerless и не постоянны. Результат - то, что, когда рисунок wblocked загружается, ваша ссылка, ID будет NULL, и упомянутый примитив будет отсутствовать. Вы должны закодировать ваш заказной объект, чтобы обработать эту ситуацию изящно.
Вставка
Операция вставки - специальный случай глубокого клонирования. В случае вставки, объекты не скопированы в базу данных адресата; вместо этого, они перемещены в новую базу данных. Когда это происходит, исходная база данных больше не имеет силу, потому что это был cannibalized, когда его объекты были перемещены в новую базу данных. Если Вы перегружаете deepClone () функция, ваши объекты будет просто клонирована, когда операцию вставки запрашивают. Если Вы используете заданную по умолчанию форму deepClone (), дешевое клонирование выполнено внутренне.
|
Из за большого объема этот материал размещен на нескольких страницах:
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 |


