Визуальная идентификация объектов с определенными расширенными данными

Автор Тема: Визуальная идентификация объектов с определенными расширенными данными  (Прочитано 12259 раз)

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

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Всем привет!
Мой плагин позволяет в автокадовский примитив добавить определенные расширенные данные (далее - РД), однако при работе нет никакой идентификации, позволяющей узнать о наличии РД в примитиве. Есть конечно функция, которая позволяет их считать, но это уже другое.
А еще в автокаде есть такая штука, как параметризация и у нее есть возможность скрыть/показать запараметризированные примитивы. Думаю, нет смысла объяснять о чем я - все и так понятно:



Собственно, вопросы:
1. Есть ли в Net API возможность создавать нечто подобное для своих нужд? Чтобы рядом с примитивом, имеющим мои РД, отображался какой-нибудь символ
2. Если на п.1 ответ "да", то второй вопрос - насколько это будет "нагружать" автокад?

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Могу предположить, что это можно сделать с помощью DrawableOverrule

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
А может проще не значок показывать, а просто Entity.Highlight() ? И никаких накладных расходов

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

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

Отмечено как Решение Александр Пекшев aka Modis 31-08-2017, 09:48:54

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
В общем - идея с Drawable Overrule подходит, но столкнулся с некоторыми проблемами:
1. Хочу дополнительную графику рисовать по принципу точек - в процентах от размера экрана. Вроде где-то видел, как это значение получить, но не могу найти. Буду признателен за подсказку
2. В методе WorldDraw не создаются примитивы. Вот мой пробник с поясняющим комментарием:
Код - C# [Выбрать]
  1. public override bool WorldDraw(Drawable drawable, WorldDraw wd)
  2. {
  3.     var ent = drawable as Entity;
  4.     if (ent != null)
  5.         if (ent.IsModPlusProduct())
  6.         {
  7.             var scale = 1;
  8.             var plane = ent.GetPlane();
  9.  
  10.             Matrix3d ucs = AcApp.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem;
  11.             var extents = ent.GeometricExtents;
  12.             //var pt = extents.MaxPoint;
  13.             var pt = extents.MaxPoint.TransformBy(ucs.Inverse());
  14.             Point3dCollection points = new Point3dCollection();
  15.             points.Add(new Point3d(pt.X + 30 * scale, pt.Y + 30 * scale, plane.PointOnPlane.Z));
  16.             points.Add(new Point3d(pt.X + 30 * scale, pt.Y + 40 * scale, plane.PointOnPlane.Z));
  17.             points.Add(new Point3d(pt.X + 40 * scale, pt.Y + 40 * scale, plane.PointOnPlane.Z));
  18.             points.Add(new Point3d(pt.X + 40 * scale, pt.Y + 60 * scale, plane.PointOnPlane.Z));
  19.             points.Add(new Point3d(pt.X + 30 * scale, pt.Y + 60 * scale, plane.PointOnPlane.Z));
  20.             points.Add(new Point3d(pt.X + 30 * scale, pt.Y + 70 * scale, plane.PointOnPlane.Z));
  21.             points.Add(new Point3d(pt.X + 60 * scale, pt.Y + 70 * scale, plane.PointOnPlane.Z));
  22.             points.Add(new Point3d(pt.X + 60 * scale, pt.Y + 60 * scale, plane.PointOnPlane.Z));
  23.             points.Add(new Point3d(pt.X + 50 * scale, pt.Y + 60 * scale, plane.PointOnPlane.Z));
  24.             points.Add(new Point3d(pt.X + 50 * scale, pt.Y + 40 * scale, plane.PointOnPlane.Z));
  25.             points.Add(new Point3d(pt.X + 60 * scale, pt.Y + 40 * scale, plane.PointOnPlane.Z));
  26.             points.Add(new Point3d(pt.X + 60 * scale, pt.Y + 30 * scale, plane.PointOnPlane.Z));
  27.             points.Add(new Point3d(pt.X + 30 * scale, pt.Y + 30 * scale, plane.PointOnPlane.Z));
  28.  
  29.             Autodesk.AutoCAD.DatabaseServices.Polyline polyline =
  30.                 new Autodesk.AutoCAD.DatabaseServices.Polyline();
  31.             for (int i = 0; i < points.Count; i++)
  32.             {
  33.                 polyline.AddVertexAt(i, points[i].Convert2d(plane), 0.0, 0.0, 0.0);
  34.             }
  35.             polyline.ColorIndex = 150;
  36.             wd.Geometry.Draw(polyline); // Так не работает - вылетает автокад с фатальной ошибкой
  37.             wd.Geometry.Polyline(points, plane.Normal, IntPtr.Zero); // Так работает, но этого мало
  38.         }
  39.     return base.WorldDraw(drawable, wd);
  40. }
Я в комментарии написал, что этого мало и вот почему: вопрос - можно ли отрисовать как-то закрашенную фигуру? Например, при создании Grip'ов можно нарисовать любую фигуру и закрасить ее нужным цветом. А тут получается только наипростейшая фигура, у которой я не могу поменять ни цвет, ни толщину, не могу создать заливку.
Все примеры, которые я нахожу, совсем на другие темы (

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
С заданием цвета разобрался. Делается так:
Код - C# [Выбрать]
  1. short backupColor = wd.SubEntityTraits.Color;
  2. wd.SubEntityTraits.Color = 150;
  3. wd.Geometry.Polyline(points, plane.Normal, IntPtr.Zero);
  4. wd.SubEntityTraits.Color = backupColor;
Остальные вопросы пока не решены

UPD==========================
Как сделать залитый полигон тоже разобрался. Не так уж все и страшно оказалось))
Код - C# [Выбрать]
  1. short backupColor = wd.SubEntityTraits.Color;
  2. wd.SubEntityTraits.FillType = FillType.FillAlways;
  3. wd.SubEntityTraits.Color = 150;
  4. wd.Geometry.Polygon(points);
  5. wd.SubEntityTraits.FillType = FillType.FillNever;
  6. wd.SubEntityTraits.Color = backupColor;

Остался вопрос - размер в процентах от экрана

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Остался вопрос - размер в процентах от экрана
Высота видового экрана в единицах чертежа:
Код - C# [Выбрать]
  1. double height = (double)Application.GetSystemVariable("VIEWSIZE");
Высота и ширина видового экрана в пикселях:
Код - C# [Выбрать]
  1. Point2d screensize = (Point2d)Application.GetSystemVariable("SCREENSIZE");
Думаю этой информации тебе будет достаточно.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Александр Ривилис, спасибо! Освежили память)

Но у меня остался один вопрос из разряда теоретики - вариант как на скрине в топике (для параметризации) сделан явно без использования Drawable Overrule, так как там окошко с кнопкой и контекстным меню. Может это какие-то особые механизмы, к которым нет доступа в API
И еще вопрос - в Civil реализовано отображение предупреждений (треугольник с восклицательным знаком) - вот это ближе к Drawable Overrule по поведению. Но такой значок я лично не представляю как можно нарисовать. Это как реализовано?



Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Но такой значок я лично не представляю как можно нарисовать. Это как реализовано?

Скорее всего это просто символ шрифта, как пример посмотри Segoe UI Symbol там под номером U+26A0 похожий значок


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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Владимир Шу, кхм... Хорошее предположение и вполне логичное. Спасибо. Погляжу символы - может и мне подходящий найдется

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
вариант как на скрине в топике (для параметризации) сделан явно без использования Drawable Overrule, так как там окошко с кнопкой и контекстным меню.
Ну это и сделано не с помощью AutoCAD .NET API, а с помощью ObjectARX. Хотя возможно при помощи GripsOverrule это можно сделать. Надо ли только такие сложности?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Скорее всего это просто символ шрифта, как пример посмотри Segoe UI Symbol там под номером U+26A0 похожий значок
Возможно, хотя я бы был осторожнее со шрифтами, которых может просто не быть на PC.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Segoe  это семейство системных шрифтов и в винде с висты...

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Надо ли только такие сложности?
Нет конечно) Просто хотелось понять как они это реализовали
Единственное, что мне не нравится в варианте с Drawable Overrule - то, что если я буду размер "значка" делать в зависимости от размера экрана (в процентах), то он будет перерисовываться после вызова Regen. Я конечно не пробовал, но по опыту работы в Civil почти на 100% уверен, что это так

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Единственное, что мне не нравится в варианте с Drawable Overrule - то, что если я буду размер "значка" делать в зависимости от размера экрана (в процентах), то он будет перерисовываться после вызова Regen.
Ты имеешь в виду, что он будет перерисовывать только после вызова Regen? Чтобы этого избежать придётся потрудится и обрабатывать все изменения размера экрана  (высоты экрана в единицах чертежа), а это несколько различных событий, и выполнять обновление своих примитивов, т.е. делать самостоятельно их регенерацию.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
В методе WorldDraw не создаются примитивы. Вот мой пробник с поясняющим комментарием:
Код - C# [Выбрать]
  1. wd.Geometry.Draw(polyline); // Так не работает - вылетает автокад с фатальной ошибкой
Конечно. Draw только рисует, контролировать закрытие объектов он не умеет. Как минимум, после нужно вызывать Dispose для полилинии.
Единственное, что мне не нравится в варианте с Drawable Overrule - то, что если я буду размер "значка" делать в зависимости от размера экрана (в процентах), то он будет перерисовываться после вызова Regen.
Насколько я помню, в Civil 3D значок предупреждения динамически размеры не изменяет, тоже только после регенерации.
А тут получается только наипростейшая фигура, у которой я не могу поменять ни цвет, ни толщину, не могу создать заливку.
Глянь wd.SubEntityTraits - там всё это можно задать.

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Насколько я помню, в Civil 3D значок предупреждения динамически размеры не изменяет, тоже только после регенерации
Я это и написал ))
Я конечно не пробовал, но по опыту работы в Civil почти на 100% уверен, что это так

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Ок, просто не заметил или не так понял  :)

Оффлайн Кирилл Захаров

  • ADN OPEN
  • ***
  • Сообщений: 119
  • Карма: 5
Здравствуйте!
Не подскажете какие-нибудь хорошие статьи и примеры про Drawable Overrule и GripsOverrule?

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Тут и тут есть примеры. Еще, если погуглить, можно найти. Но если вы ищите на русском, да с объяснениями - увы - нет такого сокровища

Оффлайн Кирилл Захаров

  • ADN OPEN
  • ***
  • Сообщений: 119
  • Карма: 5
Спасибо. Да, на английском много вроде.

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

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

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Поднимаю тему.
Реализовал я свою задумку
Извините, вам запрещён просмотр содержимого спойлеров.

Вроде ничего там страшного нет такого. Ну как мне кажется. НО! У некоторых пользователей при включенном режиме (при активном DrawableOverrule) при сохранении документа происходит фатал
У меня не получается воспроизвести ошибку, поэтому нужно мнение опытных людей с предположениями о причинах

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Есть два момента, которые мне сильно не нравятся:
1. wd.SubEntityTraits.FillType не восстанавливается исходное состояние, как это сделано для wd.SubEntityTraits.Color.
2. в методе ShowIcon() нет проверки на то, что MpProductsDrawableOverrule уже было ранее включено.

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
1. wd.SubEntityTraits.FillType не восстанавливается исходное состояние, как это сделано для wd.SubEntityTraits.Color.
Спасибо, учту. Но это вряд-ли является причиной
2. в методе ShowIcon() нет проверки на то, что MpProductsDrawableOverrule уже было ранее включено
Да, ты прав! Не предусмотрел. Но тоже не критично. Выскакивает ошибка



Но автокад не падает. Исправлю конечно же, но сейчас это не так страшно

И еще вопрос по теме - можно эту геометрию предусмотреть так, чтобы она была только в модели и не показывалась на листах, и не выходила на печать?

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

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

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
и не выходила на печать?
Цвет меняешь.... может на слой Defpoints перевести маркер?

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

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


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

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

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Александр Пекшев aka Modis, в строке 37 падает во время перетаскивания объекта... без фатала, но все таки...
Хотя вот тут http://www.arch-pub.com/Fatal-error-override-WorldDraw_10652461.html пишут, что может и с фаталом упасть..

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
У некоторых пользователей при включенном режиме (при активном DrawableOverrule) при сохранении документа происходит фатал
При сохранении или при закрытии документа или при завершении AutoCAD?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Александр Ривилис,  а как можно узнать, что объект в данный момент редактируется, скажем растягивается за ручку (Jig) и соответственно в строке extents = ent.GeometricExtents; обойти ошибку? try-catch как то не очень нравиться.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
try-catch как то не очень нравиться.
Ставь try/catch - дешевле будет. Исключение может возникнуть и по другим причинам, а не только потому что растягивают объект. Вообще же при Jig обычно участвуют не сами объекты, а их клоны, т.е. их свойство ObjectId == ObjectId.Null
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Ставь try/catch - дешевле будет. Исключение может возникнуть и по другим причинам, а не только потому что растягивают объект. Вообще же при Jig обычно участвуют не сами объекты, а их клоны, т.е. их свойство ObjectId == ObjectId.Null
Спасибо. понял почему падало. Я убрал фильтрацию по объектам ModPlus (if (ent.IsModPlusProduct()) и рисовал значок для всех объектов, а при растягивании, при включенном динамическом вводе, создаются временные размеры, у которых запрос свойства GeometricExtents и вызывает ошибку. и да, у них ObjectId == ObjectId.Null .

Александр Пекшев aka Modis,  еще заметил, что вот эта строка:
var pt = extents.MaxPoint.TransformBy(ucs.Inverse());
не очень хорошее решение, так как может получаться вот так:

Наверное стоит для наследников Curve, брать просто EndPoint ...
И вот это не очень
points.Add(new Gem.Point3d(pt.X + (offset + 00) * scale, pt.Y + (offset + 00) * scale, plane.PointOnPlane.Z));
наверное стоит задавать векторами, в соответствии с направлением линии на конце которой строится иконка...

Уронить автокад в фатал при сохранении пока не удалось.

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Спасибо за ответы. С кодом пока не занимался, но учту все, что было описано. У меня как раз есть файл (от пользователя), который точно не открывается при включенном Overrule. Падает с фаталом
var pt = extents.MaxPoint.TransformBy(ucs.Inverse());
не очень хорошее решение, так как может получаться вот так:
Я знаю об этом варианте поворота, но пока ничего не придумал. Брать EndPoint не вариант, т.к. я и обычный блок могу повернуть в "такое состояние"
И вот это не очень
points.Add(new Gem.Point3d(pt.X + (offset + 00) * scale, pt.Y + (offset + 00) * scale, plane.PointOnPlane.Z));
наверное стоит задавать векторами, в соответствии с направлением линии на конце которой строится иконка...
Пока что не вижу причин, чтобы переживать в этом месте )

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Пока что не вижу причин, чтобы переживать в этом месте )
Причина может быть в том, что поддерживать такой код сложно - он трудночитаемый. И ещё, если нужно будет внести какие-то правки, то это придётся делать одновременно в нескольких строчках. Есть риск, что где-то забудешь изменить.

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

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

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