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

ADN Club => AutoCAD .NET API => Тема начата: BearDyugin от 15-04-2021, 20:58:16

Название: Включить\Отключить аннотативность объекта
Отправлено: BearDyugin от 15-04-2021, 20:58:16
Долга меня мучал этот вопрос, на AutoLISP победить не получилось (https://adn-cis.org/forum/index.php?topic=7494.msg23731)
Чуть-чуть стал пробовать силы в .NET опираясь на статью https://adn-cis.org/kak-sdelat-obektyi-autocad-annotativnyimi-v-.net.html
Сваял вот такой код

Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.Runtime;
  4. using System;
  5.  
  6. namespace First_Function
  7. {
  8.     public class LispFunctionsExtensions
  9.     {
  10.         [LispFunction(nameof(RemoveAnnotation))]
  11.         public bool RemoveAnnotation(ResultBuffer resBuf)
  12.         {
  13.             var activeDocument = Application.DocumentManager.MdiActiveDocument;
  14.             if (resBuf != null)
  15.             {
  16.                 Array argArray = resBuf.AsArray();
  17.                 var value = argArray.GetValue(0);
  18.                 TypedValue typedValue = (TypedValue)value;
  19.                 if (typedValue.TypeCode == 5006)
  20.                 {
  21.                     ObjectId annObjId = (ObjectId)typedValue.Value;
  22.                     bool flag = false;
  23.                     Transaction tr = activeDocument.TransactionManager.StartTransaction();
  24.                     using (tr)
  25.                     {
  26.                         DBObject obj = tr.GetObject(annObjId, OpenMode.ForRead);
  27.                         if (obj != null && (obj != null && IsObjectAnnotation(obj)))
  28.                         {
  29.                             flag = true;
  30.                             obj.UpgradeOpen();
  31.                             obj.Annotative = AnnotativeStates.False;
  32.                         }
  33.                         tr.Commit();
  34.                         return flag;
  35.                     }
  36.                 }
  37.                 else return false;
  38.             }
  39.             else return false;
  40.         }
  41.         [LispFunction(nameof(AddAnnotation))]
  42.         public static bool AddAnnotation(ResultBuffer resBuf)
  43.         {
  44.             var activeDocument = Application.DocumentManager.MdiActiveDocument;
  45.             if (resBuf != null)
  46.             {
  47.                 Array argArray = resBuf.AsArray();
  48.                 var value = argArray.GetValue(0);
  49.                 TypedValue typedValue = (TypedValue)value;
  50.                 if (typedValue.TypeCode == 5006)
  51.                 {
  52.                     ObjectId annObjId = (ObjectId)typedValue.Value;
  53.                     bool flag = false;
  54.  
  55.                     Transaction tr = activeDocument.TransactionManager.StartTransaction();
  56.                     using (tr)
  57.                     {
  58.                         DBObject obj = tr.GetObject(annObjId, OpenMode.ForRead);
  59.                         if (obj != null && IsObjectAnnotation(obj))
  60.                         {
  61.                             flag = true;
  62.                             obj.UpgradeOpen();
  63.                             obj.Annotative = AnnotativeStates.True;
  64.                         }
  65.                         tr.Commit();
  66.                         return flag;
  67.                     }
  68.                 }
  69.                 else return false;
  70.             }
  71.             else return false;
  72.         }      
  73.         private static bool IsObjectAnnotation(DBObject annObject)
  74.             {
  75.             RXClass rXClass = annObject.GetRXClass();          
  76.             if (rXClass.Equals(RXClass.GetClass(typeof(DBText)))
  77.                             ||
  78.                             rXClass.Equals(RXClass.GetClass(typeof(BlockTableRecord)))
  79.                             ||
  80.                             rXClass.Equals(RXClass.GetClass(typeof(DBText)))
  81.                             ||
  82.                             rXClass.Equals(RXClass.GetClass(typeof(MText)))
  83.                             ||
  84.                             rXClass.Equals(RXClass.GetClass(typeof(Dimension)))
  85.                             ||
  86.                             rXClass.Equals(RXClass.GetClass(typeof(Leader)))
  87.                             ||
  88.                             rXClass.Equals(RXClass.GetClass(typeof(MLeader)))
  89.                             ||
  90.                             rXClass.Equals(RXClass.GetClass(typeof(Hatch)))                          
  91.                 )
  92.                 return true;
  93.             else
  94.                 return false;
  95.         }
  96.     }
  97. }

Вроде даже работает, но верю что не всю тут по ООП-ешному. Хотел бы выслушать ваши замечания, мне стыдно за свои LISP коды, хочу на C# сразу учится писать по человечески.


Вот такая запись норм?
Код - C# [Выбрать]
  1. (
  2. rXClass.Equals(RXClass.GetClass(typeof(DBText)))
  3. ||
  4. rXClass.Equals(RXClass.GetClass(typeof(BlockTableRecord)))
  5. ||
  6. rXClass.Equals(RXClass.GetClass(typeof(DBText)))
  7. ||
  8. rXClass.Equals(RXClass.GetClass(typeof(MText)))
  9. ||
  10. rXClass.Equals(RXClass.GetClass(typeof(Dimension)))
  11. ||
  12. rXClass.Equals(RXClass.GetClass(typeof(Leader)))
  13. ||
  14. rXClass.Equals(RXClass.GetClass(typeof(MLeader)))
  15. ||
  16. rXClass.Equals(RXClass.GetClass(typeof(Hatch)))                          
  17. )
Или можно как-то прогнать в цикле подставляя только список типов, а не писать кучу однотипных строк?
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: Александр Ривилис от 15-04-2021, 21:03:01
Есть одна, но существенная ошибка. Вместо:
Код - C# [Выбрать]
  1. rXClass.Equals(RXClass.GetClass(typeof(BlockTableRecord)))
должно быть
Код - C# [Выбрать]
  1. rXClass.Equals(RXClass.GetClass(typeof(BlockReference)))
Т.е. не описание блока, а вставка блока.
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: BearDyugin от 15-04-2021, 21:14:26
Есть одна, но существенная ошибка. Вместо:
Код - C# [Выбрать]
  1. rXClass.Equals(RXClass.GetClass(typeof(BlockTableRecord)))
должно быть
Код - C# [Выбрать]
  1. rXClass.Equals(RXClass.GetClass(typeof(BlockReference)))
Т.е. не описание блока, а вставка блока.

Не, тут всё верно, я создаю блоки программно на AutoLISP, и по умолчанию они создаются не аннотативными, и мне нужно включить им аннотативность. Причём при первом создании из AutoLISP можно задать аннотативнсоть, а вот сменить(иногда этот выбор даю пользователю, не все любят и умеют работать с аннотативными объектами) при редактировании описания блока, уже не получится, а эта функция позволяет теперь менять это свойство когда угодно .

А вот для вхождения поменять аннотативность как раз и нельзя.
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: trir от 15-04-2021, 22:32:50
можно сделать список типов и проверять наличие через any
Код - C# [Выбрать]
  1.             var list = new List<Type>
  2.             {
  3.                 typeof(string),
  4.                 typeof(int),
  5.                 typeof(double)
  6.             };
  7.             var t1 = 1;
  8.             float t2 = 1.1f;
  9.             var b1 = list.Any(t => t.Equals(t1.GetType()));
  10.             var b2 = list.Any(t => t.Equals(t2.GetType()));
думай функционально

и у тебя код повторяется - можно вынести в функцию
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: Дмитрий Загорулькин от 16-04-2021, 08:58:49
Записал видео с разбором кода:
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: BearDyugin от 16-04-2021, 09:17:51
Записал видео с разбором кода:
Спасибо большое!

Зачем мы сначала получаем объект для чтения, а потом ещё раз для записи?

Код - C# [Выбрать]
  1. using (var tr = activeDocument.TransactionManager.StartTransaction())
  2.                     {
  3.                         var obj = tr.GetObject(annObjId, OpenMode.ForRead, false, true);
  4.                         if (obj != null && IsObjectAnnotation(obj))
  5.                         {
  6.                             flag = true;
  7.                             var objForWrite = tr.GetObject(annObjId, OpenMode.ForWrite, false, true);
  8.                             if (objForWrite != null)
  9.                             {
  10.                                 objForWrite.Annotative = add ? AnnotativeStates.False : AnnotativeStates.False;
  11.                             }
  12.                         }
  13.                         tr.Commit();                        
  14.                     }

Нельзя сразу открыть его на запись? Или типа когда на запись, то читать нельзя, можно только писать? Проверил только с ForWrite вроде работает

Код - C# [Выбрать]
  1. using (var tr = activeDocument.TransactionManager.StartTransaction())
  2.                     {
  3.                         var obj = tr.GetObject(annObjId, OpenMode.ForWrite, false, true);
  4.                         if (obj != null && IsObjectAnnotation(obj))
  5.                         {
  6.                             flag = true;                          
  7.                             obj.Annotative = add ? AnnotativeStates.False : AnnotativeStates.False;                            
  8.                         }
  9.                         tr.Commit();                        
  10.                     }
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: Дмитрий Загорулькин от 16-04-2021, 09:39:51
Зачем мы сначала получаем объект для чтения, а потом ещё раз для записи?
Ну, типа не открываем объект на запись без необходимости. На чтение быстрее открывается, при этом объект не блокируется для других "читателей". Но это уже тонкости, конечно.
Нельзя сразу открыть его на запись?
Можно и так, конечно. Но надо понимать, что если объект неподходящего типа, то было избыточное открытие его на запись. В 99% случаев, это, скорее всего, не приведёт ни к каким последствиям, кроме ухудшения быстродействия.
Или типа когда на запись, то читать нельзя, можно только писать?
Можно и писать и читать.

P.S. Если уж совсем по уму, то можно проверить тип объекта, не открывая его, по Id. Вот там как раз пригодятся RXClass и сравнение по ним. И тогда можно будет проверить тип объекта, и если он подходящий - сразу открывать на запись и изменять. Это было бы красивое решение, ятд.

P.P.S И ещё, в видео забыл сказать. Если у нас есть ObjectId, то из него мы можем получить Database и открыть транзакцию через неё. Не надо получать активный документ.
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: Александр Ривилис от 16-04-2021, 15:53:29
BearDyugin,
obj.Annotative = add ? AnnotativeStates.False : AnnotativeStates.False;   
???
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: BearDyugin от 16-04-2021, 16:03:25
BearDyugin,
obj.Annotative = add ? AnnotativeStates.False : AnnotativeStates.False;   
???
Да там уже другой код, из видео Дмитрия, это его фрагмент, add это новый bool аргумент, чтоб один метод по нему либо добавлял либо удалял аннотатвиность.
Такая укороченная запись IF мне пока совсем не привычна, но для кратких записей очень удобно.

А ещё по последним Диминым замечаниям правки не внёс, как внесу опубликую полный текст нового кода.
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: Александр Ривилис от 16-04-2021, 16:08:21
BearDyugin,
Ты видимо не понял меня. Эта запись вне зависимости от значения add эквивалентна:
Код - C# [Выбрать]
  1. obj.Annotative = AnnotativeStates.False;
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: BearDyugin от 16-04-2021, 16:11:02
BearDyugin,
Ты видимо не понял меня. Эта запись вне зависимости от значения add эквивалентна:
Код - C# [Выбрать]
  1. obj.Annotative = AnnotativeStates.False;

Да, точно опечатка, два раза false, я его пока не дописал и не тестировал больше.
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: BearDyugin от 18-04-2021, 18:54:56
Вроде все замечания учёл, как избавится от flag не придумал
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.DatabaseServices;
  2. using Autodesk.AutoCAD.Runtime;
  3. using System;
  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.             bool flag;
  46.  
  47.             using (var tr = annObjId.Database.TransactionManager.StartTransaction())
  48.             {
  49.                 var obj = tr.GetObject(annObjId, OpenMode.ForWrite, false, true);
  50.                 if (flag = (obj != null))
  51.                 {
  52.                     obj.Annotative = add ? AnnotativeStates.True : AnnotativeStates.False;
  53.                 }
  54.                 tr.Commit();
  55.             }
  56.  
  57.             return flag;
  58.         }
  59.        
  60.         private static bool IsObjectAnnotation(ObjectId annObjId)
  61.         {
  62.             var list = new List<Type>
  63.             {
  64.                 typeof(DBText),
  65.                 typeof(BlockTableRecord),
  66.                 typeof(MText),
  67.                 typeof(Dimension),
  68.                 typeof(Leader),
  69.                 typeof(MLeader),
  70.                 typeof(Hatch)
  71.             };
  72.             return list.Any(t => annObjId.ObjectClass.Equals(RXObject.GetClass(t)));
  73.         }
  74.    
  75.     }
  76. }

Ещё в коде из статьи было добавление объекту текущего масштаба аннотации
Код - C# [Выбрать]
  1. // Добавляем текущий масштаб
  2.             string cannoscale = Application.GetSystemVariable("CANNOSCALE") as string;
  3.             obj.AddContext(occ.GetContext(cannoscale));

Проверил работает и без этого, при включении аннотативности, автоматом добавляется текущий масштаб. Может в старых версиях AutoCAD так не работало?
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: Александр Ривилис от 18-04-2021, 19:36:13
Не очень понятна эта проверка:
Код - C# [Выбрать]
  1.  if (flag = (obj != null))
obj не может стать равным null. Если предыдущая строка не сработает по каким-либо причинам, то возникнет исключение и дальнейший код выполняться не будет.
Может в старых версиях AutoCAD так не работало?
Точно не работало. И еще зависит от ANNOALLVISIBLE (https://knowledge.autodesk.com/ru/support/autocad/learn-explore/caas/CloudHelp/cloudhelp/2021/RUS/AutoCAD-Core/files/GUID-D8E50F6F-FB71-4A20-A3B9-7701C0518B81-htm.html) - если равно 0, то объекты, которые не поддерживают данный масштаб просто не будут видны.
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: BearDyugin от 18-04-2021, 21:57:15
Не очень понятна эта проверка:
Код - C# [Выбрать]
  1.  if (flag = (obj != null))
obj не может стать равным null. Если предыдущая строка не сработает по каким-либо причинам, то возникнет исключение и дальнейший код выполняться не будет.
Были такие мысли, спасибо, тогда нам и flag не нужен, после транзакции возвращаем true.

Может в старых версиях AutoCAD так не работало?
Точно не работало.
Получается для всех объектов кроме BlockTableRecord надо добавить текущий масштаб, а для BlockTableRecord найти уже все BlockReference и добавить масштаб им?
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: Дмитрий Загорулькин от 18-04-2021, 22:32:05
obj не может стать равным null
Вроде, если объект будет удалён, то вернёт null. Хотя, вероятность того, что в лисп-функцию прилетит удалённый объект, крайне мала.
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: Александр Ривилис от 18-04-2021, 22:34:01
Получается для всех объектов кроме BlockTableRecord надо добавить текущий масштаб, а для BlockTableRecord найти уже все BlockReference и добавить масштаб им?
В идеале да. Не думай, что найти все BlockReference  для конкретного BlockTableRecord так сложно: https://adn-cis.org/kak-najti-vse-vstavki-dinamicheskogo-bloka.html
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: Александр Ривилис от 18-04-2021, 22:36:36
obj не может стать равным null
Вроде, если объект будет удалён, то вернёт null. Хотя, вероятность того, что в лисп-функцию прилетит удалённый объект, крайне мала.
Для удаленного объекта (entget) возвращает nil. Так что его список передать в эту функцию не удастся. Хотя конечно можно сначала получить список, а затем удалить. Но мне кажется что будет не null, а исключение. Впрочем, нужно проверять.
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: trir от 19-04-2021, 08:01:55
Код - 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.         }
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: Дмитрий Загорулькин от 19-04-2021, 09:56:50
trir, можно ещё сделать сразу список не типов, а RX классов
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: BearDyugin от 19-04-2021, 16:20:57
Получается для всех объектов кроме 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) чем в каждой строке  списка?
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: Дмитрий Загорулькин от 19-04-2021, 16:58:24
Но тогда запись списка станет более громоздкой. Я подумал что стоит один раз написать обращение к 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. }
Хорошо, а можно объяснить смысл вынесения списка из метода?
Смысл в ощутимой оптимизации работы программы. В изначальном варианте, при каждом обращении к методу проверки формировался этот список. В исправленном варианте, список формируется только один раз.
Название: Re: Включить\Отключить аннотативность объекта
Отправлено: BearDyugin от 22-04-2021, 19:54:47
Получается для всех объектов кроме 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. }

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

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

Название: Re: Включить\Отключить аннотативность объекта
Отправлено: Александр Ривилис от 22-04-2021, 21:02:58
Ну пару часов провозился, пытаясь внутри не закрытой транзакции, пока описание блок ещё не стало аннотатвиным, его вставкам задать текущей масштаб аннотации 
Ну главное, что смог сам разобраться. :)