DrawableOverrule и Solid3d

Автор Тема: DrawableOverrule и Solid3d  (Прочитано 19522 раз)

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

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DrawableOverrule и Solid3d
« Ответ #30 : 19-02-2016, 16:49:15 »
Можно ли ADN потрясти на этот счет?
Не вижу в этом смысла. Исчерпывающей информации не будет, так что в любом случае приходится экспериментировать.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей КузинАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 116
  • Карма: 8
Re: DrawableOverrule и Solid3d
« Ответ #31 : 19-02-2016, 17:51:13 »
сразу не увидел - у вас в коде всегда создается Solid3d. Из-за этого появляются объекты, для которых нужно вызывать Dispose().
Код - C# [Выбрать]
  1. [CommandMethod("S3DOver")]
  2.         public void CmdSimpleOverrule()
  3.         {
  4.           if (_overrule == null)
  5.           {
  6.             _overrule = new Solid3dOverrule();
  7.             ObjectOverrule.AddOverrule(RXClass.GetClass(typeof(Circle)), _overrule, false);
  8.           }
  9.           else
  10.           {
  11.             ObjectOverrule.RemoveOverrule(RXClass.GetClass(typeof(Circle)), _overrule);
  12.             _overrule = null;
  13.           }
  14.           Application.DocumentManager.MdiActiveDocument.Editor.Regen();
  15.           Application.DocumentManager.MdiActiveDocument.SendStringToExecute("_REGEN3 ", true, false, false);
  16.         }
  17.  
  18.         private static Solid3dOverrule _overrule = null;
  19.  
  20.         public class Solid3dOverrule : Autodesk.AutoCAD.GraphicsInterface.DrawableOverrule
  21.         {
  22.             public Dictionary<ObjectId, Solid3d> cash = null;
  23.  
  24.             public override bool WorldDraw(Autodesk.AutoCAD.GraphicsInterface.Drawable drawable, Autodesk.AutoCAD.GraphicsInterface.WorldDraw wd)
  25.             {
  26.                 base.WorldDraw(drawable, wd);
  27.                 return false;
  28.             }
  29.             public override void ViewportDraw(Autodesk.AutoCAD.GraphicsInterface.Drawable drawable, Autodesk.AutoCAD.GraphicsInterface.ViewportDraw vd)
  30.             {
  31.                 base.ViewportDraw(drawable, vd);
  32.                 if (cash == null) cash = new Dictionary<ObjectId, Solid3d>();
  33.                 Solid3d sol = null;
  34.                 if (!cash.ContainsKey(drawable.Id))
  35.                 {
  36.                     sol = new Solid3d();
  37.                     sol.CreateBox(100, 100, 100);
  38.                     Circle pt = drawable as Circle;
  39.                     if (pt != null)
  40.                     {
  41.                         sol.TransformBy(Matrix3d.Displacement(pt.Center.GetAsVector()));
  42.                     }
  43.                     cash.Add(drawable.Id, sol);
  44.                 }
  45.                 else
  46.                 {
  47.                     sol = cash[drawable.Id];
  48.                 }
  49.                 vd.Geometry.Draw(sol);
  50.             }
  51.         }

~1000 объектов - полёт нормальный.
Так же нужно добавить очистку кеша при удалении объектов и наверное еще ряде случаев, надо продумать.+

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DrawableOverrule и Solid3d
« Ответ #32 : 21-02-2016, 19:23:10 »
Так же нужно добавить очистку кеша при удалении объектов и наверное еще ряде случаев, надо продумать.+
При удалении объектов я бы не советовал очищать кеш. Причина в том, что команды OOPS, U и UNDO могут восстановить этот объект, а у тебя относящийся к нему Solid3d уже удалён.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей КузинАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 116
  • Карма: 8
Re: DrawableOverrule и Solid3d
« Ответ #33 : 24-02-2016, 15:02:30 »
Небольшой вопрос по команде REGEN3.
Может кто подскажет есть что то подобное, но чтобы не вызывалось для всего дровинга, а конкретно по объектом. В частности Solid3d которых нет в базе.

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: DrawableOverrule и Solid3d
« Ответ #34 : 24-02-2016, 19:04:26 »
Может кто подскажет есть что то подобное, но чтобы не вызывалось для всего дровинга, а конкретно по объектом. В частности Solid3d которых нет в базе.
попробуй вызывать метод RecordGraphicsModified(true);
на объектах, для которых ты добавил Solid3d

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DrawableOverrule и Solid3d
« Ответ #35 : 24-02-2016, 19:15:45 »
Получил ответ из ADN DevHelp по поводу отличия REGEN и REGEN3. REGEN3 удаляет весь графический кеш и перерисовывает всю геометрию по новой. REGEN оптимизирован чтобы перерисовывать только те примитивы, которые отмечены как измененные.

Ну и вот этот код вроде бы делает то, что делает команда REGEN3 в AutoCAD 2015 и новее:
Код - C# [Выбрать]
  1. Document doc = Application.DocumentManager.MdiActiveDocument;
  2. Autodesk.AutoCAD.GraphicsSystem.Manager mpManager = doc.GraphicsManager;
  3. Autodesk.AutoCAD.GraphicsSystem.KernelDescriptor descriptor =
  4.                   new Autodesk.AutoCAD.GraphicsSystem.KernelDescriptor();
  5. descriptor.addRequirement(Autodesk.AutoCAD.UniqueString.Intern("3D Drawing"));
  6. Autodesk.AutoCAD.GraphicsSystem.GraphicsKernel kernal =
  7.                   Autodesk.AutoCAD.GraphicsSystem.Manager.AcquireGraphicsKernel(descriptor);
  8.  
  9. Autodesk.AutoCAD.GraphicsSystem.Model Model = mpManager.GetDBModel(kernal);
  10.  
  11. Model.Invalidate(Autodesk.AutoCAD.GraphicsSystem.InvalidationHint.InvalidateAll);
  12.  
  13. Application.DocumentManager.MdiActiveDocument.Editor.Regen();
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: DrawableOverrule и Solid3d
« Ответ #36 : 24-02-2016, 21:46:32 »
REGEN оптимизирован чтобы перерисовывать только те примитивы, которые отмечены как измененные.
RecordGraphicsModified(true) как-раз помечает, что entity изменен и его нужно перерисовать.
По идее после каждого изменения свойства, влияющего на отображение, например цвета, примитив должен помечаться как измененный.
Но это происходит не всегда, возможно недоделки API, или подразумевается особая логика.
Скорее всего DrawableOverrule не помечает примитив как измененный.

Оффлайн bender

  • ADN Club
  • **
  • Сообщений: 62
  • Карма: 4
Re: DrawableOverrule и Solid3d
« Ответ #37 : 06-06-2018, 17:03:11 »
А какова вероятность того, что в нескольких одновременно открытых чертежах будут разные объекты с одинаковым id? Может лучше использовать не id, а handle?

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: DrawableOverrule и Solid3d
« Ответ #38 : 06-06-2018, 17:05:23 »
А какова вероятность того, что в нескольких одновременно открытых чертежах будут разные объекты с одинаковым id?
Насколько мне известно, ObjectId уникально в рамках сессии.
Может лучше использовать не id, а handle?
А вот Handle как раз-таки могут быть одинаковыми в разных чертежах.

Вот тут обсуждали: http://adn-cis.org/forum/index.php?topic=7199.msg21267#msg21267

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DrawableOverrule и Solid3d
« Ответ #39 : 06-06-2018, 18:17:35 »
А какова вероятность того, что в нескольких одновременно открытых чертежах будут разные объекты с одинаковым id? Может лучше использовать не id, а handle?
А что понимать под id? Если ObjectId, то они уникальны, так как хранят в себе информацию о базе данных: ObjectId.Database
Но уникальность не означает, что их следует сравнивать при помощи '==', так как:
Код - C# [Выбрать]
  1. // Autodesk.AutoCAD.DatabaseServices.ObjectId
  2. public static bool operator ==(ObjectId a, ObjectId b)
  3. {
  4.         return a.m_id == b.m_id;
  5. }
Т.е. сравниваются только числовые значения ObjectId.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн bender

  • ADN Club
  • **
  • Сообщений: 62
  • Карма: 4
Re: DrawableOverrule и Solid3d
« Ответ #40 : 06-06-2018, 19:10:59 »
Цитировать
Но уникальность не означает, что их следует сравнивать при помощи '=='
А что в таком случае будет возвращать для двух ObjectId, у которых одинаковые числовые значения?
Код - C# [Выбрать]
  1. cash.ContainsKey(id)

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DrawableOverrule и Solid3d
« Ответ #41 : 06-06-2018, 19:12:55 »
Цитировать
Но уникальность не означает, что их следует сравнивать при помощи '=='
А что в таком случае будет возвращать для двух ObjectId, у которых одинаковые числовые значения?
Код - C# [Выбрать]
  1. cash.ContainsKey(id)

Очевидно true. Так что проверять теоретически нужно не так.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: DrawableOverrule и Solid3d
« Ответ #42 : 06-06-2018, 19:14:34 »
Надо смотреть как ContainsKey сравнивает ключи, возможно, что не с помощью ==, а через Equals
https://github.com/Microsoft/referencesource/blob/master/mscorlib/system/collections/generic/dictionary.cs

Код - C# [Выбрать]
  1. public bool ContainsKey(TKey key) {
  2.             return FindEntry(key) >= 0;
  3. }

Код - C# [Выбрать]
  1. private int FindEntry(TKey key) {
  2.             if( key == null) {
  3.                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
  4.             }
  5.  
  6.             if (buckets != null) {
  7.                 int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
  8.                 for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next) {
  9.                     if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i;
  10.                 }
  11.             }
  12.             return -1;
  13.         }

То есть, по хеш-коду и с помощью Equals.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DrawableOverrule и Solid3d
« Ответ #43 : 06-06-2018, 19:18:26 »
Надо смотреть как ContainsKey сравнивает ключи, возможно, что не с помощью ==, а через Equals
Не поможет. Я посмотрел все методы ObjectId. Ни один из них не использует сравнение Database:
Извините, вам запрещён просмотр содержимого спойлеров.

Код - C# [Выбрать]
  1. [return: MarshalAs(UnmanagedType.U1)]
  2. public sealed override bool Equals(object obj)
  3. {
  4.         if (!(obj is ObjectId))
  5.         {
  6.                 return false;
  7.         }
  8.         ObjectId objectId = (ObjectId)obj;
  9.         ObjectId objectId2 = this;
  10.         return objectId2.m_id == objectId.m_id;
  11. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: DrawableOverrule и Solid3d
« Ответ #44 : 06-06-2018, 19:25:07 »
А зачем нам привязка к базе данных? Андрей же откопал в документации, что в ObjectId ссылается на адрес в памяти. Соответственно, он может быть только один на один объект.