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

ADN Club => AutoCAD .NET API => Тема начата: Atomohod от 21-01-2019, 22:00:13

Название: Смена слоя для всех блоков
Отправлено: Atomohod от 21-01-2019, 22:00:13
Здравствуйте!

Пишу программку переносящую все объекты с одного слоя на другой. На уровне отдельных примитивов (линии, тексты и т.д.) все работает, но не сбрасывает на нужный слой блоки целиком (BlockTableRecord) в том числе и блоки внутри других блоков. Что нужно подправить в моем коде? Я слегка запутался.
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Internal;
  5. using Autodesk.AutoCAD.LayerManager;
  6. using Autodesk.AutoCAD.Runtime;
  7.  
  8. namespace AuxiliaryUtilities.Normalizers
  9. {
  10.     public class LayerNormalizer
  11.     {
  12.         [CommandMethod("DropToLayer", CommandFlags.Modal)]
  13.         public void DropBlockEntitiesToDefault()
  14.         {
  15.             Document doc = Application.DocumentManager.MdiActiveDocument;
  16.             Database db = doc.Database;
  17.             Editor ed = doc.Editor;
  18.             using ( Transaction tr = db.TransactionManager.StartTransaction() )
  19.             {
  20.                 string desiredLayer = AuxiliaryUtilities.SelectionUtilities.GetStringParameter("Set desired layer");
  21.                 string pattern = AuxiliaryUtilities.SelectionUtilities.GetStringParameter("Set search pattern");
  22.                 BlockTable bt = (BlockTable) tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  23.                 foreach ( ObjectId btrId in bt )
  24.                 {
  25.                     BlockTableRecord btr = (BlockTableRecord) tr.GetObject(btrId, OpenMode.ForRead);
  26.                     if ( btr.IsFromExternalReference || btr.IsLayout )
  27.                     {
  28.                         continue;
  29.                     }
  30.                    
  31.                     foreach ( ObjectId id in btr )
  32.                     {
  33.                         Entity ent = (Entity) tr.GetObject(id, OpenMode.ForWrite);
  34.                         if ( ent.Layer != desiredLayer && ent.Layer.Contains(pattern) )
  35.                         {
  36.                             ent.Layer = desiredLayer;
  37.                         }
  38.                     }
  39.                 }
  40.  
  41.                 tr.Commit();
  42.             }
  43.  
  44.             ed.Regen();
  45.         }
  46.     }
  47. }
Название: Re: Смена слоя для всех блоков
Отправлено: Александр Пекшев aka Modis от 21-01-2019, 22:02:28
Вижу в коде, что меняется слой примитивов в блоке. Не вижу в коде, чтобы менялся слой у блока
Название: Re: Смена слоя для всех блоков
Отправлено: Александр Пекшев aka Modis от 21-01-2019, 22:03:18
в том числе и блоки внутри других блоков
А тут нужна рекурсия
Название: Re: Смена слоя для всех блоков
Отправлено: Александр Ривилис от 21-01-2019, 22:06:30
Atomohod,
Вот тут неправильно:
Код - C# [Выбрать]
  1. if ( btr.IsFromExternalReference || btr.IsLayout )
  2.                     {
  3.                         continue;
  4.                     }
Ты таким образом не проходишься по ModelSpace и PaperSpace и не меняешь слои примитивам, которые непосредственно в них.
Название: Re: Смена слоя для всех блоков
Отправлено: Atomohod от 21-01-2019, 22:11:59
Ты таким образом не проходишься по ModelSpace и PaperSpace и не меняешь слои примитивам, которые непосредственно в них.
Не понял - почему тогда меняется слой у линий внутри блока, то есть команда отрабатывает, а не меняется лишь у самого блока? Ведь если я вообще не прохожу по содержимому Modelspace. то как тогда она отрабатывает?
Название: Re: Смена слоя для всех блоков
Отправлено: Александр Ривилис от 21-01-2019, 22:12:26
Atomohod,
Ну и не забудь про особенность слоя "0" в блоках.
Название: Re: Смена слоя для всех блоков
Отправлено: Александр Ривилис от 21-01-2019, 22:14:00
Ты таким образом не проходишься по ModelSpace и PaperSpace и не меняешь слои примитивам, которые непосредственно в них.
Не понял - почему тогда меняется слой у линий внутри блока, то есть команда отрабатывает, а не меняется лишь у самого блока? Ведь если я вообще не прохожу по содержимому Modelspace. то как тогда она отрабатывает?
Потому что ты до сих пор не видишь разницу между описанием блока (BlockTableRecord) и вставкой блока (BlockReference). Тебе кроме того, что поменять слой внутри BlockTableRecord нужно еще и поменять слой у BlockReference. В Панели свойств ты видишь BlockReference и соответственно его слой.
Название: Re: Смена слоя для всех блоков
Отправлено: Atomohod от 21-01-2019, 22:14:30
if ( btr.IsFromExternalReference || btr.IsLayout )
Цель этой проверки была исключить из обработки Layout и внешние ссылки. Выходит я не так это реализовал?
Название: Re: Смена слоя для всех блоков
Отправлено: Александр Ривилис от 21-01-2019, 22:17:43
if ( btr.IsFromExternalReference || btr.IsLayout )
Цель этой проверки была исключить из обработки Layout и внешние ссылки. Выходит я не так это реализовал?
Не так. Внешние ссылки тебе действительно нужно пропустить, а вот проверку btr.IsLayout нужно убрать.
А вот дальше нужно понимать чего ты добиваешься, т.е. просто нужно ли заменить "слой1" на "слой2" для всех примитивов или только для элементов внутри блока и вставки этого блока. Если для всех, то достаточно убрать проверку на btr.IsLayout.
Название: Re: Смена слоя для всех блоков
Отправлено: Atomohod от 21-01-2019, 22:21:56
Потому что ты до сих пор не видишь разницу между описанием блока (BlockTableRecord) и вставкой блока (BlockReference). Тебе кроме того, что поменять слой внутри BlockTableRecord нужно еще и поменять слой у BlockReference. В Панели свойств ты видишь BlockReference и соответственно его слой.
Если я правильно понял BlockReference наследник Entity, почему тогда его не обрабатывает этот код:
Код - C# [Выбрать]
  1. foreach ( ObjectId id in btr )
  2.                     {
  3.                         Entity ent = (Entity) tr.GetObject(id, OpenMode.ForWrite);
  4.                         if ( ent.Layer != desiredLayer && ent.Layer.Contains(pattern) )
  5.                         {
  6.                             ent.Layer = desiredLayer;
  7.                         }
  8.                     }
Название: Re: Смена слоя для всех блоков
Отправлено: Александр Ривилис от 21-01-2019, 22:23:23
Atomohod,
Кстати внутри BlockTableRecord могут быть не только Entity. Так что будь осторожен с
Код - C# [Выбрать]
  1. Entity ent = (Entity) tr.GetObject(id, OpenMode.ForWrite);
Тут возможно исключение.
Название: Re: Смена слоя для всех блоков
Отправлено: Atomohod от 21-01-2019, 22:24:39
убрать проверку на btr.IsLayout.
А если мне нужно обработать только содержимое ModelSpace не трогая пространство листа?
Название: Re: Смена слоя для всех блоков
Отправлено: Александр Ривилис от 21-01-2019, 22:25:01
Потому что ты до сих пор не видишь разницу между описанием блока (BlockTableRecord) и вставкой блока (BlockReference). Тебе кроме того, что поменять слой внутри BlockTableRecord нужно еще и поменять слой у BlockReference. В Панели свойств ты видишь BlockReference и соответственно его слой.
Если я правильно понял BlockReference наследник Entity, почему тогда его не обрабатывает этот код:
Код - C# [Выбрать]
  1. foreach ( ObjectId id in btr )
  2.                     {
  3.                         Entity ent = (Entity) tr.GetObject(id, OpenMode.ForWrite);
  4.                         if ( ent.Layer != desiredLayer && ent.Layer.Contains(pattern) )
  5.                         {
  6.                             ent.Layer = desiredLayer;
  7.                         }
  8.                     }
Потому что он у тебя в Модели (или Листе). А ты в него не входишь из-за проверки на btr.IsLayout
Название: Re: Смена слоя для всех блоков
Отправлено: Александр Ривилис от 21-01-2019, 22:25:53
убрать проверку на btr.IsLayout.
А если мне нужно обработать только содержимое ModelSpace не трогая пространство листа?
А если у тебя блок вставлен в пространство листа? Ты же у него внутри слои поменял.
Но если не хочешь трогать примитивы внутри пространства листа, то проверяй btr - это ModelSpace или нет.
Название: Re: Смена слоя для всех блоков
Отправлено: Atomohod от 21-01-2019, 22:27:11
внутри BlockTableRecord могут быть не только Entity
Я и не подумал об этом. А на что можно наткнуться?
Название: Re: Смена слоя для всех блоков
Отправлено: Александр Ривилис от 21-01-2019, 22:28:23
внутри BlockTableRecord могут быть не только Entity
Я и не подумал об этом. А на что можно наткнуться?
Всякие объекты, связанные с динамическими блоками - они не примитивы (т.е. не наследники Entity, а наследники DBObject).
Название: Re: Смена слоя для всех блоков
Отправлено: Atomohod от 21-01-2019, 22:30:08
А если у тебя блок вставлен в пространство листа? Ты же у него внутри слои поменял.
В моем случае это исключено - там только форматки в нулевом слое, видовые окна и все. Любая другая геометрия там исключена - типа корпоративный стандарт и за этим жесткий контроль.
Название: Re: Смена слоя для всех блоков
Отправлено: Александр Ривилис от 21-01-2019, 22:31:51
А если у тебя блок вставлен в пространство листа? Ты же у него внутри слои поменял.
В моем случае это исключено - там только форматки в нулевом слое, видовые окна и все. Любая другая геометрия там исключена - типа корпоративный стандарт и за этим жесткий контроль.
Я бы не стал на это рассчитывать. И вообще то, о чем я сказал - это не геометрия. Это некие свойства.