Вызов переопределенного метода Explode при создании штриховки

Автор Тема: Вызов переопределенного метода Explode при создании штриховки  (Прочитано 6667 раз)

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

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Всем привет!
Вчера столкнулся с одной неприятной особенностью. Если у меня есть переопределенный метод Explode, то он почему-то автоматически вызывается при нажатии на кнопку "Штриховка" на ленте. Если переопределение этого метода применяется к линии, то вопросов нет, а вот если к полилинии, то при создании штриховки вылетает ошибка:



Вот весь код для теста:
Извините, вам запрещён просмотр содержимого спойлеров.

Если закомментировать строку 192 "_ents.Add(ent);", то этой ошибки нет, но объект не будет взрываться.
Эту "особенность" можно обойти добавив в самое начало метода Explode проверку:
Код - C# [Выбрать]
  1. Document doc = Application.DocumentManager.MdiActiveDocument;
  2. if (doc.CommandInProgress == "HATCH")
  3.     return;

Возникает закономерный вопрос: это что - ошибка в API, особенность работы или я чего-то не понимаю?

PS. проверялось на 2016 и 2018 версии.
PPS. конечно же проверку лучше делать не на исключение команды HATCH, а на определение команды EXLODE  :)

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

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

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Строка 43: Зачем вызывается принудительное Dispose для объекта под управлением транзакции?
Строка 81, 137, 180: Объект ResultBuffer тоже нужно(?) "диспозить" после использования. Либо через использование конструкции using, либо явным вызовом метода Dispose. Не ручаюсь, правда, что это действительно необходимо, но в примерах из интернета это делают. Думаю, что хуже точно не будет.
Строки 124-129 и 165-170: "или крестик снимите, или трусы наденьте" - если используется шаблон "одиночка", то никаких публичных конструкторов.
Строки 195-198: Вообще не понял этих действий. Это такой хитрый способ удаления данных? Но тогда потом, если я всё правильно понимаю, при вызове Overrule при попытке получения радиуса (строка 142 или 185) будет исключение.
Ну и самое главное, что действительно является большой ошибкой - объекты ents в строках 145-150 после использования в отрисовке должны уничтожаться. Опять же - либо Dispose, либо using.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Ну и я добавлю замечание по поводу этого:
Код - C# [Выбрать]
  1. ResultBuffer rb = new ResultBuffer
  2. {
  3.     new TypedValue((int)DxfCode.ExtendedDataRegAppName, MainClass.AppName),
  4.     new TypedValue((int)DxfCode.ExtendedDataInteger32, Convert.ToDouble(5)) // <------ зачем в double, если должно быть целое???
  5. };
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Исправил ошибки, причесал код, проверил - действительно, при запуске команды "Штриховка" вызывается метод Explode для полилинии. И при выходе из команды AutoCAD падает.

Похоже, это какой-то внутренний баг. Так что, проверка текущей команды перед выполнением - вполне подходящее решение, на мой взгляд.

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Строка 43: Зачем вызывается принудительное Dispose для объекта под управлением транзакции?
Это остатки прошлых экспериментов, когда я искал причины других ошибок. Все не доходят руки убрать.

Строка 81, 137, 180: Объект ResultBuffer тоже нужно(?) "диспозить" после использования. Либо через использование конструкции using, либо явным вызовом метода Dispose. Не ручаюсь, правда, что это действительно необходимо, но в примерах из интернета это делают. Думаю, что хуже точно не будет.
label1:
Согласен - хорошим тоном считается "подчистка" за собой, но в современных условиях и при подобных небольших приложениях я пока не заметил в этом острой необходимости.

Строки 124-129 и 165-170: "или крестик снимите, или трусы наденьте" - если используется шаблон "одиночка", то никаких публичных конструкторов.
Почему публичные конструкторы в этом контексте не допустимы? В примере от Kean Walmsley есть и "крестик" и "трусы".

Строки 195-198: Вообще не понял этих действий. Это такой хитрый способ удаления данных? Но тогда потом, если я всё правильно понимаю, при вызове Overrule при попытке получения радиуса (строка 142 или 185) будет исключение.
А как ты удаляешь XData? После этих строк при чтении данных исключения не будет, поскольку у меня везде для этого случая есть проверки. Это тестовый пример, упрощенный.

Ну и самое главное, что действительно является большой ошибкой - объекты ents в строках 145-150 после использования в отрисовке должны уничтожаться. Опять же - либо Dispose, либо using.
goto label1;  :)

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Ну и я добавлю замечание по поводу этого:
Это тестовый пример - "я его слепила из того, что было"  ;D

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
А добавлять новые объекты в БД за вас кто будет? Автокад чтоль? ))
Код - C# [Выбрать]
  1. public override void Explode(Entity _ent, DBObjectCollection _ents)
  2. {
  3.     Document doc = Application.DocumentManager.MdiActiveDocument;
  4.  
  5.     if (_ent is Polyline l)
  6.     {
  7.         if (l.XData != null)
  8.         {
  9.             ResultBuffer rb = l.GetXDataForApplication(MainClass.AppName);
  10.  
  11.             if (rb != null)
  12.             {
  13.                 TypedValue[] tvs = rb.AsArray();
  14.                 double r = Convert.ToDouble(tvs[1].Value);
  15.  
  16.                 LineCircleClass lc = new LineCircleClass(r);
  17.                 List<Entity> ents = lc.GetEnts(l);
  18.                 Database db = doc.Database;
  19.                 using (OpenCloseTransaction trans = db.TransactionManager.StartOpenCloseTransaction())
  20.                 {
  21.                     BlockTableRecord ms = (BlockTableRecord)trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  22.                     foreach (Entity ent in ents)
  23.                     {
  24.                         trans.AddNewlyCreatedDBObject(ent, true);
  25.                         ms.AppendEntity(ent);
  26.                         _ents.Add(ent);
  27.                     }
  28.                     trans.Commit();
  29.                 }
  30.  
  31.                 TypedValue tv = new TypedValue((int)DxfCode.ExtendedDataRegAppName, MainClass.AppName);
  32.                 l.UpgradeOpen();
  33.                 l.XData = new ResultBuffer(tv);
  34.                 l.DowngradeOpen();
  35.             }
  36.         }
  37.     }
  38. }

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
А добавлять новые объекты в БД за вас кто будет? Автокад чтоль?
Александр, Вы не поверите... ;)

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А добавлять новые объекты в БД за вас кто будет? Автокад чтоль? ))
Здрасте! Не путай метод Explode и команду Explode.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Почему публичные конструкторы в этом контексте не допустимы? В примере от Kean Walmsley есть и "крестик" и "трусы".
Видимо, ты не до конца понимаешь в чём смысл использования этого шаблона.
А как ты удаляешь XData? После этих строк при чтении данных исключения не будет, поскольку у меня везде для этого случая есть проверки.
Да, наверное, ты прав. Я просто забыл, что XData так хитро удаляется. Я бы только не стал это делать прямо в методе Explode.

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Дмитрий Загорулькин, Александр Ривилис,
с добавленными мной строчками все сработало. Так что...

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
с добавленными мной строчками все сработало. Так что...
Так и без них работает.

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Видимо, ты не до конца понимаешь в чём смысл использования этого шаблона.
Смысл в том, чтобы переопределение работало только с определенными приложениями, зарегистрированными в БД.


Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
с добавленными мной строчками все сработало. Так что...
Так и без них работает.
Без них: создал полилинию, вызвал команду и выбрал её, вызвал команду "штриховка", завершил - фатал
С ними: создал полилинию, вызвал команду и выбрал её, вызвал команду "штриховка", завершил - получил отрезок и два кружка.
Разве что-то другое должно произойти?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
С ними: создал полилинию, вызвал команду и выбрал её, вызвал команду "штриховка", завершил - получил отрезок и два кружка.
Их не должно было появиться. Вот если бы они появились после команды EXPLODE, то это было бы нормально. А со штриховкой никакие отрезки и кружки появляться не должны.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
С ними: создал полилинию, вызвал команду и выбрал её, вызвал команду "штриховка", завершил - получил отрезок и два кружка.
Их не должно было появиться. Вот если бы они появились после команды EXPLODE, то это было бы нормально. А со штриховкой никакие отрезки и кружки появляться не должны.
Тогда извиняюсь - неверно прочитал в чем загвоздка

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Точно могу сказать, что проблема связана с предварительным просмотром штриховки.
Если вы вокруг полилинии с переопределенной графикой построите прямоугольник (т.е. замкнутый контур), то при наведении мышкой с командой Штриховка на прямоугольник у полилинии перестанет работать переопределении графики - т.е. она превратится обратно в начальную полилинию. Потом конечно фатал
Но если установить переменную HPQUICKPREVIEW в 0, то проблема исчезнет вообще!

Могу предположить, что в методе WorldDraw логично должно быть что-то на эту тему - типа исключить объекты из обработки командой Штриховка (и подобных). Не думаю, что разработчики такого не предусмотрели. Разве что только в АПИ не добавили

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Видимо, AutoCAD выполняет предварительный анализ и подготовку чертежа. Сделано это, скорее всего, для ускорения работы этого самого предварительного просмотра. Чтобы когда пользователь перемещал курсор по чертежу, не было долгих зависаний. Возможно, что в этот анализ как раз входит обработка полилиний - взрыв, получение её объектов, использование этих объектов в составлении временных контуров и т.д. Насколько я помню, штриховку нельзя построить по контурам из объектов, которые не добавлены в БД чертежа. И возможно, что во время работы этой команды базовый метод Explode добавляет получаемые осколки в БД чертежа, а после завершения команды объекты удаляются из базы.
Я вижу в этом возможную проблему, только если используется перерисовка полилинии с изменением её геометрии. Скорее всего, штриховка с использованием такой полилинии как границы будет некорректной.

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Я вижу в этом возможную проблему, только если используется перерисовка полилинии с изменением её геометрии. Скорее всего, штриховка с использованием такой полилинии как границы будет некорректной.
Да нет, вполне корректная, только учитывается оригинальная геометрия полилинии:


Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
только учитывается оригинальная геометрия полилинии
Ну, собственно, это я и имел в виду. :)