Операции с объектами, расположенными на ModelSpace без его открытия

Автор Тема: Операции с объектами, расположенными на ModelSpace без его открытия  (Прочитано 14022 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн WingАвтор темы

  • ADN Club
  • Сообщений: 17
  • Карма: 0
Здравствуйте.

Наткнулся на то, что в некоторых командах открывается ModelSpace, примерно так:
Код - C++ [Выбрать]
  1. AcDbBlockTable *pTable;
  2. AcDbBlockTableRecord *pModelSpace;
  3. acdbHostApplicationServices()->workingDatabase()->getBlockTable(pTable, AcDb::kForRead);
  4. pTable->getAt(ACDB_MODEL_SPACE, pModelSpace, AcDb::kForWrite);
  5. return pModelSpace;
а в некоторых командах вызываются acdbOpenAcDbEntity() и далее всякие операции без открытия Model Space.

Вопрос - может быть, в командах не надо открывать Model Space? А для чего надо, в каких случаях?
Если можно, дайте ссылки, где можно прочитать о подобном.

И второй вопрос, в двух командах используется ads_regen(). В первом случае Model Space открывается, но перед вызовом ads_regen() пришлось закрывать все объекты и сам Model Space, иначе при удалении всех объектов с чертежа была странная картина: некоторые объекты (не те, что выделены для команды) оставались, но их нельзя было выделить, и при отключении всех слоев они тоже оставались видимыми, и прекрасно масштабировались мышью. Во второй команде такого эффекта нет, хотя там на момент вызова ads_regen объекты остаются открытыми (с помощью acdbOpenAcDbEntity), но открытия Model Space в этой команде нет вообще.
Получается, что ads_regen() требует закрытого Model Space для своей работы, но позволяет иметь открытыми объекты. Так ли это? Может быть, вообще не открывать Model Space?
Есть ли в описанных вариантах применения ads_regen() что-то явно неправильное?

Спасибо.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Приветствую на форуме! На всякий случай напоминаю, что у нас принято "один вопрос - одна тема".
Теперь по существу вопросов. ModelSpace открывается обычно в двух случаях:
1) Нужно добавить новый примитив к ModelSpace. В этом случае ModelSpace должен быть открыт для записи (AcDb::kForWrite)
2) Производится итерация по всему пространству модели для выбора каких-либо примитивов по каким-либо критериям. В этом случае достаточно открыть ModelSpace для чтения (AcDb::kForRead)
Следует активно использовать интеллектуальные указатели (AcDbBlockTableRecordPointer, AcDbObjectPointer и т.д.). Они не дадут забыть закрыть ModelSpace и другие объекты/примитивы.
Напомню, что если объект (любой, в том числе и ModelSpace) открыт для записи, то повторно открыть его как для записи, так и для чтения нельзя. И соответственно ads_regen() сработать не сможет - она итерирует по пространству модели чтобы отобразить все примитивы в нём.

Надеюсь, что мне удалось доступно объяснить. Если это не так - задавай уточняющие вопросы с примерами своего кода, а я постараюсь его "оптимизировать" по своему усмотрению. Я бы, например, никогда не стал бы писать такой код, как у тебя приведен, который возвращает указатель на пространство модели из функции. Уж очень опасно забыть не закрыть ModelSpace. Это просто приведёт к тому, что AutoCAD перестанет работать.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн WingАвтор темы

  • ADN Club
  • Сообщений: 17
  • Карма: 0
Спасибо за ответы, Александр!

Использование Model Space присутствует в обоих вопросах, поэтому счел уместным объединить. Т.е. это две части одного вопроса, хотя бы частично. Ваше замечание учту.

Насчет указателей, я согласен с тем, что они лучше, но как быть с тем, что руками мы закрываем сначала объекты, потом Model Space, а порядок вызова деструкторов не определен? Ничего не испортится, если закроется сначала Model Space, а потом объект? А если с ними вместе открывать другие объекты, например слои, есть требования по порядку закрытия?


Для выбора всех объектов по  acedSSGet( L"_A", ....);  не надо открывать Model Space, я правильно понимаю?
Такой код есть и работает. О каких итерациях тогда речь?
« Последнее редактирование: 21-11-2013, 11:57:16 от Wing »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Насчет указателей, я согласен с тем, что они лучше, но как быть с тем, что руками мы закрываем сначала объекты, потом Model Space, а порядок вызова деструкторов не определен? Ничего не испортится, если закроется сначала Model Space, а потом объект? А если с ними вместе открывать другие объекты, например слои, есть требования по порядку закрытия?
Ну во-первых порядком вызова деструкторов можно управлять. Например, конструкция вида:
Код - C++ [Выбрать]
  1. // Точка 1
  2. {
  3.  AcDbObjectPointer<AcDbCurve> pPoly(eid,AcDb::kForRead);
  4.  if (pPoly.openStatus() != Acad::eOk) {
  5.     acutPrintf(_T("\nЭто не кривая!.")); return;
  6.  }
  7. }
  8. // Точка 2
В "Точке 2" объект с AcDbObjectId равным eid будет закрыт, так как pPoly вышел из "области видимости" и сработал его деструктор.
Основное правило - если объект нужен, т.е. программа считывает его данные или наоборот модифицирует его, то он (объект) должен быть открыт. В противном случае очень желательно его закрыть как можно быстрее.

Для выбора всех объектов по  acedSSGet( L"_A", ....);  не надо открывать Model Space, я правильно понимаю?
Такой код есть и работает. О каких итерациях тогда речь?
Понимаешь правильно. Более того, если в этот момент ModelSpace окажется открыта на запись, то функция acedSSGet( L"_A", ....); не сработает, так она сама пытается открыть ModelSpace, а как я писал уже выше это становится для неё невозможным.
Что я понимал по итерациями? Я имел в виду, что ты сам можешь написать аналог функции acedSSGet( L"_A", ....); А для этой цели тебе пришлось бы выполнить итерацию по ModelSpace, т.е. найти все примитивы, которые есть в ModelSpace.
Пример:
Код - C++ [Выбрать]
  1. Acad::ErrorStatus ObjectIdArrayFromCurrentSpace(AcDbObjectIdArray &ids)
  2. {
  3.   ids.setLogicalLength(0);
  4.   AcDbBlockTableRecordPointer pCurSpace(acdbCurDwg()->currentSpaceId(),AcDb::kForRead);
  5.   AcDbBlockTableRecordIterator *iter = NULL;  pCurSpace->newIterator(iter);
  6.   if (iter) {
  7.     AcDbObjectId eId;
  8.     for (;!iter->done(); iter->step()) {
  9.       iter->getEntityId(eId); ids.append(eId);
  10.     }
  11.     delete iter;
  12.   }
  13.   return Acad::eOk;
  14. }
« Последнее редактирование: 21-11-2013, 13:32:16 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн WingАвтор темы

  • ADN Club
  • Сообщений: 17
  • Карма: 0
{ { .... } }    - так управлять временем жизни не удобно, если объекты нужны на нескольких страницах кода, а также если их области видимости почему-либо пересекаются.
Вариант с приоритетом разрушения был в loki, но, емнип, там реализовано для объектов, а не для автоуказателей. Можно, по идее, и самому сделать нечто подобное - создал AcDbObjectPointer, запихнул в контейнер с приоритетом разрушения, и забыл.
Или можно открывать самому, а в контейнер пихать открытые указатели с приоритетом закрытия.
Может есть что-то такое уже готовое, arx-ное?

Если закрыть сначала ModelSpace, а потом объект на нем, это ошибка?

По acedSSGet( L"_A", ....); понял, спасибо.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Так управлять временем жизни не удобно, если объекты нужны на нескольких страницах кода, а также если их области видимости почему-либо пересекаются.
Никто тебе не мешает закрывать и открывать объекты. Главный принцип - как можно меньше держать объект открытым.
Может есть что-то такое уже готовое, arx-ное?
Нет.
Если закрыть сначала ModelSpace, а потом объект на нем, это ошибка?
Нет. Это нормальное и наиболее естественное поведение. Т.е. допустим тебе нужно добавить окружность (AcDbCircle) в пространство модели:
1. Создаёшь окружность.
2. Открываешь пространство модели на запись.
3. Добавляешь окружность к пространству модели.
4. Закрываешь пространство модели.
5. Модифицируешь окружность (например, меняешь цвет, слой, радиус...)
6. Закрываешь окружность.

P.S.: У меня создаётся впечатление, что ты "рихтуешь" чей-то чужой код, который написан крайне небрежно, без понимания основ ObjectARX. Я прав?  ;)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн WingАвтор темы

  • ADN Club
  • Сообщений: 17
  • Карма: 0
Спасибо за ответы.

Цитировать
P.S.: У меня создаётся впечатление, что ты "рихтуешь" чей-то чужой код, который написан крайне небрежно, без понимания основ ObjectARX. Я прав?  ;)

Код, действительно, в большинстве случаев не мой. Мой там есть заплатами, составленными методом копипаста, когда заплату надо было дать быстро, не разбираясь во всех дебрях.
Понимал ли предыдущий разработчик основы ARX, сказать не берусь, а мне информация об этом не помешала бы. Дайте ссылку, если можно, именно на основы.
А что небрежно, это да. Там такие перлы попадались, как:
Код - C++ [Выбрать]
  1. bool b;
  2. b=true;
  3. b=somefunction();
  4. return false;
ну или арксинус от -4. и т.д.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Дайте ссылку, если можно, именно на основы.
К сожалению в явном виде такого документа нет. Если не считать одного курса, который читали на Autodesk University несколько лет назад, но я его сейчас не смог найти.  :( Так что и ссылки дать не на что. А вообще это приходит с опытом и изучением чужих примеров. Которых, кстати, в самом ObjectARX SDK достаточно много.
Ну и не стесняйся задавать вопросы - поможем.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн WingАвтор темы

  • ADN Club
  • Сообщений: 17
  • Карма: 0

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн WingАвтор темы

  • ADN Club
  • Сообщений: 17
  • Карма: 0