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

ADN Club => AutoCAD .NET API => Тема начата: Алексей Терно от 28-03-2018, 12:24:15

Название: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Алексей Терно от 28-03-2018, 12:24:15
Всем привет!
Вчера столкнулся с одной неприятной особенностью. Если у меня есть переопределенный метод Explode, то он почему-то автоматически вызывается при нажатии на кнопку "Штриховка" на ленте. Если переопределение этого метода применяется к линии, то вопросов нет, а вот если к полилинии, то при создании штриховки вылетает ошибка:

(https://s31.postimg.org/9wcmc6pe3/2018-03-28_11-56-53.png)

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

Если закомментировать строку 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  :)
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Александр Ривилис от 28-03-2018, 20:24:16
Из всего написанного я понял только, что тебе удалось обойти эту ошибку.
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Дмитрий Загорулькин от 28-03-2018, 20:41:54
Строка 43: Зачем вызывается принудительное Dispose для объекта под управлением транзакции?
Строка 81, 137, 180: Объект ResultBuffer тоже нужно(?) "диспозить" после использования. Либо через использование конструкции using, либо явным вызовом метода Dispose. Не ручаюсь, правда, что это действительно необходимо, но в примерах из интернета это делают. Думаю, что хуже точно не будет.
Строки 124-129 и 165-170: "или крестик снимите, или трусы наденьте" - если используется шаблон "одиночка", то никаких публичных конструкторов.
Строки 195-198: Вообще не понял этих действий. Это такой хитрый способ удаления данных? Но тогда потом, если я всё правильно понимаю, при вызове Overrule при попытке получения радиуса (строка 142 или 185) будет исключение.
Ну и самое главное, что действительно является большой ошибкой - объекты ents в строках 145-150 после использования в отрисовке должны уничтожаться. Опять же - либо Dispose, либо using.
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Александр Ривилис от 28-03-2018, 20:47:53
Ну и я добавлю замечание по поводу этого:
Код - 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. };
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Дмитрий Загорулькин от 28-03-2018, 21:01:23
Исправил ошибки, причесал код, проверил - действительно, при запуске команды "Штриховка" вызывается метод Explode для полилинии. И при выходе из команды AutoCAD падает.

Похоже, это какой-то внутренний баг. Так что, проверка текущей команды перед выполнением - вполне подходящее решение, на мой взгляд.
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Алексей Терно от 28-03-2018, 21:55:14
Строка 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;  :)
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Алексей Терно от 28-03-2018, 21:57:11
Ну и я добавлю замечание по поводу этого:
Это тестовый пример - "я его слепила из того, что было"  ;D
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Александр Пекшев aka Modis от 28-03-2018, 22:18:47
А добавлять новые объекты в БД за вас кто будет? Автокад чтоль? ))
Код - 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. }
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Дмитрий Загорулькин от 28-03-2018, 22:21:25
А добавлять новые объекты в БД за вас кто будет? Автокад чтоль?
Александр, Вы не поверите... ;)
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Александр Ривилис от 28-03-2018, 22:23:31
А добавлять новые объекты в БД за вас кто будет? Автокад чтоль? ))
Здрасте! Не путай метод Explode и команду Explode.
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Дмитрий Загорулькин от 28-03-2018, 22:24:31
Почему публичные конструкторы в этом контексте не допустимы? В примере от Kean Walmsley есть и "крестик" и "трусы".
Видимо, ты не до конца понимаешь в чём смысл использования этого шаблона.
А как ты удаляешь XData? После этих строк при чтении данных исключения не будет, поскольку у меня везде для этого случая есть проверки.
Да, наверное, ты прав. Я просто забыл, что XData так хитро удаляется. Я бы только не стал это делать прямо в методе Explode.
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Александр Пекшев aka Modis от 28-03-2018, 22:25:05
Дмитрий Загорулькин, Александр Ривилис,
с добавленными мной строчками все сработало. Так что...
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Алексей Терно от 28-03-2018, 22:26:23
с добавленными мной строчками все сработало. Так что...
Так и без них работает.
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Алексей Терно от 28-03-2018, 22:27:17
Видимо, ты не до конца понимаешь в чём смысл использования этого шаблона.
Смысл в том, чтобы переопределение работало только с определенными приложениями, зарегистрированными в БД.
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Дмитрий Загорулькин от 28-03-2018, 22:28:10
Одиночка на C# (https://ru.wikipedia.org/wiki/%D0%9E%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BA%D0%B0_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)#C#)
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Александр Пекшев aka Modis от 28-03-2018, 22:28:17
с добавленными мной строчками все сработало. Так что...
Так и без них работает.
Без них: создал полилинию, вызвал команду и выбрал её, вызвал команду "штриховка", завершил - фатал
С ними: создал полилинию, вызвал команду и выбрал её, вызвал команду "штриховка", завершил - получил отрезок и два кружка.
Разве что-то другое должно произойти?
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Александр Ривилис от 28-03-2018, 23:01:54
С ними: создал полилинию, вызвал команду и выбрал её, вызвал команду "штриховка", завершил - получил отрезок и два кружка.
Их не должно было появиться. Вот если бы они появились после команды EXPLODE, то это было бы нормально. А со штриховкой никакие отрезки и кружки появляться не должны.
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Александр Пекшев aka Modis от 28-03-2018, 23:04:33
С ними: создал полилинию, вызвал команду и выбрал её, вызвал команду "штриховка", завершил - получил отрезок и два кружка.
Их не должно было появиться. Вот если бы они появились после команды EXPLODE, то это было бы нормально. А со штриховкой никакие отрезки и кружки появляться не должны.
Тогда извиняюсь - неверно прочитал в чем загвоздка
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Александр Пекшев aka Modis от 28-03-2018, 23:23:16
Точно могу сказать, что проблема связана с предварительным просмотром штриховки.
Если вы вокруг полилинии с переопределенной графикой построите прямоугольник (т.е. замкнутый контур), то при наведении мышкой с командой Штриховка на прямоугольник у полилинии перестанет работать переопределении графики - т.е. она превратится обратно в начальную полилинию. Потом конечно фатал
Но если установить переменную HPQUICKPREVIEW в 0, то проблема исчезнет вообще!

Могу предположить, что в методе WorldDraw логично должно быть что-то на эту тему - типа исключить объекты из обработки командой Штриховка (и подобных). Не думаю, что разработчики такого не предусмотрели. Разве что только в АПИ не добавили
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Дмитрий Загорулькин от 29-03-2018, 13:21:58
Видимо, AutoCAD выполняет предварительный анализ и подготовку чертежа. Сделано это, скорее всего, для ускорения работы этого самого предварительного просмотра. Чтобы когда пользователь перемещал курсор по чертежу, не было долгих зависаний. Возможно, что в этот анализ как раз входит обработка полилиний - взрыв, получение её объектов, использование этих объектов в составлении временных контуров и т.д. Насколько я помню, штриховку нельзя построить по контурам из объектов, которые не добавлены в БД чертежа. И возможно, что во время работы этой команды базовый метод Explode добавляет получаемые осколки в БД чертежа, а после завершения команды объекты удаляются из базы.
Я вижу в этом возможную проблему, только если используется перерисовка полилинии с изменением её геометрии. Скорее всего, штриховка с использованием такой полилинии как границы будет некорректной.
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Алексей Терно от 29-03-2018, 14:18:37
Я вижу в этом возможную проблему, только если используется перерисовка полилинии с изменением её геометрии. Скорее всего, штриховка с использованием такой полилинии как границы будет некорректной.
Да нет, вполне корректная, только учитывается оригинальная геометрия полилинии:
(https://s31.postimg.org/a2mn4izdn/2018-03-29_14-16-07.png)
Название: Re: Вызов переопределенного метода Explode при создании штриховки
Отправлено: Дмитрий Загорулькин от 29-03-2018, 14:35:52
только учитывается оригинальная геометрия полилинии
Ну, собственно, это я и имел в виду. :)