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

ADN Club => AutoCAD .NET API => Тема начата: Дима_ от 11-06-2015, 14:08:08

Название: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Дима_ от 11-06-2015, 14:08:08
Всем Здравствуйте. Вопрос в следующем - есть рабочий DrawJig который "протягивает" размеры (AlignedDimension) от необходимых точек и есть желание заставить его работать не по команде, а при "тяготении" ручек. Я знаю что MoveGripPointsAt в процессе перемещения работает не с настоящей БД а с клонами объектов, но на последний вызов идет "из под" нормального объекта. Так вот при вызове Editor.Drag() из под переопределенного метода MoveGripPointsAt в процессе перемещения (когда вызываемый ObjectID не валидный) - происходит ФАТАЛ по завершении Jig'а, при том, что, например, просто запрос точки Editor.GetPoint("\nPT: ") - работает. Причем тот-же Jig из отдельной команды, либо из того-же MoveGripPointsAt, но при валидно ObjectID прекрасно работает. Я грешил, что ошибка где-то в районе создания AlignedDimension, но оказалось, что даже создав "пустой", ниего не делающий Jig валится на AcquirePoint. Ниже упрощенный пример, команда test запускает Jig, и переопеделенно перемещение у примитива "точка" - ошибка выявится при включении строки 27:
Код - C# [Выбрать]
  1. module JigTest
  2. open Autodesk.AutoCAD.ApplicationServices
  3. open Autodesk.AutoCAD.Runtime
  4. open Autodesk.AutoCAD.DatabaseServices
  5. open Autodesk.AutoCAD.Geometry
  6. open Autodesk.AutoCAD.EditorInput
  7.  
  8. // сокращение на Editor
  9. let Ed()=Application.DocumentManager.MdiActiveDocument.Editor
  10.  
  11. //класс Jig'а
  12. type JigEmpty()=
  13.   inherit DrawJig()
  14.   override jg.WorldDraw(wd)=true
  15.   override jg.Sampler(jp)=
  16.    jp.AcquirePoint("\nPoint: ")|>ignore //этого достаточно для вызова фатала
  17.    SamplerStatus.OK
  18.  
  19. //класс переопределения ручек
  20. type GrpOver()=
  21.   inherit GripOverrule()
  22.   override ob.MoveGripPointsAt(ent,ic,vct)=
  23.      match ent with  
  24.       | :? DBPoint as point when point.ObjectId.IsValid-> // произойдет когда закончим перетакивание перетащили
  25.         Ed().Drag(new JigEmpty())|>ignore // здесь работает
  26.       | :? DBPoint as point-> // проиcходит при перетаскивании
  27.         //Ed().Drag(new JigEmpty())|>ignore // !!!! раскоментирование данной строки ведет к фаталу после завершения Drag'а
  28.         Ed().GetPoint("Test")|>ignore// этот вызов в то-же время будет работать
  29.         ()
  30.       |_->base.MoveGripPointsAt(ent,ic,vct)
  31.  
  32. // команда для проверки
  33. [<CommandMethod "Test">]
  34. let Test()=
  35.   Ed().Drag(new JigEmpty())|>ignore // команда-же прекрасно работает
  36.  
  37. // ставим в "автозагрузку" Overrule на точку
  38. type Initial()=
  39.   interface IExtensionApplication with
  40.     member obj.Initialize()=GripOverrule.AddOverrule(RXClass.GetClass(typeof<DBPoint>),new GrpOver(),true)
  41.     member obj.Terminate()=()

з.ы. все это нужно для обеспечения точности перемещения ручек в переOverrule'ный объект.
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Александр Ривилис от 11-06-2015, 14:12:35
Думаю что это принципиально работать не будет.
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Дима_ от 11-06-2015, 14:27:43
Там можно сделать "залипуху" вида вызова Editor.GetPoint(от нужной точки) - этот вызов работает - который переключать на разные "нужные" точки. Но это не удобно (мне надо чтоб показывали редактируемые рамеры от трех точек одновременно).
з.ы. может спросим у автодеска - хотя ответ немного предсказуем.
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Александр Ривилис от 11-06-2015, 14:29:59
Я могу передать этот вопрос в ADN DevHelp. Но тебе для этой цели придётся переписать код с F# на C# и подготовить тестовый проект.
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Дима_ от 11-06-2015, 14:31:27
Off-Topic: показать
Думаете не осилят :)?
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Александр Ривилис от 11-06-2015, 14:33:02
Off-Topic: показать
Думаю что заморачиваться с F# не будут и сразу попросят код на C# или будут тянуть резину.
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Александр Ривилис от 11-06-2015, 16:02:06
Вообще-то я думаю, что Drag во время другого Drag (а MoveGripPointsAt пока !ObjectId.IsValid приводит к Drag) работать не может. Так что тебе придётся определится и придумать другой способ.
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Дима_ от 11-06-2015, 16:08:43
Я тоже грешу на проблему "реентрабельности" (она была актуальна в MsDos - поэтому я с ней хорошо знаком - но видимо и в автокаде тоже), но ведь GetPoint и изнутри работает...
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Александр Ривилис от 11-06-2015, 16:09:43
но ведь GetPoint и изнутри работает...
GetPoint и Drag - это две совершенно разные вещи...
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Александр Ривилис от 11-06-2015, 16:17:47
Я правильно понимаю, что тебе в начале редактирования ручек нужно создать несколько AlignedDimension и в процессе MoveGripPointsAt их редактировать?
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Дима_ от 11-06-2015, 22:53:39
Да, мне надо, когда юзер берет ручку посчитать от нее контрольные точки и прорисовать к ним aligneddimension
P.S. А главное чтоб он мог вводить значения размеров.
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Александр Ривилис от 12-06-2015, 00:20:19
Да, мне надо, когда юзер берет ручку посчитать от нее контрольные точки и прорисовать к ним aligneddimension
Когда "юзер берет ручку" - это не MoveGripPointsAt, а OnGripStatusChanged. Попробуй в нём создавать свои размеры. Я вообще не понял при чем здесь DrawJig. Скорее тебе нужен метод WorldDraw, в котором ты будешь перерисовывать свои размеры.
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Дима_ от 12-06-2015, 01:01:20
Нет OnGripStatusChanged - это когда ручку уже отпустили (проверял уже), оно-же и как MoveGripPointsAt c IsValid, я хочу чтоб пользователь взявшись за ручку увидел "тянущиеся" размеры которые можно задать (то есть обеспечить точность позиционирования точки относительно заданных) - как когда мы тянем точку полилинии - видим "тянучки" на углы и соседние точки.
з.ы. давайте попробуем спросить - может скажут чего (хотя ответ, как я уже говорил ожидаем)
Off-Topic: показать
переписывать на C# мне было мучительно - к хорошему быстро привыкаешь

Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.Geometry;
  5. using Autodesk.AutoCAD.EditorInput;
  6. using Autodesk.AutoCAD.GraphicsInterface;
  7.  
  8.  
  9.     public class JigEmpty : DrawJig
  10.     {
  11.         protected override bool WorldDraw(WorldDraw draw)
  12.         {return true;}
  13.  
  14.         protected override SamplerStatus Sampler(JigPrompts prompts)
  15.         {
  16.             PromptPointResult prResult1 = prompts.AcquirePoint("\nDrag Pt ");
  17.             return SamplerStatus.OK;
  18.         }
  19.     }
  20.     public class GrpOver : GripOverrule
  21.     {
  22.  
  23.         public override void MoveGripPointsAt(Entity ent,IntegerCollection ic,Vector3d vct)
  24.         {
  25.             DBPoint point = ent as DBPoint;
  26.             Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  27.             //вариант 1 - работает
  28.             if (point != null && point.ObjectId.IsValid)
  29.             { ed.Drag(new JigEmpty()); }
  30.  
  31.             //вариант 2 - тоже работает
  32.             //if (point != null)
  33.             //{ ed.GetPoint("\nPt "); }
  34.            
  35.             //вариант 3 - здесь FATAL
  36.             //if (point != null)
  37.             //{ ed.Drag(new JigEmpty()); }
  38.            
  39.             { base.MoveGripPointsAt(ent, ic, vct); }
  40.         }
  41.  
  42.     }
  43.     public class Inital : IExtensionApplication
  44.     {
  45.         public void Initialize()
  46.         {GripOverrule.AddOverrule(RXClass.GetClass(typeof(DBPoint)),new GrpOver(),true);}
  47.         public void Terminate()
  48.         {}
  49.     }
  50.  
  51.  
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Александр Ривилис от 12-06-2015, 01:11:34
Я правильно понимаю, что ты хочешь сделать что-то подобное: http://adn-cis.org/dinamicheski-razmeryi-pri-pomoshhi-gripoverrule.html ?
Тогда прочитай комментарии к оригинальной статье - средствами .NET API это сделать пока нельзя: http://adndevblog.typepad.com/autocad/2015/06/dynamic-dimension-using-gripoverrule.html#comment-6a0167607c2431970b01b7c7997b1b970b
Впрочем я завтра отправлю вопрос в ADN DevHelp.
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Дима_ от 12-06-2015, 01:38:34
По сути мне нужно безопасно перехватить событие перемещения ручки, понять какая взята и отменив продолжение "подсунуть" пользователю свой jig в котором все тянучки уже настроены, а результат уже применить к примитиву
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Александр Ривилис от 12-06-2015, 01:40:23
и отменив продолжение
А вот это то, чего сделать нельзя.
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Дима_ от 12-06-2015, 01:43:50
А вот пример с getpoint по сути это делает сам по себе, но там можно использовать только одну опорную точку
P.s. Видимо клик проскакивает
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Александр Ривилис от 13-06-2015, 21:17:47
Отправил вопрос в ADN DevHelp.
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Дима_ от 13-06-2015, 23:03:03
Спасибо.
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Александр Ривилис от 17-06-2015, 16:37:52
Получил ответ. Если в двух словах, то так делать нельзя. Но можешь попробовать такой код:
Код - C# [Выбрать]
  1. public class TestDrawJig : DrawJig
  2.  
  3. {
  4.  
  5.     public  Point3d cp;
  6.  
  7.  
  8.     public TestDrawJig()
  9.  
  10.     {
  11.  
  12.         cp = Point3d.Origin;
  13.  
  14.     }
  15.  
  16.  
  17.     protected override bool WorldDraw(WorldDraw draw)
  18.  
  19.     {
  20.  
  21.         return true;
  22.  
  23.     }
  24.  
  25.  
  26.     protected override SamplerStatus Sampler(JigPrompts prompts)
  27.  
  28.     {
  29.  
  30.         PromptPointResult ppRes = prompts.AcquirePoint("\n[ Jig ] Pick a point : ");
  31.  
  32.  
  33.         if (cp != null)
  34.  
  35.         {
  36.  
  37.             double dDistance = ppRes.Value.DistanceTo(cp);
  38.  
  39.             if (dDistance < 0.00001)
  40.  
  41.             {
  42.  
  43.                 return SamplerStatus.NoChange;
  44.  
  45.             }
  46.  
  47.         }
  48.  
  49.  
  50.         cp = ppRes.Value;
  51.  
  52.  
  53.         return SamplerStatus.OK;
  54.  
  55.     }
  56.  
  57. }
  58.  
  59.  
  60. public class GrpOver : GripOverrule
  61.  
  62. {
  63.  
  64.     private static GrpOver _gripOverrule = null;
  65.  
  66.     private static TestDrawJig _testDrawJig = null;
  67.  
  68.  
  69.     public override bool IsApplicable(RXObject overruledSubject)
  70.  
  71.     {
  72.  
  73.         bool isApplicable = false;
  74.  
  75.         DBPoint point = overruledSubject as DBPoint;
  76.  
  77.         if (point != null)
  78.  
  79.         {
  80.  
  81.             isApplicable = true;
  82.  
  83.         }
  84.  
  85.         return isApplicable;
  86.  
  87.     }
  88.  
  89.  
  90.     public static void AttachOverrule()
  91.  
  92.     {
  93.  
  94.         _gripOverrule = new GrpOver();
  95.  
  96.         Overrule.AddOverrule(RXClass.GetClass(typeof(DBPoint)), _gripOverrule, true);
  97.  
  98.         Overrule.Overruling = true;
  99.  
  100.     }
  101.  
  102.  
  103.     public static void RemoveOverrule()
  104.  
  105.     {
  106.  
  107.         Overrule.RemoveOverrule(RXClass.GetClass(typeof(DBPoint)), _gripOverrule);
  108.  
  109.         Overrule.Overruling = false;
  110.  
  111.         _gripOverrule = null;
  112.  
  113.     }
  114.  
  115.  
  116.     public override void MoveGripPointsAt(Entity ent, IntegerCollection ic, Vector3d vct)
  117.  
  118.     {
  119.  
  120.         DBPoint point = ent as DBPoint;
  121.  
  122.         Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  123.  
  124.         ed.WriteMessage(String.Format("{0}MoveGripPointsAt...", Environment.NewLine));
  125.  
  126.  
  127.         if (point != null && point.ObjectId.IsValid)
  128.  
  129.         {
  130.  
  131.             if (_testDrawJig == null)
  132.  
  133.                 _testDrawJig = new TestDrawJig();
  134.  
  135.  
  136.             PromptResult pr = ed.Drag(_testDrawJig);
  137.  
  138.             if (pr.Status == PromptStatus.OK)
  139.  
  140.             {
  141.  
  142.                 Point3d pt = _testDrawJig.cp;
  143.  
  144.                 ed.WriteMessage(String.Format("Point selected : {0} {1} {2}", pt.X, pt.Y, pt.Z));
  145.  
  146.             }
  147.  
  148.         }
  149.  
  150.  
  151.         base.MoveGripPointsAt(ent, ic, vct);
  152.  
  153.     }
  154.  
  155. }
  156.  
  157.  
  158. public class Commands : IExtensionApplication
  159.  
  160. {
  161.  
  162.     void IExtensionApplication.Initialize()
  163.  
  164.     {
  165.  
  166.         GrpOver.AttachOverrule();
  167.  
  168.     }
  169.  
  170.  
  171.     void IExtensionApplication.Terminate()
  172.  
  173.     {
  174.  
  175.         GrpOver.RemoveOverrule();
  176.  
  177.     }
  178.  
  179. }

Я не пробовал его, но судя по тому что в нём стоит проверка на point.ObjectId.IsValid он работает аналогично твоему.
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Дима_ от 18-06-2015, 14:40:02
Это грустно - была у меня еще надежда, что можно бует использовать переопределенный метод GetHotGripDimensionData в  унаследованном от GripData в коллекции GetGripPoints () (там например AlternateBasePoint - можно переопределить), но отобразить редактируемые размеры я не осилил - а жаль. В итоге придется приучать юзеров делать лишний щелчок (чтоб отобразить привязки).
Название: Re: Скрестить DrawJig и MoveGripPointsAt
Отправлено: Александр Ривилис от 18-06-2015, 14:49:54
Ну или в качестве разминки перепиши это всё на ObjectARX/C++ - благо есть готовый пример.