Переопределение привязок

Автор Тема: Переопределение привязок  (Прочитано 4910 раз)

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

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

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Добрый день! Есть большое желание создать команду которая переопределяла бы свойство привязки таким образом, чтобы привязки срабатывали только к объектам, расположенным на определенном слое. Прошу мэтров подсказать, в какую сторону копать?

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Переопределение привязок
« Ответ #1 : 13-04-2022, 11:56:07 »
Надо смотреть OsnapOverrule

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Re: Переопределение привязок
« Ответ #2 : 13-04-2022, 13:17:21 »
получается, но возник вопрос. я получил все объекты чертежа и проверил их на принадлежность слою. но почему-то выдает ошибку, когда я хочу получить объект для заблокированного слоя. Как это победить?

Код - C# [Выбрать]
  1.    foreach (ObjectId so in ms)
  2.  
  3.                     {
  4.                             foreach  (string sLayerName_for in FiltrPerem.namelayerCreate)
  5.                                 {
  6.                                 var ent =
  7.  
  8.                                   tr.GetObject(so, OpenMode.ForWrite) as Entity;//Тут ошибка для объекта на заблокированном слое
  9.  
  10.                                 if (ent != null && ent.Layer.ToString()== sLayerName_for)
  11.  
  12.                                 {
  13.  
  14.                                     ent.XData = rb;
  15.  
  16.                                 }
  17.                             }
  18.  
  19.                     }

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Переопределение привязок
« Ответ #3 : 13-04-2022, 13:33:45 »
Код - C# [Выбрать]
  1. tr.GetObject(so, OpenMode.ForWrite, false, true)

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Re: Переопределение привязок
« Ответ #4 : 13-04-2022, 13:39:03 »
Полет нормальный! Спасибо, Дмитрий!  ;D

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Re: Переопределение привязок
« Ответ #5 : 13-04-2022, 16:44:50 »
Не совсем нормальный полет... Почему-то, если выбрать список из двух слоев, отключаются все привязки... подскажите?

Код - C# [Выбрать]
  1.                  using (
  2.  
  3.                   var rb =
  4.  
  5.                     new ResultBuffer(
  6.  
  7.                                      new TypedValue((int)DxfCode.ExtendedDataRegAppName, "TTIF_SNAP"),
  8.  
  9.                                      new TypedValue((int)DxfCode.ExtendedDataInteger16,1)
  10.  
  11.                                     )
  12.                                        
  13.                       )
  14.  
  15.                 {
  16.                         foreach (ObjectId so in ms)
  17.  
  18.                         {
  19.                             foreach (string sLayerName_for in FiltrPerem.namelayerCreate)//работает только при списке из одного значения
  20.                             {
  21.                                 var ent =
  22.  
  23.                                   tr.GetObject(so, OpenMode.ForWrite, false, true) as Entity;
  24.  
  25.                                 if (ent != null) && ent.Layer.ToString() != sLayerName_for)
  26.  
  27.                                 {
  28.                                    ent.XData = rb;
  29.                                 }
  30.                         }
  31.  
  32.                     }
  33.                 };
« Последнее редактирование: 13-04-2022, 17:55:49 от VitaliyB »

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Переопределение привязок
« Ответ #6 : 14-04-2022, 09:50:36 »
А как этот код связан с привязками? Непонятно

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Re: Переопределение привязок
« Ответ #7 : 14-04-2022, 10:41:00 »
проблема какая-то в ent.XData=rb - как мне кажется;

Сам код я взял https://www.keanw.com/2013/12/disabling-snapping-to-specific-autocad-objects-using-net-part-1.html и немного подредактировал с получения объектов GetSelection на перебор объектов всего чертежа и сопоставлению необходимому слою. Почему не работает при передачи в список FiltrPerem.namelayerCreate более 1 имени слоя - не могу понять. Привожу весь код. Не стреляйте в пианиста, он играет как умеет)

Код - C# [Выбрать]
  1. namespace PTO
  2. {/// <summary>
  3. /// https://www.keanw.com/2013/12/disabling-snapping-to-specific-autocad-objects-using-net-part-1.html
  4. /// </summary>
  5.     public class ViborSnap
  6.  
  7.     {
  8.        public static bool m_isNotifyEnabled = false;
  9.         const string regAppName = "TTIF_SNAP";
  10.         private static OSOverrule _osOverrule = null;
  11.  
  12.         // Object Snap Overrule to prevent snapping to objects
  13.  
  14.         // with certain XData attached
  15.  
  16.         public class OSOverrule : OsnapOverrule
  17.  
  18.         {
  19.  
  20.             public OSOverrule()
  21.  
  22.             {
  23.                 // Tell AutoCAD to filter on our application name
  24.  
  25.                 // (this should mean our overrule only gets called
  26.  
  27.                 // on objects possessing XData with this name)
  28.  
  29.                 SetXDataFilter(regAppName);
  30.             }
  31.  
  32.             public override void GetObjectSnapPoints(
  33.  
  34.               Entity ent,
  35.               ObjectSnapModes mode,
  36.               IntPtr gsm,
  37.               Point3d pick,
  38.               Point3d last,
  39.               Matrix3d view,
  40.               Point3dCollection snap,
  41.               IntegerCollection geomIds
  42.  
  43.             )  {  }
  44.  
  45.  
  46.             public override void GetObjectSnapPoints(
  47.  
  48.               Entity ent,
  49.               ObjectSnapModes mode,
  50.               IntPtr gsm,
  51.               Point3d pick,
  52.               Point3d last,
  53.               Matrix3d view,
  54.               Point3dCollection snaps,
  55.               IntegerCollection geomIds,
  56.               Matrix3d insertion
  57.  
  58.             ) { }
  59.  
  60.  
  61.  
  62.  
  63.             public override bool IsContentSnappable(Entity entity)
  64.  
  65.             {
  66.              return false;
  67.             }
  68.         }
  69.  
  70.         private static void ToggleOverruling(bool on)
  71.  
  72.         {
  73.             if (on)
  74.             {
  75.                 if (_osOverrule == null)
  76.                 {
  77.                     _osOverrule = new OSOverrule();
  78.                     ObjectOverrule.AddOverrule( RXObject.GetClass(typeof(Entity)),  _osOverrule,  false );
  79.                 }
  80.                 ObjectOverrule.Overruling = true;
  81.             }
  82.  
  83.             else
  84.             {
  85.                 if (_osOverrule != null)
  86.                 {
  87.                     ObjectOverrule.RemoveOverrule(RXObject.GetClass(typeof(Entity)),  _osOverrule);
  88.                     _osOverrule.Dispose();
  89.                     _osOverrule = null;
  90.                 }
  91.                 // I don't like doing this and so have commented it out:
  92.                 // there's too much risk of stomping on other overrules...
  93.                 // ObjectOverrule.Overruling = false;
  94.             }
  95.         }
  96.  
  97.         [CommandMethod("ИгнорSnapSelection_On")]
  98.  
  99.         public static void DisableSnapping()
  100.         {
  101.             var doc = Application.DocumentManager.MdiActiveDocument;
  102.             var db = doc.Database;
  103.             var ed = doc.Editor;
  104.             // Start by getting the entities to disable snapping for.
  105.             // If none selected, turn off the overrule
  106.             using (Transaction tr = db.TransactionManager.StartTransaction())
  107.             {
  108.                 // получаем ссылку на пространство модели (ModelSpace)
  109.                 BlockTableRecord ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
  110.                 // "пробегаем" по всем объектам в пространстве модели
  111.                 foreach (ObjectId id in ms)
  112.                 {
  113.                     // приводим каждый из них к типу Entity
  114.                     Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
  115.                 }
  116.        
  117.             ToggleOverruling(true);
  118.  
  119.             // Start a transaction to modify the entities' XData
  120.  
  121.                  // Make sure our RegAppID is in the table
  122.                 var rat =
  123.                   (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForRead);
  124.  
  125.                 if (!rat.Has(regAppName))
  126.                 {
  127.                     rat.UpgradeOpen();
  128.                     var ratr = new RegAppTableRecord();
  129.                     ratr.Name = regAppName;
  130.                     rat.Add(ratr);
  131.                     tr.AddNewlyCreatedDBObject(ratr, true);
  132.                 }
  133.                 // Create the XData and set it on the object
  134.                 using (
  135.                   var rb =
  136.                     new ResultBuffer(
  137.                                      new TypedValue((int)DxfCode.ExtendedDataRegAppName, regAppName),
  138.                                      new TypedValue((int)DxfCode.ExtendedDataInteger16,1)
  139.                                     )
  140.                       )
  141.                 {
  142.                         foreach (ObjectId so in ms)
  143.                         {
  144.                             foreach (string sLayerName_for in FiltrPerem.namelayerCreate)//работает только при списке из одного значения
  145.                             {
  146.                                 var ent =
  147.                                   tr.GetObject(so, OpenMode.ForWrite, false, true) as Entity;
  148.                                 if (ent != null && ent.Layer.ToString() != sLayerName_for)
  149.                                 {
  150.                                    ent.XData = rb;
  151.                                 }
  152.                         }
  153.                     }
  154.                 };
  155.                 tr.Commit();
  156.             }
  157.         }
  158.  
  159.  
  160.         [CommandMethod("ИгнорSnapSelection_Off")]
  161.  
  162.         public static void EnableSnapping()
  163.  
  164.         {
  165.  
  166.             var doc = Application.DocumentManager.MdiActiveDocument;
  167.             var db = doc.Database;
  168.             var ed = doc.Editor;
  169.           // Start a transaction to modify the entities' XData
  170.             using (Transaction tr = db.TransactionManager.StartTransaction())
  171.             {
  172.                 // получаем ссылку на пространство модели (ModelSpace)
  173.                 BlockTableRecord ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
  174.                 // "пробегаем" по всем объектам в пространстве модели
  175.                 foreach (ObjectId id in ms)
  176.                 {
  177.                     // приводим каждый из них к типу Entity
  178.                     Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
  179.                 }
  180.  
  181.                 // Create a ResultBuffer and use it to remove the XData
  182.                 // from the object
  183.                 using (
  184.                   var rb =
  185.                     new ResultBuffer(
  186.                       new TypedValue(
  187.                         (int)DxfCode.ExtendedDataRegAppName, regAppName
  188.                       )
  189.                     )
  190.                 )
  191.                 {
  192.                     foreach (ObjectId so in ms)
  193.                     {
  194.                         foreach (string sLayerName_for in FiltrPerem.namelayerCreate)
  195.                         {
  196.                             var ent =
  197.                               tr.GetObject(so, OpenMode.ForWrite, false, true) as Entity;//Тут ошибка для объекта на заблокированном слое
  198.                             if (ent != null)
  199.                             {
  200.                                 ent.XData = rb;
  201.                             }
  202.                         }
  203.                     }
  204.                 };
  205.                 tr.Commit();
  206.  
  207.         }
  208.     }
  209.     }
  210. }
  211.  
« Последнее редактирование: 14-04-2022, 13:17:15 от VitaliyB »

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Переопределение привязок
« Ответ #8 : 14-04-2022, 11:34:50 »
Не стреляйте в пианиста, он играет как умеет)
Но подчистить хотя бы пустые строки можно же? Разве удобно самому так с ним работать?
По коду пока особо не смотрел. Но при беглом взгляде зацепился за вложенные транзакции. Зачем такое? Одна не справится?

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Re: Переопределение привязок
« Ответ #9 : 14-04-2022, 11:47:07 »
да, почистил пустые строки - извиняюсь за предыдущий вариант. по транзакции тоже убрал лишнюю - согласен она там ни к чему.

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Переопределение привязок
« Ответ #10 : 14-04-2022, 13:26:56 »
А зачем в этом случае нужен фильтр по XData? Попытка подстроить готовый код под свои нужды? Там Xdata оправдан тем, что переопределение применяется к определённым выбранным объектам. А тут - все объекты на каком-то слое. Эти объекты можно определить без XData-меток.

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Re: Переопределение привязок
« Ответ #11 : 14-04-2022, 13:29:16 »
да, именно - пытался подстроить готовый код под свои нужды... а каким способом тогда определять объекты?

Отмечено как Решение VitaliyB 14-04-2022, 14:48:48

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Переопределение привязок
« Ответ #12 : 14-04-2022, 13:53:00 »
Код - C# [Выбрать]
  1. namespace CivilTest
  2. {
  3.     using System;
  4.     using System.Linq;
  5.     using Autodesk.AutoCAD.DatabaseServices;
  6.     using Autodesk.AutoCAD.Geometry;
  7.     using Autodesk.AutoCAD.Runtime;
  8.  
  9.     /// <summary>
  10.     /// https://www.keanw.com/2013/12/disabling-snapping-to-specific-autocad-objects-using-net-part-1.html
  11.     /// </summary>
  12.     public class OSnapLayerFilter
  13.     {
  14.         private static readonly string[] Layers = { "Test1", "Test2" };
  15.         private static OsOverrule _osOverrule;
  16.        
  17.         private class OsOverrule : OsnapOverrule
  18.         {
  19.             public override void GetObjectSnapPoints(
  20.                 Entity ent,
  21.                 ObjectSnapModes mode,
  22.                 IntPtr gsm,
  23.                 Point3d pick,
  24.                 Point3d last,
  25.                 Matrix3d view,
  26.                 Point3dCollection snap,
  27.                 IntegerCollection geomIds)
  28.             {
  29.                 if (IsApplicable(ent))
  30.                     return;
  31.  
  32.                 base.GetObjectSnapPoints(ent, mode, gsm, pick, last, view, snap, geomIds);
  33.             }
  34.  
  35.  
  36.             public override void GetObjectSnapPoints(
  37.                 Entity ent,
  38.                 ObjectSnapModes mode,
  39.                 IntPtr gsm,
  40.                 Point3d pick,
  41.                 Point3d last,
  42.                 Matrix3d view,
  43.                 Point3dCollection snaps,
  44.                 IntegerCollection geomIds,
  45.                 Matrix3d insertion)
  46.             {
  47.                 if (IsApplicable(ent))
  48.                     return;
  49.  
  50.                 base.GetObjectSnapPoints(ent, mode, gsm, pick, last, view, snaps, geomIds, insertion);
  51.             }
  52.  
  53.  
  54.             public override bool IsContentSnappable(Entity entity)
  55.             {
  56.                 return !IsApplicable(entity);
  57.             }
  58.  
  59.             /// <inheritdoc />
  60.             public override bool IsApplicable(RXObject overruledSubject)
  61.             {
  62.                 return base.IsApplicable(overruledSubject) && overruledSubject is Entity ent &&
  63.                        Layers.Any(x => x.Equals(ent.Layer, StringComparison.OrdinalIgnoreCase));
  64.             }
  65.         }
  66.  
  67.         private static void ToggleOverruling(bool on)
  68.         {
  69.             if (on)
  70.             {
  71.                 if (_osOverrule == null)
  72.                 {
  73.                     _osOverrule = new OsOverrule();
  74.                     Overrule.AddOverrule(RXObject.GetClass(typeof(Entity)), _osOverrule, false);
  75.                 }
  76.  
  77.                 Overrule.Overruling = true;
  78.             }
  79.             else
  80.             {
  81.                 if (_osOverrule == null)
  82.                     return;
  83.  
  84.                 Overrule.RemoveOverrule(RXObject.GetClass(typeof(Entity)), _osOverrule);
  85.                 _osOverrule.Dispose();
  86.                 _osOverrule = null;
  87.             }
  88.         }
  89.  
  90.         [CommandMethod("IgnoreSnapSelection_On")]
  91.         public static void DisableSnapping()
  92.         {
  93.             ToggleOverruling(true);
  94.         }
  95.  
  96.         [CommandMethod("IgnoreSnapSelection_Off")]
  97.         public static void EnableSnapping()
  98.         {
  99.             ToggleOverruling(false);
  100.         }
  101.     }
  102. }

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

  • ADN OPEN
  • **
  • Сообщений: 63
  • Карма: 2
Re: Переопределение привязок
« Ответ #13 : 14-04-2022, 14:48:37 »
Дмитрий, спасибо большое!  ;D Потестил вроде все работает. Очень здорово должно помочь в работе с нагруженными чертежами (коих много). На всякий случай, так сказать, для собственного развития, уточню, правильно ли я поправил код под свои нужды:

1. Зачем при Создании массива Layers было ключевое слово readonly? Я его убрал, иначе же нельзя в процессе сессии автокада загрузить туда новые значения

2. Опять же для перезаписи массива Layers, чтобы при вызове команды каждый раз передавались новые значения:

Код - C# [Выбрать]
  1.   [CommandMethod("ИгнорSnapSelection_On")]
  2.         public static void DisableSnapping()
  3.         {
  4.             Layers = {"новые значения для массива"};// тут переопределяю массив Layers каждый раз при вызове команды, т.к. при тестировании массив каждый раз не изменялся
  5.             ToggleOverruling(true);
  6.         }
  7.  

3. Чтобы исключить из привязок все слои, не присутствующие в списке Layers:
Код - C# [Выбрать]
  1. public override bool IsApplicable(RXObject overruledSubject)
  2.             {
  3.                 return base.IsApplicable(overruledSubject) && overruledSubject is Entity ent &&
  4.                        !Layers.Any(x => x.Equals(ent.Layer, StringComparison.OrdinalIgnoreCase));// тогда проверяем это условие с логическим значением"НЕ"
  5.             }
  6.  


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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Переопределение привязок
« Ответ #14 : 14-04-2022, 16:43:22 »
1. Зачем при Создании массива Layers было ключевое слово readonly? Я его убрал, иначе же нельзя в процессе сессии автокада загрузить туда новые значения
У меня в коде оно неизменно, поэтому readonly.
2. Ок.
3. Если надо отключить все кроме тех, что в коллекции - то норм.