Включить\Отключить аннотативность объекта

Автор Тема: Включить\Отключить аннотативность объекта  (Прочитано 16766 раз)

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

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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Получается для всех объектов кроме BlockTableRecord надо добавить текущий масштаб, а для BlockTableRecord найти уже все BlockReference и добавить масштаб им?
В идеале да. Не думай, что найти все BlockReference  для конкретного BlockTableRecord так сложно: https://adn-cis.org/kak-najti-vse-vstavki-dinamicheskogo-bloka.html
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
obj не может стать равным null
Вроде, если объект будет удалён, то вернёт null. Хотя, вероятность того, что в лисп-функцию прилетит удалённый объект, крайне мала.
Для удаленного объекта (entget) возвращает nil. Так что его список передать в эту функцию не удастся. Хотя конечно можно сначала получить список, а затем удалить. Но мне кажется что будет не null, а исключение. Впрочем, нужно проверять.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 475
  • Карма: 63
Код - C# [Выбрать]
  1.         static List<Type> list = new List<Type>
  2.         {
  3.             typeof(DBText),
  4.             typeof(BlockTableRecord),
  5.             typeof(MText),
  6.             typeof(Dimension),
  7.             typeof(Leader),
  8.             typeof(MLeader),
  9.             typeof(Hatch)
  10.         };
  11.  
  12.         private static bool IsObjectAnnotation(ObjectId annObjId)
  13.         {
  14.             return list.Any(t => annObjId.ObjectClass.Equals(RXObject.GetClass(t)));
  15.         }

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 738
trir, можно ещё сделать сразу список не типов, а RX классов

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

  • ADN Club
  • ****
  • Сообщений: 270
  • Карма: 24
  • Геодезист
Получается для всех объектов кроме BlockTableRecord надо добавить текущий масштаб, а для BlockTableRecord найти уже все BlockReference и добавить масштаб им?
В идеале да. Не думай, что найти все BlockReference  для конкретного BlockTableRecord так сложно: https://adn-cis.org/kak-najti-vse-vstavki-dinamicheskogo-bloka.html
Делать это принудительно всегда, или стоит проверить версию AutoCAD, и если свежая то этого не требуется?

Код - C# [Выбрать]
  1.         static List<Type> list = new List<Type>
  2.         {
  3.             typeof(DBText),
  4.             typeof(BlockTableRecord),
  5.             typeof(MText),
  6.             typeof(Dimension),
  7.             typeof(Leader),
  8.             typeof(MLeader),
  9.             typeof(Hatch)
  10.         };
  11.  
  12.         private static bool IsObjectAnnotation(ObjectId annObjId)
  13.         {
  14.             return list.Any(t => annObjId.ObjectClass.Equals(RXObject.GetClass(t)));
  15.         }

Хорошо, а можно объяснить смысл вынесения списка из метода?

можно ещё сделать сразу список не типов, а RX классов

Но тогда запись списка станет более громоздкой. Я подумал что стоит один раз написать обращение к RX классу в (как это называется где у нас Any) чем в каждой строке  списка?

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 738
Но тогда запись списка станет более громоздкой. Я подумал что стоит один раз написать обращение к RX классу в (как это называется где у нас Any) чем в каждой строке  списка?
Можно как-то так:
Код - C# [Выбрать]
  1. private static readonly List<RXClass> AnnotativeClasses = new[]
  2.     {
  3.         typeof(DBText),
  4.         typeof(BlockTableRecord),
  5.         typeof(MText),
  6.         typeof(Dimension),
  7.         typeof(Leader),
  8.         typeof(MLeader),
  9.         typeof(Hatch)
  10.     }
  11.     .Select(RXObject.GetClass)
  12.     .ToList();
  13.  
  14. private static bool IsObjectAnnotation(ObjectId annObjId)
  15. {
  16.     return AnnotativeClasses.Any(t => annObjId.ObjectClass.Equals(t));
  17. }
Хорошо, а можно объяснить смысл вынесения списка из метода?
Смысл в ощутимой оптимизации работы программы. В изначальном варианте, при каждом обращении к методу проверки формировался этот список. В исправленном варианте, список формируется только один раз.

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

  • ADN Club
  • ****
  • Сообщений: 270
  • Карма: 24
  • Геодезист
Получается для всех объектов кроме BlockTableRecord надо добавить текущий масштаб, а для BlockTableRecord найти уже все BlockReference и добавить масштаб им?
В идеале да. Не думай, что найти все BlockReference  для конкретного BlockTableRecord так сложно: https://adn-cis.org/kak-najti-vse-vstavki-dinamicheskogo-bloka.html
Ну пару часов провозился, пытаясь внутри не закрытой транзакции, пока описание блок ещё не стало аннотатвиным, его вставкам задать текущей масштаб аннотации  ;D
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.Runtime;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6.  
  7. namespace BD_Function
  8. {
  9.     public class LispFunctionsExtensions
  10.     {
  11.         [LispFunction(nameof(RemoveAnnotation))]
  12.         public bool RemoveAnnotation(ResultBuffer resBuf)
  13.         {
  14.             return SetAnnotation(resBuf, false);
  15.         }
  16.  
  17.         [LispFunction(nameof(AddAnnotation))]
  18.         public static bool AddAnnotation(ResultBuffer resBuf)
  19.         {
  20.             return SetAnnotation(resBuf, true);
  21.         }
  22.  
  23.         private static bool SetAnnotation(ResultBuffer resBuf, bool add)
  24.         {
  25.             if (resBuf == null)
  26.             {
  27.                 return false;
  28.             }
  29.  
  30.             var argArray = resBuf.AsArray();
  31.             var typedValue = argArray[0];
  32.  
  33.             if (typedValue.TypeCode != (short)LispDataType.ObjectId)
  34.             {
  35.                 return false;
  36.             }
  37.  
  38.             var annObjId = (ObjectId)typedValue.Value;
  39.  
  40.             if (IsObjectAnnotation(annObjId) == false)
  41.             {
  42.                 return false;
  43.             }
  44.  
  45.             using (var tr = annObjId.Database.TransactionManager.StartTransaction())
  46.             {
  47.                 var obj = tr.GetObject(annObjId, OpenMode.ForWrite, false, true);
  48.                 obj.Annotative = add ? AnnotativeStates.True : AnnotativeStates.False;
  49.  
  50.                 if (add)
  51.                 {
  52.                     AddCurrentScale(obj);
  53.                 }
  54.  
  55.                 tr.Commit();
  56.             }
  57.             if (IsObjectBlockTableRecord(annObjId) && add)
  58.             {
  59.                 AddCurrentScaleToBlockRef(annObjId);
  60.             }
  61.  
  62.             return true;
  63.         }
  64.  
  65.         private static bool IsObjectBlockTableRecord(ObjectId annObjId)
  66.         {
  67.             return annObjId.ObjectClass.Equals(RXClass.GetClass(typeof(BlockTableRecord)));
  68.         }
  69.  
  70.         private static void AddCurrentScale(DBObject dbObj)
  71.         {
  72.             if (!IsDbObjectBlockTableRecord(dbObj))            
  73.             {
  74.                 Database db = Application.DocumentManager.MdiActiveDocument.Database;
  75.                 ObjectContextManager ocm = db.ObjectContextManager;
  76.                 ObjectContextCollection occ = ocm.GetContextCollection("ACDB_ANNOTATIONSCALES");
  77.                 string cannoscale = Application.GetSystemVariable("CANNOSCALE") as string;
  78.                 dbObj.AddContext(occ.GetContext(cannoscale));
  79.             }
  80.         }
  81.  
  82.         private static void AddCurrentScaleToBlockRef(ObjectId annObjId)
  83.         {
  84.             using (var tr = annObjId.Database.TransactionManager.StartTransaction())
  85.             {
  86.                 BlockTableRecord blockTableRecord = (BlockTableRecord)tr.GetObject(annObjId, OpenMode.ForRead, false, true);
  87.                
  88.                 // получаем все вставки  блока
  89.                 ObjectIdCollection blockRefs = blockTableRecord.GetBlockReferenceIds(true, true);
  90.  
  91.                 // если блок динамический
  92.                 if (blockTableRecord.IsDynamicBlock)
  93.                 {
  94.                     // получаем все анонимные блоки динамического блока
  95.                     ObjectIdCollection anonymousIds = blockTableRecord.GetAnonymousBlockIds();
  96.                     foreach (ObjectId anonymousBtrId in anonymousIds)
  97.                     {
  98.                         // получаем анонимный блок
  99.                         BlockTableRecord anonymousBtr = (BlockTableRecord)tr.GetObject(anonymousBtrId, OpenMode.ForRead);
  100.                         // получаем все вставки этого блока
  101.                         ObjectIdCollection blockRefIds = anonymousBtr.GetBlockReferenceIds(true, true);
  102.                         foreach (ObjectId id in blockRefIds)
  103.                         {
  104.                             blockRefs.Add(id);
  105.                         }
  106.                     }
  107.                 }
  108.                 foreach (ObjectId objectId in blockRefs)
  109.                 {
  110.                     var obj = tr.GetObject(objectId, OpenMode.ForWrite, false, true);
  111.                     AddCurrentScale(obj);
  112.                 }
  113.                 tr.Commit();
  114.             }
  115.         }
  116.  
  117.         private static readonly List<RXClass> AnnotativeClasses = new[]
  118.         {
  119.         typeof(DBText),
  120.         typeof(BlockTableRecord),
  121.         typeof(MText),
  122.         typeof(Dimension),
  123.         typeof(Leader),
  124.         typeof(MLeader),
  125.         typeof(Hatch)
  126.          }
  127.         .Select(RXObject.GetClass)
  128.         .ToList();
  129.  
  130.         private static bool IsObjectAnnotation(ObjectId annObjId)
  131.         {
  132.             return AnnotativeClasses.Any(t => annObjId.ObjectClass.Equals(t));
  133.         }
  134.  
  135.         private static bool IsDbObjectBlockTableRecord(DBObject dBObject)
  136.         {
  137.             return dBObject.GetRXClass().Equals(RXClass.GetClass(typeof(BlockTableRecord)));
  138.         }
  139.  
  140.     }
  141. }

С динамическими блоками не проверял. С обычными наблюдается такой момент, что после включения аннотативности их описанию, к его вставкам возвращаются все масштабы аннотативности, что были у них раньше, а не только текущий. Не уверен что с этим нужно бороться.

Ну и по коду надеюсь ещё улучшений подкинете, я уж рад что это вообще работает, на красивости пока мозгов не хватает.


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

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