Сообщество программистов Autodesk в СНГ

ADN Club => ObjectARX => Тема начата: Олег от 23-11-2015, 15:46:16

Название: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Олег от 23-11-2015, 15:46:16
Добрый день.
Подскажите в чем причина?
Изменения , например, позиции AcDbBlockReference или цвета линии в блоке не отображается на чертеже.
Изменения видны  только если вручную через меню, например, менять тип линии.
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Александр Ривилис от 23-11-2015, 16:49:07
Не вижу кода, не знаю контекста. По кофейной гуще не гадаю.
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Олег от 23-11-2015, 16:58:16
Код - C++ [Выбрать]
  1. void EditorReactor::pickfirstModified()
  2. {
  3. // бла бла - получаем выделенный элемент
  4.  
  5.                   AcDbObjectPointer<AcDbObject>  pObj(objId, AcDb::kForRead);
  6.  
  7.                   if ( pObj->isKindOf(AcDbBlockReference::desc()))
  8.                   {
  9.                           AcDbObjectPointer<AcDbBlockReference>  pBlkRef(objId, AcDb::kForRead);
  10.                           BlockInfo(pBlkRef);
  11.                           pBlkRef->close();
  12.                   }  
  13. }
  14. void BlockInfo(AcDbBlockReference * pBlkRef)
  15. {
  16.         acutPrintf(_T("\n-----------Это блок---------"));
  17.         AcGePoint3d p3d(pBlkRef->position());
  18.         acutPrintf(_T("\nКоординаты блока: X:%7.1f,  Y:%7.1f,  Z:%7.1f"), p3d.x, p3d.y, p3d.z);
  19.  
  20.         acutPrintf(_T("\nИндекс цвета  блока %d"), pBlkRef->colorIndex());
  21.  
  22.         AcGePoint3d p3d2(pBlkRef->position());
  23.         Adesk::UInt16 newColor = pBlkRef->colorIndex();
  24.  
  25.         pBlkRef->upgradeOpen();
  26.  
  27.         AcGePoint3d p3d_2(p3d2.x + 1000, p3d2.y, p3d2.z);
  28.         pBlkRef->setPosition(p3d_2);
  29.         acutPrintf(_T("\nНовые Координаты блока: X:%7.1f,  Y:%7.1f,  Z:%7.1f"), p3d_2.x, p3d_2.y, p3d_2.z);
  30.        
  31.         newColor++;
  32.         if (newColor >= 255) newColor = 1;
  33.         pBlkRef->setColorIndex(newColor);
  34.        
  35.         acutPrintf(_T("\nНовый индекс цвета  блока %d"), pBlkRef->colorIndex());
  36.  
  37.         pBlkRef->downgradeOpen();
  38. }
  39.  

В результате ни координаты не меняются ни цвет  ни цвета линий.
Изменения цвета линий осуществляются в еще одной вызываемой функции. Здесь она не представлена для простоты чтения кода.
Если подобную последовательность использовать для примитивов например линий то и цвет их меняется и позиция.
И даже без upgradeOpen() и downgradeOpen().
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Александр Ривилис от 23-11-2015, 17:27:03
Цвет и тип линии и не должны менятся. Они те, что в описании блока. А вот положение менятся должно. Похоже, что у тебя что-то не то с контекстом. Ты не в реакторе случайно это пытаешься делать? Похоже что без тестового проекта тебе не обойтись.
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Олег от 23-11-2015, 17:30:21
в реакторе.
пример немного изменил.

а как тогда менять то?
подскажите пожалста
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Александр Ривилис от 23-11-2015, 17:39:09
Ты зачем дважды открываешь вставку блока?
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Александр Ривилис от 23-11-2015, 21:42:19
Я сделал тестовый проект и записал видео:



Пару замечаний:
1. В самом реакторе pickfirstModified крайне (!!!) нежелательно модифицировать примитивы. Ты вообще в AutoCAD видел чтобы так делалось? Я за 25 лет работы с AutoCAD такого не видел. Это противоречит общепринятому в AutoCAD подходу.
Я сделал этот пример только для того, чобы было понятно как это можно сделать. Если выбрана вставка блока с именем TESTBLK, то она сдвигается  на (10, 10, 0) и меняет индекс цвета на 1.
2. Поменять цвет вставке блока можно, но (!!!) видно это будет только если примитив (или примитивы) внутри определения блока имеют цвет "ПоБлоку" ("byBlock"). В противном случае их цвет останется тем же, что и был. Учи AutoCAD!!!
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Александр Ривилис от 24-11-2015, 00:23:17
А вот так принято делать в AutoCAD:



Исходники приложил.
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Олег от 24-11-2015, 15:56:24
Добрый день.
Спасибо за помощь.
Решение первого вопроса я выделил. Когда убрал второе открытие то и блоки двигаются и цвета линий в блоке меняются.
Прохожу итератором по всем примитивам блока и там меняю индекс цвета элемента точно так же как индекс цвета блока.

Спасибо за примеры и видео. Все наглядно и понятно.
По поводу запрета изменений свойств внутри реактора я так понимаю это следует из принципа что в обработчике событий нельзя делать то что может снова вызвать событие. Верно?

И еще один вопрос по вашему примеру.
Вы в правильном примере используете выбор элемента (acedSSLength) 2 раза.
Насколько правильно было бы в  AutoCAD использовать указатель на выбранный элемент?
Имею ввиду.
В реакторе по событию фокуса на элементе получить на него указатель.
Затем, у меня окно проперти, в окне меняю какоето свойство и оно применяется к элементу по указателю.
Соответственно указатель в null если элемент теряет фокус.
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Александр Ривилис от 24-11-2015, 16:08:54
Насколько правильно было бы в  AutoCAD использовать указатель на выбранный элемент?
Так делать очень не рекомендую. Следует придерживаться принципа: открывать объект/примитив только тогда, когда нужно получить из него информацию или изменить его и сразу же закрывать. Во всяком случае перед тем как твоя программа возвращает управление AutoCAD ты должен закрыть все открытые тобой объекты. Иначе проблем не оберёшься. Особенно если открывал объект для ForWrite.
По поводу запрета изменений свойств внутри реактора я так понимаю это следует из принципа что в обработчике событий нельзя делать то что может снова вызвать событие. Верно?
Упрощенно - верно.
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Александр Ривилис от 24-11-2015, 16:12:02
Вы в правильном примере используете выбор элемента (acedSSLength) 2 раза.
Эта функция получает количество элементов в наборе (в данном случае в наборе предварительного выбора - pickfirst).
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Олег от 24-11-2015, 16:13:04
А разве элемент остается открытым если на него получен указатель?
Или скажем так если я его закрываю то указатель теряется?
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Александр Ривилис от 24-11-2015, 16:16:45
А разве элемент остается открытым если на него получен указатель?
Конечно. Закрывает его метод close() (или деструктор AcDbObjectPointer - он вызвает метод close()). После вызова close() объект становится недействительным и указатель ссылается на область памяти, которая уже не является объектом (сравни с операторами new/delete)
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Олег от 24-11-2015, 16:21:20
Ну да, логично.
Спасибо за разъяснения, теперь более понятен принцип.
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Александр Ривилис от 24-11-2015, 16:27:19
Ну да, логично.
Спасибо за разъяснения, теперь более понятен принцип.
Добавлю еще один существенный момент. Открыть объект ForRead можно 256 раз не закрывая, а вот открыть ForWrite можно только один раз, причем если этот объект еще ни разу не открыт ни ForRead, ни ForWrite. Именно по этой причине - перестал быть нужен объект - сразу его закрываем.
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Олег от 24-11-2015, 16:52:46
Поэтому у меня и не применялись изменения к свойствам )))
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Александр Ривилис от 24-11-2015, 17:03:17
Поэтому у меня и не применялись изменения к свойствам )))
Меня больше удивляет другое: почему в твоём коде не возникло исключение:
Цитировать
INTERNAL ERROR: !dbobji.cpp@8743: eNotOpenForWrite
Вызов pBlkRef->setPosition(p3d_2); должен был привести к падению AutoCAD с такой ошибкой, так как метод pBlkRef->upgradeOpen(); не должен был сработать. Кстати, проверять код результата, методов возвращающих Acad::ErrorStatus очень желательно.
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Владимир Шу от 24-11-2015, 17:05:00
Открыть объект ForRead можно 256 раз не закрывая, а вот открыть ForWrite можно только один раз, причем если этот объект еще ни разу не открыт ни ForRead, ни ForWrite.
Прошу прощения что вмешиваюсь, но хотелось бы узнать, эти ограничения действуют и для .net платформы? В справке не нашел этого момента.
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Александр Ривилис от 24-11-2015, 17:12:42
Прошу прощения что вмешиваюсь, но хотелось бы узнать, эти ограничения действуют и для .net платформы? В справке не нашел этого момента.
Конечно. Ибо .NET платформа по сути это обёртки над ObjectARX. Кстати и в справке ты плохо искал:

(https://adn-cis.org/forum/proxy.php?request=http%3A%2F%2Fimg-fotki.yandex.ru%2Fget%2F64624%2F7842324.4%2F0_110d8b_fef7749b_orig.png&hash=a9ab1a3336a58dcaee4e699b42ca1aff)
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Владимир Шу от 24-11-2015, 17:16:31
Кстати и в справке ты плохо искал
Вернее не там искал, я в разделе транзакций смотрел...
Спасибо за разъяснения.
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Олег от 24-11-2015, 17:30:47
Вызов pBlkRef->setPosition(p3d_2); должен был привести к падению AutoCAD
Все верно падение было. Причем не только тут
        pBlkRef->setPosition(p3d_2);
 а и здесь
        AcGePoint3d p3d2(pBlkRef->position());
        Adesk::UInt16 newColor = pBlkRef->colorIndex();
если их ставить после
       pBlkRef->upgradeOpen();

Но я как то думал что не то чтото делаю, потому спросил про другое. А замет после ваших слов про двойное открытие все встало на свои места )))

А на ошибки я пока никогда не проверяю потом все вставлю проверки, пока что всю суть надо понять.
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Александр Ривилис от 24-11-2015, 17:37:39
Все верно падение было.
О! Теперь ты меня успокоил. :)
А на ошибки я пока никогда не проверяю потом все вставлю проверки, пока что всю суть надо понять.
Вот как раз суть то и можно понять, если проверять на ошибки. Тем более, что у них достаточно понятные аббревиатуры.
Название: Re: Изменения в например позиции AcDbBlockReference не отображается на чертеже
Отправлено: Олег от 24-11-2015, 17:42:19
Вот как раз суть то и можно понять, если проверять на ошибки. Тем более, что у них достаточно понятные аббревиатуры.

Понял. Воспользуюсь советом ))