DrawJig. Можно ли "спрятать" объект?

Автор Тема: DrawJig. Можно ли "спрятать" объект?  (Прочитано 8748 раз)

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

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

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

Приложил gif как это выглядит.
Для текущего примера - можно ли во время работы DrawJig не отображать выбранный размер?

Отмечено как Решение Александр Пекшев aka Modis 02-06-2015, 00:23:09

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #1 : 01-06-2015, 22:05:09 »
Если в двух словах, то нужно:
1) сделать клон примитива
2) сделать оригинал невидимым
3) в DrawJig работать с клоном
4) при нормальном выходе из DrawJig обменять оригинал и клон местами.
Как-то так, но не тестировал:
Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.GraphicsInterface;
  7. using Autodesk.AutoCAD.Runtime;
  8.  
  9. namespace DrawJigQuestion
  10. {
  11.   public class Class1
  12.   {
  13.     [CommandMethod("DrawJigQuestion")]
  14.     public static void Main()
  15.     {
  16.       var doc = Application.DocumentManager.MdiActiveDocument;
  17.       var db = doc.Database;
  18.       var ed = doc.Editor;
  19.       Entity en = null;
  20.       var peo = new PromptEntityOptions("\nSelect rotated dimension: ");
  21.       peo.SetRejectMessage("\nWrong!");
  22.       peo.AddAllowedClass(typeof(RotatedDimension), false);
  23.       var per = ed.GetEntity(peo);
  24.       if (per.Status != PromptStatus.OK) return;
  25.       var jig = new DJig(); // JIg
  26.       using (Entity enOrig = per.ObjectId.Open(OpenMode.ForWrite) as Entity)
  27.       {
  28.         en = enOrig.Clone() as Entity;
  29.         enOrig.Visible = false;
  30.       }
  31.       doc.TransactionManager.FlushGraphics();
  32.       var rs = jig.StartJig(en); // Jig result
  33.       if (rs.Status != PromptStatus.OK)
  34.       {
  35.         using (Entity enOrig = per.ObjectId.Open(OpenMode.ForWrite) as Entity)
  36.         {
  37.           enOrig.Visible = true;
  38.         }
  39.       }
  40.       else
  41.       {
  42.         using (Entity enOrig = per.ObjectId.Open(OpenMode.ForWrite) as Entity)
  43.         {
  44.           enOrig.Visible = true;
  45.           enOrig.HandOverTo(en,true,true);
  46.         }
  47.       }
  48.       doc.TransactionManager.FlushGraphics();
  49.     }
  50.   }
  51.  
  52.   public class DJig : DrawJig
  53.   {
  54.     private Point3d _prevPoint;
  55.     private Point3d _currPoint;
  56.     private Entity _dimension;
  57.  
  58.     public PromptResult StartJig(Entity en)
  59.     {
  60.       _dimension = en;
  61.       _prevPoint = new Point3d(0, 0, 0);
  62.       return Application.DocumentManager.MdiActiveDocument.Editor.Drag(this);
  63.     }
  64.  
  65.     protected override SamplerStatus Sampler(JigPrompts prompts)
  66.     {
  67.       var jppo = new JigPromptPointOptions("\nPoint: ")
  68.       {
  69.         UserInputControls = (UserInputControls.Accept3dCoordinates
  70.                              | UserInputControls.NoZeroResponseAccepted
  71.                              | UserInputControls.AcceptOtherInputString
  72.                              | UserInputControls.NoNegativeResponseAccepted)
  73.       };
  74.       var rs = prompts.AcquirePoint(jppo);
  75.       _currPoint = rs.Value;
  76.       if (rs.Status != PromptStatus.OK) return SamplerStatus.Cancel;
  77.       if (!CursorHasMoved()) return SamplerStatus.NoChange;
  78.       _prevPoint = _currPoint;
  79.       return SamplerStatus.OK;
  80.     }
  81.     private bool CursorHasMoved()
  82.     {
  83.       return _currPoint.DistanceTo(_prevPoint) > 1e-6;
  84.     }
  85.  
  86.     protected override bool WorldDraw(WorldDraw draw)
  87.     {
  88.       var dim = (Dimension)_dimension;
  89.  
  90.       var pts = new Point3dCollection();
  91.       dim.GetStretchPoints(pts);
  92.       var pt2 = pts[1];
  93.       dim.MoveStretchPointsAt(new IntegerCollection { 1 }, pt2.GetVectorTo(_currPoint));
  94.  
  95.       draw.Geometry.Draw(dim);
  96.  
  97.       return true;
  98.     }
  99.   }
  100. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #2 : 01-06-2015, 22:28:13 »
Но вот эта часть мне не нравится категорически:
Код - C# [Выбрать]
  1.     dim.MoveStretchPointsAt(new IntegerCollection { 1 }, pt2.GetVectorTo(_currPoint));
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #3 : 02-06-2015, 00:22:35 »
Цитировать
enOrig.Visible = true;
Вот так-то - век живи - век учись! Я даже и не знал почему-то, что у примитива есть такой параметр) Мне казалось, что решение более сложное. Вопрос заключался именно в этом
Цитировать
Но вот эта часть мне не нравится категорически:
Разве есть другие варианты? Я об этом спрашивал еще очень давно и получив такое решение, оказавшееся рабочим, успокоился

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #4 : 02-06-2015, 00:31:02 »
Вот тебе еще один вариант:
Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.GraphicsInterface;
  7. using Autodesk.AutoCAD.Runtime;
  8.  
  9. namespace DrawJigQuestion
  10. {
  11.   public class Class1
  12.   {
  13.     [CommandMethod("DrawJigQuestion")]
  14.     public static void Main()
  15.     {
  16.       var doc = Application.DocumentManager.MdiActiveDocument;
  17.       var db = doc.Database;
  18.       var ed = doc.Editor;
  19.       RotatedDimension en = null;
  20.       var peo = new PromptEntityOptions("\nSelect rotated dimension: ");
  21.       peo.SetRejectMessage("\nWrong!");
  22.       peo.AddAllowedClass(typeof(RotatedDimension), false);
  23.       var per = ed.GetEntity(peo);
  24.       if (per.Status != PromptStatus.OK) return;
  25.       Point3d pWCS = per.PickedPoint.TransformBy(ed.CurrentUserCoordinateSystem);
  26.       var jig = new DJig(); // JIg
  27.       using (RotatedDimension enOrig = per.ObjectId.Open(OpenMode.ForWrite) as RotatedDimension)
  28.       {
  29.         en = enOrig.Clone() as RotatedDimension;
  30.         enOrig.Visible = false;
  31.         if (pWCS.DistanceTo(en.XLine1Point) < pWCS.DistanceTo(en.XLine2Point))
  32.           jig.firstPoint = true;
  33.       }
  34.       doc.TransactionManager.FlushGraphics();
  35.       var rs = jig.StartJig(en); // Jig result
  36.       using (RotatedDimension enOrig = per.ObjectId.Open(OpenMode.ForWrite) as RotatedDimension)
  37.       {
  38.         enOrig.Visible = true;
  39.         if (rs.Status == PromptStatus.OK)
  40.         {
  41.           if (jig.firstPoint)
  42.             enOrig.XLine1Point = jig._pnew;
  43.           else
  44.             enOrig.XLine2Point = jig._pnew;
  45.         }
  46.       }
  47.       en.Dispose();
  48.       doc.TransactionManager.FlushGraphics();
  49.     }
  50.   }
  51.  
  52.   public class DJig : DrawJig
  53.   {
  54.     private Point3d _prevPoint;
  55.     private Point3d _currPoint;
  56.     private RotatedDimension _dimension;
  57.     public Point3d _pnew;
  58.     public bool firstPoint = false;
  59.     public PromptResult StartJig(RotatedDimension en)
  60.     {
  61.       _dimension = en;
  62.       _prevPoint = new Point3d(0, 0, 0);
  63.       _pnew = _dimension.XLine2Point;
  64.       return Application.DocumentManager.MdiActiveDocument.Editor.Drag(this);
  65.     }
  66.  
  67.     protected override SamplerStatus Sampler(JigPrompts prompts)
  68.     {
  69.       var jppo = new JigPromptPointOptions("\nPoint: ")
  70.       {
  71.         UserInputControls = (UserInputControls.Accept3dCoordinates
  72.                              | UserInputControls.NoZeroResponseAccepted
  73.                              | UserInputControls.AcceptOtherInputString
  74.                              | UserInputControls.NoNegativeResponseAccepted)
  75.       };
  76.       var rs = prompts.AcquirePoint(jppo);
  77.       _currPoint = rs.Value;
  78.       if (rs.Status != PromptStatus.OK) return SamplerStatus.Cancel;
  79.       if (!CursorHasMoved()) return SamplerStatus.NoChange;
  80.       _prevPoint = _currPoint;
  81.       return SamplerStatus.OK;
  82.     }
  83.     private bool CursorHasMoved()
  84.     {
  85.       return _currPoint.DistanceTo(_prevPoint) > 1e-6;
  86.     }
  87.  
  88.     protected override bool WorldDraw(WorldDraw draw)
  89.     {
  90.       var dim = (RotatedDimension)_dimension;
  91.       _pnew = _currPoint;
  92.       Line3d ls = new Line3d(dim.XLine1Point, dim.XLine2Point);
  93.       try {
  94.         PointOnCurve3d pc = ls.GetClosestPointTo(_pnew);
  95.         _pnew = pc.Point;
  96.       }
  97.       catch {
  98.       }
  99.       finally {
  100.         ls.Dispose();
  101.       }
  102.       if (firstPoint)
  103.         dim.XLine1Point = _pnew;
  104.       else
  105.         dim.XLine2Point = _pnew;
  106.       draw.Geometry.Draw(dim);
  107.       return true;
  108.     }
  109.   }
  110. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #5 : 02-06-2015, 01:24:06 »
И еще вопрос - можно ли достичь такого эффекта в самом DrawJig? Если допустим я работаю там с коллекцией объектов и мне нужно "спрятать" один из них в процессе "отрисовки"

Цитировать
Вот тебе еще один вариант:
В вашем варианте выносная линия перемещается только по горизонтали, а не в указанную точку

И еще:
Код - C# [Выбрать]
  1. per.ObjectId.Open(OpenMode.ForWrite)
Студия ругается, что это устаревший вариант (я пробовал на 2010 каде) и нужно использовать GetObject(). Но с GetObject() уже не работает. Видимо нужно через транзакцию работать

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #6 : 02-06-2015, 09:02:32 »
Студия ругается, что это устаревший вариант (я пробовал на 2010 каде) и нужно использовать GetObject(). Но с GetObject() уже не работает. Видимо нужно через транзакцию работать
Не обращай внимание на "ругань студии". Это в большинстве случаев более эффективный чем с транзакцией метод.
В вашем варианте выносная линия перемещается только по горизонтали, а не в указанную точку
Во-первых, не по горизонтали, а по прямой между первоначальными точками выносок. Я это сделал умышленно для того, чтобы показать, что можно и так.
Во-вторых, если тебя это не устраивает - убери строки с 92 по 101 в моём коде.
И еще вопрос - можно ли достичь такого эффекта в самом DrawJig? Если допустим я работаю там с коллекцией объектов и мне нужно "спрятать" один из них в процессе "отрисовки"
Думаю (но не уверен - нужно проверить), если перестать вызывать метод draw.Geometry.Draw(dim); для этого элемента, то он и не будет отрисовываться.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #7 : 17-10-2018, 00:37:48 »
Пришло время оживить эту тему! ))
На самом деле проблема существует давно, но я как-то долго на неё забивал и вот наконец-то дошли руки.

А проблема заключается в том, что при работе Jig не происходит отрисовка изменения размера. Кодов не привожу, так как уверен, что примеры в теме будут давать такой-же эффект. И что самое интересное - я точно помню, что в ранних версиях автокада (2009 - 2012) это все работало! А вот в 2013 и выше - нет.
При этом как-бы не то, что совсем не работает - размер, при движении мышкой, как-то вот дрыгается (можно ловить взглядом. Как-будто их там два одновременно), но не меняет своего положения. Причем после завершения транзакции размер изменяется как положено - сдвигается на то новое значение, которое установилось в Jig (ну или выносные линии размера - не важно).

Уточняю - я пробовал и через SetStretchPoints и через изменение DimLinePoint - разницы нет

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #8 : 17-10-2018, 00:45:18 »
Кодов не привожу, так как уверен, что примеры в теме будут давать такой-же эффект.
Ну тогда будешь разговаривать сам с собой. Если нужна помощь - давай коды (нормальный тестовый проект) и видео того, что у тебя происходит.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #9 : 17-10-2018, 10:06:06 »
Да, насчет отсутствия примеров я погорячился ))
В общем задумка была у меня в следующем:
1. Запускаю транзакцию
2. Открываю размер на запись
3. Запускаю Jig в процессе работы которой меняю размер
4. Если статус работы Jig == Ok, то фиксирую транзакцию
Выглядит примерно так:
Извините, вам запрещён просмотр содержимого спойлеров.

И вот моя "ленивая" идея не работает, так как зрительно ничего не происходит.

После того, как я заменил строки 42-47 на это:
Код - C# [Выбрать]
  1. List<Dimension> dimensions = new List<Dimension>();
  2. foreach (var objectId in psr.Value.GetObjectIds())
  3. {
  4.     if (tr.GetObject(objectId, OpenMode.ForWrite, false) is Dimension dimension)
  5.     {
  6.         var dimClone = (Dimension)dimension.Clone();
  7.         dimension.Visible = false;
  8.         dimensions.Add(dimClone);
  9.     }
  10. }
  11.  
  12. doc.TransactionManager.FlushGraphics();
я получил нужный эффект - размер меняется динамически. Просто вариант с клоном займет немного больше кода, так как я работать буду с несколькими размерами и придется запоминать какой клон от какого объекта-исходника.

Но в этом варианте тоже есть проблема - установка dimension.Visible = false; не имеет эффекта пока не произойдет tr.Commit(). При этом doc.TransactionManager.FlushGraphics(); не помогает

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #10 : 17-10-2018, 10:21:31 »
А если заменить так, то можно и без транзакции работать:
Код - C# [Выбрать]
  1. List<Dimension> dimensions = new List<Dimension>();
  2. foreach (var objectId in psr.Value.GetObjectIds())
  3. {
  4.     using (Dimension dimension = objectId.Open(OpenMode.ForWrite) as Dimension)
  5.     {
  6.         var dimClone = (Dimension)dimension.Clone();
  7.         dimension.Visible = false;
  8.         dimensions.Add(dimClone);
  9.     }
  10. }
  11.  
  12. var jig = new DimLineJustifyJig();
  13. var rs = jig.StartJig(ppr.Value, dimensions);
А потом уже обрабатывать результат Jig. В этом случае объект-исходник нормально скрывается.

Но тогда я не понимаю - как работает TransactionManager.FlushGraphics()? И зачем он? Нет возможности видеть изменения объекта до того, как зафиксируется транзакция?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #11 : 17-10-2018, 12:09:16 »
Но тогда я не понимаю - как работает TransactionManager.FlushGraphics()? И зачем он? Нет возможности видеть изменения объекта до того, как зафиксируется транзакция?
Сначала TransactionManager.QueueForGraphicsFlush , потом TransactionManager.FlushGraphics - должно обновляться:
Цитировать
Flushes the graphics queue to the display.

Normally an entity's graphics are not updated until the entity's changes are committed. In the transaction environment this doesn't occur until the outermost transaction (or, if there are no nested transactions, then the single transaction itself) is ended, so the graphics for all entities in the transactions are not updated until the outermost transaction ends. If a graphics update is desired before the outermost transaction is ended, then the queueForGraphicsFlush() function should be called to queue up all changes made so far followed by a flushGraphics() call to flush all graphics currently queued up out to the display.

 

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

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #12 : 17-10-2018, 12:20:06 »
Сначала TransactionManager.QueueForGraphicsFlush , потом TransactionManager.FlushGraphics - должно обновляться:
О как! И действительно помогло. Добавил в мой первый пример две строчки:
Код - C# [Выбрать]
  1. protected override bool WorldDraw(WorldDraw draw)
  2. {
  3.     _line.StartPoint = _startPoint;
  4.     _line.EndPoint = _currentPoint;
  5.     draw.Geometry.Draw(_line);
  6.     foreach (var dimObj in _dimensions)
  7.     {
  8.         if (dimObj is RotatedDimension rotatedDimension)
  9.         {
  10.             var newPt = _line.GetClosestPointTo(rotatedDimension.DimLinePoint, true);
  11.             rotatedDimension.DimLinePoint = newPt;
  12.             draw.Geometry.Draw(dimObj);
  13.             AcApp.DocumentManager.MdiActiveDocument.TransactionManager.QueueForGraphicsFlush();
  14.             AcApp.DocumentManager.MdiActiveDocument.TransactionManager.FlushGraphics();
  15.         }
  16.     }
  17.  
  18.     return true;
  19. }
и все стало динамически обновляться. Единственная проблема - вариант с клонами работает плавно, а вариант с FlushGraphics как-то "дерганно", некрасиво.
Нужно запомнить на будущее эту тему про FlushGraphics. Спасибо

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #13 : 17-10-2018, 12:22:38 »
Единственная проблема - вариант с клонами работает плавно, а вариант с FlushGraphics как-то "дерганно", некрасиво.
Это как раз понятно, так как идёт опрос всех модифицированных примитивов в транзакции и их обновление.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: DrawJig. Можно ли "спрятать" объект?
« Ответ #14 : 19-10-2018, 15:10:45 »
Если я использую DrawJig для модификации объекта, то возможно ли во время работы DrawJig "спрятать" объект-исходник?
Что-то я не понимаю идею. DrawJig как раз для того и сделан, чтобы показывать объект во время модификации. Если этого не нужно делать - значит не надо просто использовать DrawJig. Зачем он тогда нужен? Или в изначальном вопросе не описан какой-то нюанс?