Смена слоя для всех блоков

Автор Тема: Смена слоя для всех блоков  (Прочитано 13136 раз)

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

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Здравствуйте!

Пишу программку переносящую все объекты с одного слоя на другой. На уровне отдельных примитивов (линии, тексты и т.д.) все работает, но не сбрасывает на нужный слой блоки целиком (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. }

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Смена слоя для всех блоков
« Ответ #1 : 21-01-2019, 22:02:28 »
Вижу в коде, что меняется слой примитивов в блоке. Не вижу в коде, чтобы менялся слой у блока

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Смена слоя для всех блоков
« Ответ #2 : 21-01-2019, 22:03:18 »
в том числе и блоки внутри других блоков
А тут нужна рекурсия

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Смена слоя для всех блоков
« Ответ #3 : 21-01-2019, 22:06:30 »
Atomohod,
Вот тут неправильно:
Код - C# [Выбрать]
  1. if ( btr.IsFromExternalReference || btr.IsLayout )
  2.                     {
  3.                         continue;
  4.                     }
Ты таким образом не проходишься по ModelSpace и PaperSpace и не меняешь слои примитивам, которые непосредственно в них.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Re: Смена слоя для всех блоков
« Ответ #4 : 21-01-2019, 22:11:59 »
Ты таким образом не проходишься по ModelSpace и PaperSpace и не меняешь слои примитивам, которые непосредственно в них.
Не понял - почему тогда меняется слой у линий внутри блока, то есть команда отрабатывает, а не меняется лишь у самого блока? Ведь если я вообще не прохожу по содержимому Modelspace. то как тогда она отрабатывает?

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Смена слоя для всех блоков
« Ответ #5 : 21-01-2019, 22:12:26 »
Atomohod,
Ну и не забудь про особенность слоя "0" в блоках.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Смена слоя для всех блоков
« Ответ #6 : 21-01-2019, 22:14:00 »
Ты таким образом не проходишься по ModelSpace и PaperSpace и не меняешь слои примитивам, которые непосредственно в них.
Не понял - почему тогда меняется слой у линий внутри блока, то есть команда отрабатывает, а не меняется лишь у самого блока? Ведь если я вообще не прохожу по содержимому Modelspace. то как тогда она отрабатывает?
Потому что ты до сих пор не видишь разницу между описанием блока (BlockTableRecord) и вставкой блока (BlockReference). Тебе кроме того, что поменять слой внутри BlockTableRecord нужно еще и поменять слой у BlockReference. В Панели свойств ты видишь BlockReference и соответственно его слой.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Re: Смена слоя для всех блоков
« Ответ #7 : 21-01-2019, 22:14:30 »
if ( btr.IsFromExternalReference || btr.IsLayout )
Цель этой проверки была исключить из обработки Layout и внешние ссылки. Выходит я не так это реализовал?

Отмечено как Решение Atomohod 21-01-2019, 22:36:11

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Смена слоя для всех блоков
« Ответ #8 : 21-01-2019, 22:17:43 »
if ( btr.IsFromExternalReference || btr.IsLayout )
Цель этой проверки была исключить из обработки Layout и внешние ссылки. Выходит я не так это реализовал?
Не так. Внешние ссылки тебе действительно нужно пропустить, а вот проверку btr.IsLayout нужно убрать.
А вот дальше нужно понимать чего ты добиваешься, т.е. просто нужно ли заменить "слой1" на "слой2" для всех примитивов или только для элементов внутри блока и вставки этого блока. Если для всех, то достаточно убрать проверку на btr.IsLayout.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Re: Смена слоя для всех блоков
« Ответ #9 : 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.                     }

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Смена слоя для всех блоков
« Ответ #10 : 21-01-2019, 22:23:23 »
Atomohod,
Кстати внутри BlockTableRecord могут быть не только Entity. Так что будь осторожен с
Код - C# [Выбрать]
  1. Entity ent = (Entity) tr.GetObject(id, OpenMode.ForWrite);
Тут возможно исключение.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Re: Смена слоя для всех блоков
« Ответ #11 : 21-01-2019, 22:24:39 »
убрать проверку на btr.IsLayout.
А если мне нужно обработать только содержимое ModelSpace не трогая пространство листа?

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Смена слоя для всех блоков
« Ответ #12 : 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
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Смена слоя для всех блоков
« Ответ #13 : 21-01-2019, 22:25:53 »
убрать проверку на btr.IsLayout.
А если мне нужно обработать только содержимое ModelSpace не трогая пространство листа?
А если у тебя блок вставлен в пространство листа? Ты же у него внутри слои поменял.
Но если не хочешь трогать примитивы внутри пространства листа, то проверяй btr - это ModelSpace или нет.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Re: Смена слоя для всех блоков
« Ответ #14 : 21-01-2019, 22:27:11 »
внутри BlockTableRecord могут быть не только Entity
Я и не подумал об этом. А на что можно наткнуться?