Некорректное поведение base.MoveGripPointsAt для BlockReference.

Автор Тема: Некорректное поведение base.MoveGripPointsAt для BlockReference.  (Прочитано 3315 раз)

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

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

Оффлайн GienaАвтор темы

  • ADN OPEN
  • Сообщений: 6
  • Карма: 0
Здравствуйте.

При переопределении  MoveGripPointsAt для GripOverrule не работает base.MoveGripPointsAt. При вызове базового метода вставка блока просто стоит на месте, а должна перемещаться на offset. Для Entity отличных от BlockReference все работает как ожидается . В чем может быть дело?

Код ниже.

Наследник GripOverrule:

Код - C# [Выбрать]
  1.  public class ConnectionGripOverrule : GripOverrule
  2.     {
  3.         static public ConnectionGripOverrule theOverrule;
  4.         static HashSet<ObjectId> mCurves = new HashSet<ObjectId>();
  5.         static HashSet<ObjectId> mBlkRefs = new HashSet<ObjectId>();
  6.         static ObjectId CurrentId;
  7.  
  8.         ConnectionGripOverrule() { }
  9.  
  10.         public static void StartIfNotStarted()
  11.         {
  12.             if (theOverrule == null)
  13.             {
  14.                 theOverrule = new ConnectionGripOverrule();
  15.                 ObjectOverrule.AddOverrule(RXClass.GetClass(typeof(BlockReference)), ConnectionGripOverrule.theOverrule, true);
  16.                 GripOverrule.Overruling = true;
  17.             }
  18.         }
  19.  
  20.         public static void AddTrackGeometry(ObjectId curveId)
  21.         {
  22.             if (!mCurves.Contains(curveId) && curveId != ObjectId.Null)
  23.             {
  24.                 mCurves.Add(curveId);
  25.             }
  26.         }
  27.  
  28.         public static void AddTrackingBlkRec(ObjectId brId)
  29.         {
  30.             if (!mBlkRefs.Contains(brId) && brId != ObjectId.Null)
  31.             {
  32.                 mBlkRefs.Add(brId);
  33.                 ObjectId[] idArray = new ObjectId[mBlkRefs.Count];
  34.                 mBlkRefs.CopyTo(idArray);
  35.                 theOverrule.SetIdFilter(idArray);
  36.             }
  37.  
  38.         }
  39.  
  40.         public override void GetGripPoints(Entity entity, Point3dCollection gripPoints, IntegerCollection snapModes, IntegerCollection geometryIds)
  41.         {
  42.              CurrentId = entity.ObjectId;
  43.              base.GetGripPoints(entity, gripPoints, snapModes, geometryIds);
  44.         }
  45.  
  46.         public override void MoveGripPointsAt(Entity entity, GripDataCollection grips, Vector3d offset, MoveGripPointsFlags bitFlags)
  47.         {
  48.             base.MoveGripPointsAt(entity, grips, offset, bitFlags);
  49.         }
  50.  
  51.         public override void MoveGripPointsAt(Entity entity, IntegerCollection indices, Vector3d offset)
  52.         {
  53.             if (indices.Count > 0 && indices[0] == 0)
  54.             {
  55.                 BlockReference pt = entity as BlockReference;
  56.                 if (pt != null && mBlkRefs.Contains(CurrentId))
  57.                 {
  58.                     Database db = HostApplicationServices.WorkingDatabase;
  59.                     bool found = false;
  60.  
  61.                     OpenCloseTransaction tr = db.TransactionManager.StartOpenCloseTransaction();
  62.  
  63.                     using (tr)
  64.                     {
  65.  
  66.                         foreach (ObjectId curId in mCurves)
  67.                         {
  68.                             DBObject obj = tr.GetObject(curId, OpenMode.ForRead);
  69.                             Curve cur = obj as Curve;
  70.                             if (cur != null)
  71.                             {
  72.                                 Point3d ptOffset = pt.Position + offset;
  73.                                 Point3d ptOnCurve = cur.GetClosestPointTo(ptOffset, false);
  74.                                 Vector3d dist = ptOnCurve - ptOffset;
  75.                                 if (!dist.IsZeroLength(Tolerance.Global) && dist.Length - offset.Length <2000)
  76.                                 {
  77.                                     Matrix3d mat = Matrix3d.Displacement(-dist);
  78.                                     Point3d pos = cur.GetClosestPointTo(ptOffset.TransformBy(mat), false);
  79.                                     pt.Position = pos;
  80.                                     found = true;
  81.                                     break;
  82.                                 }
  83.                             }
  84.                         }
  85.  
  86.                         if (!found)
  87.                         {
  88.                             base.MoveGripPointsAt(entity, indices, offset);
  89.                         }
  90.                     }
  91.                 }
  92.                 else
  93.                 {
  94.                     base.MoveGripPointsAt(entity, indices, offset);
  95.                 }
  96.             }
  97.             else
  98.             {
  99.                 base.MoveGripPointsAt(entity, indices, offset);
  100.             }
  101.         }
  102.        
  103.     }
  104.  

Вызов :



 
Код - C# [Выбрать]
  1. public class Commands : IExtensionApplication
  2.     {
  3.         [CommandMethod("TrackBr")]
  4.         public void CreatePointOnCurve()
  5.  
  6.         {
  7.             Document doc = Application.DocumentManager.MdiActiveDocument;
  8.             Database db = doc.Database;
  9.             Editor ed = doc.Editor;
  10.  
  11.             PromptEntityOptions opts = new PromptEntityOptions("\nSelect curve : ");
  12.  
  13.             opts.SetRejectMessage("\nEntity must be a curve.");
  14.             opts.AddAllowedClass(typeof(Curve), false);
  15.  
  16.             PromptEntityResult per = ed.GetEntity(opts);
  17.             ObjectId curId = per.ObjectId;
  18.  
  19.             PromptEntityOptions opts1 = new PromptEntityOptions("\nSelect block reference :");
  20.  
  21.             opts1.SetRejectMessage("\nEntity must be a block reference.");
  22.             opts1.AddAllowedClass(typeof(BlockReference), false);
  23.  
  24.             PromptEntityResult per1 = ed.GetEntity(opts1);
  25.             ObjectId brId = per1.ObjectId;
  26.  
  27.             if (curId != ObjectId.Null && brId != ObjectId.Null)
  28.  
  29.             {
  30.                 ConnectionGripOverrule.StartIfNotStarted();
  31.                 ConnectionGripOverrule.AddTrackGeometry(curId);
  32.                 ConnectionGripOverrule.AddTrackingBlkRec(brId);
  33.             }
  34.  
  35.         }
  36.  
  37.      }


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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Что-то я нигде не увидел tr.Commit(), что означает, что вызывается tr.Abort()
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Еще могу порекомендовать перенести обработку в переопределённый метод:
Код - C# [Выбрать]
  1. public override void MoveGripPointsAt(Entity entity, GripDataCollection grips, Vector3d offset, MoveGripPointsFlags bitFlags)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн GienaАвтор темы

  • ADN OPEN
  • Сообщений: 6
  • Карма: 0
Коммит видимо не причем, так как вот это дает такой же разультат:

Код - C# [Выбрать]
  1. foreach (ObjectId curId in mCurves)
  2.                     {
  3.                         using (Curve cur = curId.Open(OpenMode.ForRead) as Curve)
  4.                         {
  5.                             if (cur != null)
  6.                             {
  7.                                 Point3d ptOffset = pt.Position + offset;
  8.                                 Point3d ptOnCurve = cur.GetClosestPointTo(ptOffset, false);
  9.                                 Vector3d dist = ptOnCurve - ptOffset;
  10.                                 if (!dist.IsZeroLength(Tolerance.Global) && dist.Length - offset.Length < 2000)
  11.                                 {
  12.                                     Matrix3d mat = Matrix3d.Displacement(-dist);
  13.                                     Point3d pos = cur.GetClosestPointTo(ptOffset.TransformBy(mat), false);
  14.                                     pt.Position = pos;
  15.                                     found = true;
  16.                                     break;
  17.                                 }
  18.                             }
  19.                         }

Что касается public override void MoveGripPointsAt(Entity entity, GripDataCollection grips, Vector3d offset, MoveGripPointsFlags bitFlags), то дебагер туда не попадает вообще. Насколько я помню при создании Custom Entity в ObjectARX второй вариант MoveGripPointsAt, очень похожий по параметрам на этот шарповский, вызывается после того как первый вернет что то отличное от eOk... Но тут функции MoveGripPointsAt обе void...  :-\

При смене позиции блока  br.Position = Point3d, транзакция нужна?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
При смене позиции блока  br.Position = Point3d, транзакция нужна?
Если он у тебя уже открыт для записи, то не нужна. Кстати, не забывай, что MoveGripPointsAt работает с клонированными (не внесёнными в базу) объектами. Точнее, тебе очень желательно проверять ObjectId переданного туда объекта. Если он не null, то это объект в базе, если нет, то клон.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн GienaАвтор темы

  • ADN OPEN
  • Сообщений: 6
  • Карма: 0
Вобщем результаты следующие. Все убрал до такого вида:

Класс:

Код - C# [Выбрать]
  1.  public class ConnectionGripOverrule : GripOverrule
  2.     {
  3.         static public ConnectionGripOverrule theOverrule;
  4.  
  5.         ConnectionGripOverrule() { }
  6.  
  7.         public static void StartIfNotStarted()
  8.         {
  9.             if (theOverrule == null)
  10.             {
  11.                 theOverrule = new ConnectionGripOverrule();
  12.                 ObjectOverrule.AddOverrule(RXClass.GetClass(typeof(BlockReference)), ConnectionGripOverrule.theOverrule, true);
  13.                 GripOverrule.Overruling = true;
  14.             }
  15.         }
  16.  
  17.  
  18.         public override void GetGripPoints(Entity entity, Point3dCollection gripPoints, IntegerCollection snapModes, IntegerCollection geometryIds)
  19.         {
  20.              
  21.              base.GetGripPoints(entity, gripPoints, snapModes, geometryIds);
  22.         }
  23.  
  24.         public override void MoveGripPointsAt(Entity entity, IntegerCollection indices, Vector3d offset)
  25.         {
  26.             base.MoveGripPointsAt( entity,  indices, offset);
  27.         }
  28.     }

Вызов:

Код - C# [Выбрать]
  1. public class Commands : IExtensionApplication
  2.     {
  3.         [CommandMethod("TrackBr")]
  4.         public void CreatePointOnCurve()
  5.         {
  6.             ConnectionGripOverrule.StartIfNotStarted();
  7.         }
  8.     }

После выполнения команды, вставки блоков при попытке перетаскивания за грип стоят на месте (не перемещаются по offset). Проверял для Circle и Line - все OK.

У себя поставил костыль дублирующий перемещение по offset (то что должно по идее делать base.MoveGripPointsAt()).

Кстати, не забывай, что MoveGripPointsAt работает с клонированными (не внесёнными в базу) объектами.

Да, это клон.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Вот тест который я провел в AutoCAD 2020:
Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.EditorInput;
  7.  
  8. // This line is not mandatory, but improves loading performances
  9. [assembly: CommandClass(typeof(TestMoveGripPoint.MyCommands))]
  10.  
  11. namespace TestMoveGripPoint
  12. {
  13.   public class ConnectionGripOverrule : GripOverrule
  14.   {
  15.     static public ConnectionGripOverrule theOverrule;
  16.  
  17.     ConnectionGripOverrule() { }
  18.  
  19.     public static void StartIfNotStarted()
  20.     {
  21.       if (theOverrule == null)
  22.       {
  23.         theOverrule = new ConnectionGripOverrule();
  24.         ObjectOverrule.AddOverrule(RXClass.GetClass(typeof(BlockReference)), ConnectionGripOverrule.theOverrule, true);
  25.         GripOverrule.Overruling = true;
  26.       }
  27.     }
  28.  
  29.     public override void GetGripPoints(Entity entity, Point3dCollection gripPoints, IntegerCollection snapModes, IntegerCollection geometryIds)
  30.     {
  31.       base.GetGripPoints(entity, gripPoints, snapModes, geometryIds);
  32.     }
  33.  
  34.     public override void GetGripPoints(Entity entity, GripDataCollection grips, double curViewUnitSize, int gripSize, Vector3d curViewDir, GetGripPointsFlags bitFlags)
  35.     {
  36.       base.GetGripPoints(entity, grips, curViewUnitSize, gripSize, curViewDir, bitFlags);
  37.     }
  38.  
  39.     public override void MoveGripPointsAt(Entity entity, IntegerCollection indices, Vector3d offset)
  40.     {
  41.       base.MoveGripPointsAt(entity, indices, offset);
  42.     }
  43.     public override void MoveGripPointsAt(Entity entity, GripDataCollection grips, Vector3d offset, MoveGripPointsFlags bitFlags)
  44.     {
  45.       base.MoveGripPointsAt(entity, grips, offset, bitFlags);
  46.     }
  47.  
  48.   }
  49.  
  50.   public class MyCommands
  51.   {
  52.     [CommandMethod("TrackBr")]
  53.     public void CreatePointOnCurve()
  54.     {
  55.       ConnectionGripOverrule.StartIfNotStarted();
  56.     }
  57.   }
  58. }

Вот результаты:



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

Оффлайн GienaАвтор темы

  • ADN OPEN
  • Сообщений: 6
  • Карма: 0
C одиночными Circle и Line y меня тоже все работает как надо. Для вставки блока с несколькими примитивами это не работает. У меня для теста прямоугольник с двумя линиями объединенные в блок.





Autocad 2017, ObjectARX 2017

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
C одиночными Circle и Line y меня тоже все работает как надо. Для вставки блока с несколькими примитивами это не работает. У меня для теста прямоугольник с двумя линиями объединенные в блок.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Giena 12-09-2019, 12:02:12

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А вот и в AutoCAD 2017 (со всеми обновлениями):

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

Оффлайн GienaАвтор темы

  • ADN OPEN
  • Сообщений: 6
  • Карма: 0
Александр, спасибо, что проверили. У меня не установлены обновления, видимо из-за этого не работает как надо.

Autodesk Autocad Architecture 2017.

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

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