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

ADN Club => ObjectARX => Тема начата: GrandmaSquid3 от 04-04-2018, 23:20:30

Название: Использование маскировки в AcDbEntity
Отправлено: GrandmaSquid3 от 04-04-2018, 23:20:30
Добрый вечер! Я начал разрабатывать собственный компонент для AutoCAD на основе AcDbEntity и столкнулся с проблемой создания маскировки, т.е. нужно скрывать все элементы находящиеся позади моего компонента.

Для этих целей в AutoCAD есть элемент - Маскировка (Wipeout), но использовать его в AcDbEntity нужно по-особенному (http://adndevblog.typepad.com/autocad/2012/10/drawing-acdbwipeout-in-custom-entity-worlddraw.html). Еще не успел опробовать данное решение, но что-то мне не нравится.

Есть ли еще какие-то варианты маскирования фона кроме Wipeout и Hatch (заливка области)? Может лучше сделать собственный компонент наследуясь от AcDbWipeot (если это возможно)? Пожалуйста, подскажите в каком направлении рыть, я только начал изучать ObjectARX.
Название: Re: Использование маскировки в AcDbEntity
Отправлено: Александр Ривилис от 04-04-2018, 23:30:41
Еще не успел опробовать данное решение, но что-то мне не нравится.
Что именно не нравится?
я только начал изучать ObjectARX.
Начинать изучение ObjectARX с создания Custom Entity - это не лучший вариант.
Название: Re: Использование маскировки в AcDbEntity
Отправлено: GrandmaSquid3 от 05-04-2018, 09:13:02
Начинать изучение ObjectARX с создания Custom Entity - это не лучший вариант.
Ничего не поделать, обстоятельства. Но имея опыт программирования на C++ / C# и разработки под Компас-3D, Solidworks разобраться можно. Я как раз читаю книгу Полещука, вроде всё ясно. Тут дело в другом - возможно я выбрал не оптимальное решение.

Мне нужно сделать простой интеллектуальный объект и тут AcDbEntity идеально подходит (возможно я ошибаюсь). Но как оказалось, нужно ещё прятать (маскировать) объекты за моим объектом. Я нашел два решения:

1) Использовать Wipeout (маскировка). Вроде оптимальное решение, но смущает факт необходимости добавления Wipeout в AcDbBlockTableRecord для возможности отображения. Остальные же графические объекты унаследованные от AcDbEntity можно просто отображать с помощью метода worldDraw(mode).

2) Использовать Hatch (штриховка). Штриховка является ресурсоемким объектом чертежа, плюс нужно сделать так чтобы при печати цвет заливки был белым, а при работе с чертежом цвет заливки был равен цвета фона автокаде.
Название: Re: Использование маскировки в AcDbEntity
Отправлено: GrandmaSquid3 от 05-04-2018, 09:17:28
А нельзя ли в AcDbEntity или AcDbObject как-то поиграть с рендером?
Название: Re: Использование маскировки в AcDbEntity
Отправлено: Александр Ривилис от 05-04-2018, 10:50:44
А нельзя ли в AcDbEntity или AcDbObject как-то поиграть с рендером?
Нет конечно. AcDbEntity вообще ничего не знает про рендер.
Название: Re: Использование маскировки в AcDbEntity
Отправлено: GrandmaSquid3 от 05-04-2018, 10:54:27
Так как бы Вы реализовали данную задачу?
Название: Re: Использование маскировки в AcDbEntity
Отправлено: Александр Ривилис от 05-04-2018, 10:58:20
Мне нужно сделать простой интеллектуальный объект и тут AcDbEntity идеально подходит (возможно я ошибаюсь).
Я не знаю что представляет из себя этот "интеллектуальный объект", поэтому сложно дать рекомендации по тому от какого класса следует наследовать.
1) Использовать Wipeout (маскировка). Вроде оптимальное решение, но смущает факт необходимости добавления Wipeout в AcDbBlockTableRecord для возможности отображения. Остальные же графические объекты унаследованные от AcDbEntity можно просто отображать с помощью метода worldDraw(mode).
Проблема связана с тем, что огромную роль играет порядок отображения объектов. Если объекты за твоим объектом будут отрисованы после твоего объекта, то твой объект их не скроет. И тут в игру вступает AcDbSortentsTable, которая управляет порядком прорисовки объектов на уровне блока.
Название: Re: Использование маскировки в AcDbEntity
Отправлено: GrandmaSquid3 от 12-04-2018, 14:41:18
Что-то не вышло как в том примере, фатальная ошибка: Unhandled Access Violation Reading!

В примере создают новый AcDbBlockTableRecord, в который помещают AcDbWipeout. Далее в методе subWorldDraw кастомного объекта открывают AcDbBlockTableRecord и вызывают метод отрисовки. И вроде при создании кастомного объекта все ок. Но когда я хочу перенести свой объект, то возникает фатальная ошибка. Не могу понять из-за чего.
Название: Re: Использование маскировки в AcDbEntity
Отправлено: Александр Ривилис от 12-04-2018, 14:47:38
Но когда я хочу перенести свой объект, то возникает фатальная ошибка. Не могу понять из-за чего.
Перенос - это что? Команда _MOVE? Но в примере нет переопределения subTransformBy, который должен вызываться в этом случае. Это же просто минимальный пример.
Название: Re: Использование маскировки в AcDbEntity
Отправлено: GrandmaSquid3 от 12-04-2018, 14:50:36
Да, я про subTransformBy. Я создал свой компонент на основе AcDbEntity и он хорошо переносится. Вся проблема в добавлении AcDbWipeout.
Название: Re: Использование маскировки в AcDbEntity
Отправлено: Александр Ривилис от 12-04-2018, 14:55:27
Да, я про subTransformBy. Я создал свой компонент на основе AcDbEntity и он хорошо переносится. Вся проблема в добавлении AcDbWipeout.
Запусти под отладчиком и посмотри что происходит в этом методе. И вообще-то на код нужно глянуть - я по фотографии не лечу. :-)
Название: Re: Использование маскировки в AcDbEntity
Отправлено: GrandmaSquid3 от 12-04-2018, 15:15:40
Когда кастомного объект отрисовывается впервые раз (subWorldDraw), тот можно получить AcDbBlockTableRecord по его AcDbObjectId и все ок. Но когда я начинаю перемещать объект и вызывается отрисовка, то AcDbObjectId равен нулю, что вызывает ошибку! Что-то не могу понять как переменная моего класса обнуляется...
Название: Re: Использование маскировки в AcDbEntity
Отправлено: Александр Ривилис от 12-04-2018, 15:19:30
Но когда я начинаю перемещать объект и вызывается отрисовка, то AcDbObjectId равен нулю, что вызывает ошибку! Что-то не могу понять как переменная моего класса обнуляется...
О! Обрати внимание на методы dwgInFields и dwgOutFields в том примере. Наверняка ты забыл:
Код - C++ [Выбрать]
  1. pFiler->writeHardPointerId(wipeOutId); // <------- в dwgOutFields
и
Код - C++ [Выбрать]
  1. pFiler->readHardPointerId(&wipeOutId); // <------- в dwgInFields
Название: Re: Использование маскировки в AcDbEntity
Отправлено: GrandmaSquid3 от 12-04-2018, 18:00:06
Ура, работает! Действительно дело в HardPointerId.

Но вот сижу и думаю как это работает... ИД объекта (AcDbObjectId) постоянно меняется?! Мне казалось что методы dwgInFields и dwgOutFields служат только для сохранения файла на диске. Нужно ли удерживать указатель в dxfInFields и dxfOutFields?

Кстати, я решил работать не с AcDbBlockTableRecord в своем кастомного компоненте (как было в примере), а сразу AcDbWipeout, передавая его AcDbObjectId в свой компонент и используя метод acdbOpenAcDbEntity в самом компоненте. Так я могу менять и свойства Wipeout'а (размер и положение) и отрисовывать его. Или это не верно?
Название: Re: Использование маскировки в AcDbEntity
Отправлено: Александр Ривилис от 13-04-2018, 00:31:27
Кстати, я решил работать не с AcDbBlockTableRecord в своем кастомного компоненте (как было в примере), а сразу AcDbWipeout, передавая его AcDbObjectId в свой компонент и используя метод acdbOpenAcDbEntity в самом компоненте. Так я могу менять и свойства Wipeout'а (размер и положение) и отрисовывать его. Или это не верно?
А где он в этом случае находится? Анонимный AcDbBlockTableRecord использовался в примере для того, чтобы он "не путался под ногами", т.е. не был виден в чертеже.
Но вот сижу и думаю как это работает... ИД объекта (AcDbObjectId) постоянно меняется?! Мне казалось что методы dwgInFields и dwgOutFields служат только для сохранения файла на диске. Нужно ли удерживать указатель в dxfInFields и dxfOutFields?
Id-объекта не меняется. Меняется только если закрыть dwg-файл и повторно его открыть. dwgInFields и dwgOutFields используются во многих случах, но в данном случае при создании клона примитива, который и перетаскивается, пока оригинальный остаётся на месте. Т.е. сначала срабатывает конструктор твоего класса, создавая новый экземпляр твоего примитива, потом dwgOutFields для оригинального примитива, а затем dwgInFields для новый экземпляра заполняет его значениями.
Создания клона можно избежать если переопределить в своём классе метод subCloneMeForDragging(), чтобы он возвращал  Adesk::kFalse. Но этого лучше не делать, так как вызовет другие побочные эффекты.
Название: Re: Использование маскировки в AcDbEntity
Отправлено: GrandmaSquid3 от 17-04-2018, 15:03:25
Нужно ли удалять AcDbBlockTableRecord (в котором находится AcDbWipeout) при удалении кастомного объеста?
Название: Re: Использование маскировки в AcDbEntity
Отправлено: Александр Ривилис от 17-04-2018, 16:04:46
Нужно ли удалять AcDbBlockTableRecord (в котором находится AcDbWipeout) при удалении кастомного объеста?
Во-первых, нет необходимости - _PURGE удалит этот блок, если на него нет никаких ссылок (HardPointerId).
Во-вторых, ты не знаешь в какой момент можно удалять.
Название: Re: Использование маскировки в AcDbEntity
Отправлено: GrandmaSquid3 от 17-04-2018, 16:26:43
Как не знаю? В деструкторе моего кастомного компонента разве нельзя удалить? Хотя предполагаю что и тут есть особенности AutoCAD'а.

Если смотреть "со стороны" то я создаю свой кастомный компонент на основе AcDbEntity. Так как в нем нельзя создать AcDbWipeout, я создаю новую таблицу AcDbBlockTableRecord уже в которой создаю AcDbWipeout. Далее передаю ссылку на таблицу в свой компонент, чтобы смочь отрисовывать содержимое этой этой таблицы. Выходит что при каждом создании моего компонента будет создаваться таблица и в ней маскировка. Когда я буду удалять свой компонент, то таблица с маскировкой будут оставаться (утечка памяти).
Название: Re: Использование маскировки в AcDbEntity
Отправлено: Александр Ривилис от 17-04-2018, 16:33:24
В деструкторе моего кастомного компонента разве нельзя удалить?
Нет. Деструктор "закрывает" объект если он уже в базе, а не удаляет его. Удаляет (точнее ставит пометку об удалении) метод erase() твоего объекта.
Название: Re: Использование маскировки в AcDbEntity
Отправлено: GrandmaSquid3 от 17-04-2018, 16:40:52
Кажется начинаю представлять как это устроено. Но как в итоге быть с таблицей и маскировкой? Если на объект никто не ссылается, то он потом уничтожается?
Название: Re: Использование маскировки в AcDbEntity
Отправлено: Александр Ривилис от 17-04-2018, 16:45:50
Если на объект никто не ссылается, то он потом уничтожается?
Во всяком случае _PURGE может его удалить.
Название: Re: Использование маскировки в AcDbEntity
Отправлено: GrandmaSquid3 от 17-04-2018, 16:47:36
Спасибо!