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

ADN Club => AutoCAD .NET API => Тема начата: Алексей Кузин от 17-02-2016, 12:57:50

Название: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 17-02-2016, 12:57:50
использую DrawableOverrule для DuctFitting.

Код - C# [Выбрать]
  1. public override void ViewportDraw(Drawable drawable, ViewportDraw vd)
  2.         {
  3.             Solid3d Solidd = new Solid3d();
  4.             Solidd.CreateBox(100,100,100);//для примера
  5.  
  6.             vd.Geometry.Draw(Solidd);
  7.  
  8.             Solidd.Dispose();
  9.  
  10.             base.ViewportDraw(drawable, vd);
  11.         }

в отображении "2d Wireframe"  всё хорошо. стоит переключиться на "Shaded" или любой другой - солид пропадает и начинает вести себя неадекватно.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Привалов Дмитрий от 17-02-2016, 13:44:53
солид пропадает и начинает вести себя неадекватно.
неадекватно это как?

попробуй
//Solidd.Dispose();

или
base.ViewportDraw(drawable, vd);
Solidd.Dispose();
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 17-02-2016, 14:01:26
LmRArtist
Отформатируй код, как указано у меня в подписи.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 17-02-2016, 14:14:42
Цитировать
неадекватно это как?

Например: переключаю на "Shaded" - пропал.   делаю OBJRELUPDATE - появился.   масштабирую, переключаю проекции - пропадает.

перенос Dispose() не помог    :( :(

а если Dispose()  убрать вовсе - проблема вроде как решается. Но не думаю что если убрать dispose() хорошая идея.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 17-02-2016, 14:20:49
Попробуй вместо:
Код - C# [Выбрать]
  1. vd.Geometry.Draw(Solidd);
использовать:
Код - C# [Выбрать]
  1. Solidd.ViewportDraw(vd);
Скорее всего не поможет и скорее всего это ограничение, которое накладывает DrawableOverrule.
Если подготовишь тестовый проект - отправлю в ADN DevHelp. Возможно они смогут помочь.

Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 17-02-2016, 14:26:24
Цитировать
Попробуй вместо:
Код - C# [Выбрать]
vd.Geometry.Draw(Solidd);
использовать:
Код - C# [Выбрать]
Solidd.ViewportDraw(vd);
Скорее всего не поможет и скорее всего это ограничение, которое накладывает DrawableOverrule.

не помогло. перестало отображать даже в "2D Wireframe"
Название: Re: DrawableOverrule и Solid3d
Отправлено: Привалов Дмитрий от 17-02-2016, 14:38:16
убрать вовсе - проблема вроде как решается. Но не думаю что если убрать dispose() хорошая идея.
На самом деле Dispose() это несколько сложная тема. Сложнее, чем кажется на первый взгляд.
И описана не очень хорошо.

Для разных объектов:
1 нужно вызывать обязательно
2 можно проигнорировать
3 управляется транзакцией
4 нельзя вызывать, т.к. управляется автокадом.
5 необходимо предотвратить вызов

в твоем случае, возможно 4-5
в 5 случае, возможно нужно вынести из метода. И не вызывать Dispose
static Solid3d Solidd = new Solid3d();
Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 17-02-2016, 16:22:15
добавил cash.

Код - C# [Выбрать]
  1. Dictionary<long, Solid3d> cash = new Dictionary<long, Solid3d>();
  2.  
  3.         public override void ViewportDraw(Drawable drawable, ViewportDraw vd)
  4.         {
  5.             Solid3d Solidd = new Solid3d();
  6.             Solidd.CreateBox(100, 100, 100);//для примера
  7.  
  8.             long key = drawable.Id.Handle.Value;
  9.             if (!cash.ContainsKey(key))
  10.                 cash.Add(key, Solidd);
  11.             else
  12.                 cash[key] = Solidd;
  13.  
  14.             vd.Geometry.Draw(Solidd);
  15.  
  16.             base.ViewportDraw(drawable, vd);
  17.         }

Возникают пропадания когда приближаю/отдаляю объекты.  В остальном вроде работоспособно, спасибо Дмитрию за советы  8)
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 17-02-2016, 18:31:31
Пару замечаний по коду.
1) А почему cash не static?
2) Если уж ты обнаружил, что cash.ContainsKey(key), то зачем вызывать Solidd.CreateBox(100, 100, 100), если этот объект у тебя уже есть в cash и ты можешь им воспользоваться?
3) Вместо drawable.Id.Handle.Value лучше пользоваться drawable.Id (т.е. ObjectId). На случай, когда у тебя открыты несколько чертежей.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 17-02-2016, 21:22:25
Я сделал тестовый проект, записал видео и отправил вопрос в ADN DevHelp.
Подозреваю, что нормально Solid3D может отрисовываться в VisualStyle != 2DWireFrame только в случае если он Database Resident (т.е. содержится в чертеже). В данном случае это не так.
Когда будет ответ - сообщу.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 18-02-2016, 15:15:03
Спасибо, Александр.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 18-02-2016, 15:22:00
Спасибо, Александр.
Хотел у тебя уточнить. У тебя именно так появляются и пропадают "ящики", как у меня на видео:

Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 18-02-2016, 15:41:36
Да. именно так как у вас на видео.
Есть подозрение что при scale есть определенные участки (уровни детализации). И нужно сохранять Solid3d в cash для каждого из этих участков. Если вы понимаете о чем речь. Возможно я не прав.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 18-02-2016, 15:48:53
И нужно сохранять Solid3d в cash для каждого из этих участков.
Ну это был бы уже совсем перебор. И так их плодится слишком много, с учетом того, что в нормальной ситуации в конце ViewportDraw/WorldDraw для них должен вызываться Dispose().
Пока из ADN DevHelp мне предложили при включении/выключении Overruling запускать команду Regen3:
Код - C# [Выбрать]
  1. doc.SendStringToExecute("_REGEN3\n", true, false, false);
На всякий случай попробуй, но думаю что это из другой оперы. А сейчас проверить у меня возможности нет.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 18-02-2016, 16:04:44
Цитировать
Ну это был бы уже совсем перебор.
тоже так думаю.

Код - C# [Выбрать]
  1. doc.SendStringToExecute("_REGEN3\n", true, false, false);

REGEN3 спасает конечно ситуацию, если рассматривать вариант когда Solid3d создается каждый раз. в этом случае команда REGEN3 вызывает перерисовку и Solid3d будет подменяться в cash. (к слову для "старого" Solid3d который был в cash вызываю dispose())

Цитировать
при включении/выключении Overruling
не совсем корректно только в этих ситуациях будет вызывать. Желательно чтобы при включенном Overruling корректно работало масштабирование, а оно не всегда вызывает перерисовку...  :-\ :-\ :-\
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 18-02-2016, 16:26:20
REGEN3 спасает конечно ситуацию, если рассматривать вариант когда Solid3d создается каждый раз. в этом случае команда REGEN3 вызывает перерисовку и Solid3d будет подменяться в cash. (к слову для "старого" Solid3d который был в cash вызываю dispose())
Не понял. Ты внутри ViewportDraw вызываешь запуск команды REGEN3? Это не годится в любом случае.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Дмитрий Загорулькин от 18-02-2016, 16:41:19
А чем эта команда от обычного REGEN отличается?
Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 18-02-2016, 16:46:12
конечно не внутри.

Вот вариант кода, когда подменяется Solid3d каждый раз.
Код - C# [Выбрать]
  1. static Dictionary<ObjectId, Solid3d> cash = new Dictionary<ObjectId, Solid3d>();
  2.  
  3.         public override void ViewportDraw(Drawable drawable, ViewportDraw vd)
  4.         {
  5.             Solid3d Solidd = new Solid3d();
  6.             Solidd.CreateBox(100, 100, 100);//для примера
  7.  
  8.             ObjectId key = drawable.Id;
  9.             if (!cash.ContainsKey(key))
  10.                 cash.Add(key, Solidd);
  11.             else
  12.             {
  13.                 cash[key].Dispose();
  14.                 cash[key] = Solidd;
  15.             }
  16.  
  17.             vd.Geometry.Draw(Solidd);
  18.  
  19.             base.ViewportDraw(drawable, vd);
  20.         }

В такой ситуации при каждом вызове REGEN3 - запускается перерисовка и вызывается метод ViewportDraw.
Solid3d после вызова REGEN3 появляется. Но стоит масштабировать и Solid3d пропадает.
Именно исходя из этого я начал думать что нужно хранить объекты в памяти для каждого уровня детализации.
Проверил теорию так - сохраняю в памяти все объекты , потому как не нашел способ определения этих уровней детализации.
Код - C# [Выбрать]
  1. static Dictionary<ObjectId, List<Solid3d>> cash = new Dictionary<ObjectId, List<Solid3d>>();
  2.  
  3.         public override void ViewportDraw(Drawable drawable, ViewportDraw vd)
  4.         {
  5.             Solid3d Solidd = new Solid3d();
  6.             Solidd.CreateBox(100, 100, 100);//для примера
  7.  
  8.             ObjectId key = drawable.Id;
  9.             if (!cash.ContainsKey(key))
  10.                 cash.Add(key, new List<Solid3d>());
  11.            
  12.             cash[key].Add(Solidd);
  13.  
  14.             vd.Geometry.Draw(Solidd);
  15.  
  16.             base.ViewportDraw(drawable, vd);
  17.         }

При масштабировании перестал пропадать Solid3d (по крайне мере сколько успел посмотреть до падения Автокада  :D)
этот пример конечно не работоспособен. Сделал чтобы проверить теорию...
Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 18-02-2016, 16:57:55
Цитировать
А чем эта команда от обычного REGEN отличается?

точно не знаю чем именно. Но REGEN3 вызывает перерисовку, а REGEN - нет.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 18-02-2016, 17:07:53
А чем эта команда от обычного REGEN отличается?
Команда недокументированная. Судя по всему отличие от REGEN в том, что REGEN работает только с примитивами в базе данных, а REGEN3 и с транзитной графикой - заставляет её перерисовываться.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 18-02-2016, 18:36:37
Если drawing сохранить, то при масштабировании Solid3d пропадать не будет.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 18-02-2016, 19:55:30
Если drawing сохранить, то при масштабировании Solid3d пропадать не будет.
Не понял. Поясни о чем ты?
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 19-02-2016, 00:41:10
Так. Добрался до компа и проверил что даёт _REGEN3:
Код - C# [Выбрать]
  1. // (C) Copyright 2016 by  
  2. //
  3. using System;
  4. using System.Collections.Generic;
  5. using Autodesk.AutoCAD.Runtime;
  6. using Autodesk.AutoCAD.ApplicationServices;
  7. using Autodesk.AutoCAD.DatabaseServices;
  8. using Autodesk.AutoCAD.Geometry;
  9. using Autodesk.AutoCAD.GraphicsSystem;
  10.  
  11. using Autodesk.AutoCAD.EditorInput;
  12. using AcGi = Autodesk.AutoCAD.GraphicsInterface;
  13.  
  14. // This line is not mandatory, but improves loading performances
  15. [assembly: CommandClass(typeof(Rivilis.MyCommands))]
  16.  
  17. namespace Rivilis
  18. {
  19.   public class MyCommands
  20.   {
  21.     [CommandMethod("S3DOver")]
  22.     public void CmdSimpleOverrule()
  23.     {
  24.       if (_overrule == null)
  25.       {
  26.         _overrule = new Solid3dOverrule();
  27.         Overrule.AddOverrule(RXClass.GetClass(typeof(Circle)), _overrule, false);
  28.       }
  29.       else
  30.       {
  31.         Overrule.RemoveOverrule(RXClass.GetClass(typeof(Circle)), _overrule);
  32.         _overrule = null;
  33.       }
  34.       Application.DocumentManager.MdiActiveDocument.Editor.Regen();
  35.       Application.DocumentManager.MdiActiveDocument.SendStringToExecute("_REGEN3 ", true, false, false);
  36.     }
  37.     private static Solid3dOverrule _overrule = null;
  38.   }
  39.   public class Solid3dOverrule : AcGi.DrawableOverrule
  40.   {
  41.     public Dictionary<ObjectId, Solid3d> cash = null;
  42.  
  43.     public override bool WorldDraw(AcGi.Drawable drawable, AcGi.WorldDraw wd)
  44.     {
  45.       base.WorldDraw(drawable, wd);
  46.       return false;
  47.     }
  48.     public override void ViewportDraw(AcGi.Drawable drawable, AcGi.ViewportDraw vd)
  49.     {
  50.       base.ViewportDraw(drawable, vd);
  51.       if (cash == null) cash = new Dictionary<ObjectId, Solid3d>();
  52.       Solid3d sol = new Solid3d();
  53.       if (!cash.ContainsKey(drawable.Id))
  54.       {
  55.         sol.CreateBox(100, 100, 100);
  56.         Circle pt = drawable as Circle;
  57.         if (pt != null) {
  58.           sol.TransformBy(Matrix3d.Displacement(pt.Center.GetAsVector()));
  59.         }
  60.         cash.Add(drawable.Id, sol);
  61.      }
  62.      else
  63.      {
  64.        sol = cash[drawable.Id];
  65.      }
  66.      vd.Geometry.Draw(sol);
  67.     }
  68.   }
  69. }

Вот видео:


Кубики перестали пропадать. Хм... Проверил в AutoCAD 2015 и 2016 - всё чисто.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 19-02-2016, 11:09:48
Цитата: LmRArtist от 18-02-2016, 18:36:37
Если drawing сохранить, то при масштабировании Solid3d пропадать не будет.
Не понял. Поясни о чем ты?

создаем новый drawing - рисуем - появляются пропадания при масштабировании.
Сохраняем drawing.
Переоткрываем его - рисуем, теперь при масштабировании пропадания отсутствуют.
(Повторилось несколько раз, но не всегда это срабатывает) - возможно из-за этого у вас пропадания перестали появляться.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 19-02-2016, 11:26:13
Ваш код работает. буду разбираться что у меня не так. Очень странно кстати.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 19-02-2016, 14:11:16
Задал вопрос почему пропадают Solid3D если вызвать для них Dispose() в WorldDraw/ViewportDraw и получил ожидаемый ответ:
Цитировать
Вы должны хранить Solid3D в памяти. Это ожидаемое (запланированное) поведение. AutoCAD в различных условиях сохраняет Drawable в своем списке для оптимального отображения. Если Solid3D удален из памяти, то AutoCAD не сможет его показать.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 19-02-2016, 14:35:58
Всё понятно. Спасибо за помощь.
Кстати при вашем варианте падает автокад, из-за того что для Solid3d не вызывается Dispose().   в Output валит сообщения - "Forgot to call Dispose? (Autodesk.AutoCAD.DatabaseServices.Solid3d): DisposableWrapper"
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 19-02-2016, 15:30:21
Кстати при вашем варианте падает автокад, из-за того что для Solid3d не вызывается Dispose().   в Output валит сообщения - "Forgot to call Dispose? (Autodesk.AutoCAD.DatabaseServices.Solid3d): DisposableWrapper"
Я в курсе. Это лишь тестовый пример. В какой момент вызывать Dispose нужно продумать.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Привалов Дмитрий от 19-02-2016, 15:45:39
В какой момент вызывать Dispose нужно продумать.
Еще неплохо бы выяснить чем отличаются:
Application.DocumentManager.MdiActiveDocument.Editor.Regen();
Application.DocumentManager.MdiActiveDocument.SendStringToExecute("_REGEN3 ", true, false, false);
_regen
_redrawall
_regenall
RecordGraphicsModified(true);
...и возможно что-то еще


Слишком много их развелось для "освежения вида".
Можно ли ADN потрясти на этот счет?
....кстати словил еще один случай когда помог только RecordGraphicsModified(true); для отображения правильного цвета, после изменения цвета у размера в 2008 автокаде.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Дмитрий Загорулькин от 19-02-2016, 15:55:16
У таблиц и у размеров, как у сложных объектов, есть еще свои методы обновления. У размера это RecomputeDimensionBlock.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 19-02-2016, 16:49:15
Можно ли ADN потрясти на этот счет?
Не вижу в этом смысла. Исчерпывающей информации не будет, так что в любом случае приходится экспериментировать.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 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 объектов - полёт нормальный.
Так же нужно добавить очистку кеша при удалении объектов и наверное еще ряде случаев, надо продумать.+
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 21-02-2016, 19:23:10
Так же нужно добавить очистку кеша при удалении объектов и наверное еще ряде случаев, надо продумать.+
При удалении объектов я бы не советовал очищать кеш. Причина в том, что команды OOPS, U и UNDO могут восстановить этот объект, а у тебя относящийся к нему Solid3d уже удалён.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Алексей Кузин от 24-02-2016, 15:02:30
Небольшой вопрос по команде REGEN3.
Может кто подскажет есть что то подобное, но чтобы не вызывалось для всего дровинга, а конкретно по объектом. В частности Solid3d которых нет в базе.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Привалов Дмитрий от 24-02-2016, 19:04:26
Может кто подскажет есть что то подобное, но чтобы не вызывалось для всего дровинга, а конкретно по объектом. В частности Solid3d которых нет в базе.
попробуй вызывать метод RecordGraphicsModified(true);
на объектах, для которых ты добавил Solid3d
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 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();
Название: Re: DrawableOverrule и Solid3d
Отправлено: Привалов Дмитрий от 24-02-2016, 21:46:32
REGEN оптимизирован чтобы перерисовывать только те примитивы, которые отмечены как измененные.
RecordGraphicsModified(true) как-раз помечает, что entity изменен и его нужно перерисовать.
По идее после каждого изменения свойства, влияющего на отображение, например цвета, примитив должен помечаться как измененный.
Но это происходит не всегда, возможно недоделки API, или подразумевается особая логика.
Скорее всего DrawableOverrule не помечает примитив как измененный.
Название: Re: DrawableOverrule и Solid3d
Отправлено: bender от 06-06-2018, 17:03:11
А какова вероятность того, что в нескольких одновременно открытых чертежах будут разные объекты с одинаковым id? Может лучше использовать не id, а handle?
Название: Re: DrawableOverrule и Solid3d
Отправлено: Дмитрий Загорулькин от 06-06-2018, 17:05:23
А какова вероятность того, что в нескольких одновременно открытых чертежах будут разные объекты с одинаковым id?
Насколько мне известно, ObjectId уникально в рамках сессии.
Может лучше использовать не id, а handle?
А вот Handle как раз-таки могут быть одинаковыми в разных чертежах.

Вот тут обсуждали: http://adn-cis.org/forum/index.php?topic=7199.msg21267#msg21267
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 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.
Название: Re: DrawableOverrule и Solid3d
Отправлено: bender от 06-06-2018, 19:10:59
Цитировать
Но уникальность не означает, что их следует сравнивать при помощи '=='
А что в таком случае будет возвращать для двух ObjectId, у которых одинаковые числовые значения?
Код - C# [Выбрать]
  1. cash.ContainsKey(id)
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 06-06-2018, 19:12:55
Цитировать
Но уникальность не означает, что их следует сравнивать при помощи '=='
А что в таком случае будет возвращать для двух ObjectId, у которых одинаковые числовые значения?
Код - C# [Выбрать]
  1. cash.ContainsKey(id)

Очевидно true. Так что проверять теоретически нужно не так.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Дмитрий Загорулькин от 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.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 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. }
Название: Re: DrawableOverrule и Solid3d
Отправлено: Дмитрий Загорулькин от 06-06-2018, 19:25:07
А зачем нам привязка к базе данных? Андрей же откопал в документации, что в ObjectId ссылается на адрес в памяти. Соответственно, он может быть только один на один объект.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 06-06-2018, 19:33:50
Андрей же откопал в документации, что в ObjectId ссылается на адрес в памяти. Соответственно, он может быть только один на один объект.
Там всё-таки всё хитрее. Я бы не стал полагаться на это.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Дмитрий Загорулькин от 06-12-2018, 16:41:24
Уже несколько раз перечитал всю тему, экспериментирую, но никак не могу нащупать: какой должен быть порядок действий, если объект был изменён?
Вот, например. Есть у нас объект, мы его перерисовали кубиком, кубик поместили в кэш. Теперь при каждой перерисовке мы берём кубик из кэша, а не создаём новый. Но, предположим, что габариты объекта поменялись и теперь надо показывать кубик другого размера. Как поступить в этом случае? Старый кубик из кэша удалять? Или ничего не удалять, а создать просто новый и закинуть в кэш? Вызывать ли команду _REGEN3 при этом?
Что-то никак не могу подружиться с этим механизмом. Постоянно теряется графика, если объект изменять.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Александр Ривилис от 06-12-2018, 18:21:03
Старый кубик из кэша удалять?
Если он не используется для других примитивов - удалять. И рисовать новый и закидывать в кэш. Думаю что так.
Название: Re: DrawableOverrule и Solid3d
Отправлено: Дмитрий Загорулькин от 06-12-2018, 21:06:02
Если сразу удалять, то почему-то возникают проблемы с отображением. Решил не удалять, а помечать как неиспользуемые. Пока что придумал, что удалять их буду в событии Database.DatabaseToBeDestroyed. Попробовал в событии Application.BeginQuit - ловил стабильный фатал. Сейчас работает как надо и вроде как проблем нет.
Немного напрягает, что неиспользуемые объекты будут висеть в памяти пока чертёж не закроют, но пока другого более подходящего момента не придумал.