Как узнать, вставлен ли блок в другой блок

Автор Тема: Как узнать, вставлен ли блок в другой блок  (Прочитано 13117 раз)

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

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

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

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

Существует ли возможность, зная ObjectId блока,
узнать вставлен ли он в другой блок?
И если да, то как узнать, в какой именно?

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
зная ObjectId блока
Что имеется в виду под блоком? BlockReference (вставка блока) или BlockTableRecord (описание блока) ?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Самый простой, на мой взгляд, вариант:
1. Узнать имя искомого блока. Если знаете ObjectId, значит узнать имя - не проблема
2. Провести итерацию по всем BlockTableRecord в документе
3. В каждом BlockTableRecord провести итерацию по всем объектам внутри и если это блок - сравнить его имя с искомым блоком
Сопроводить это множеством различных условий, чтобы уменьшить количество проверяемых BlockTableRecord

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

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
зная ObjectId блока
Что имеется в виду под блоком? BlockReference (вставка блока) или BlockTableRecord (описание блока) ?
Описание блока.

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

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
Самый простой, на мой взгляд, вариант:
1. Узнать имя искомого блока. Если знаете ObjectId, значит узнать имя - не проблема
2. Провести итерацию по всем BlockTableRecord в документе
3. В каждом BlockTableRecord провести итерацию по всем объектам внутри и если это блок - сравнить его имя с искомым блоком
Сопроводить это множеством различных условий, чтобы уменьшить количество проверяемых BlockTableRecord
Это первое, что приходит в голову. Но на мой взгляд это похоже на брутфорс.

Отмечено как Решение vermesser 18-04-2017, 18:27:22

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Описание блока.
А нужно найти в какие блоки есть вставки этого блока?  Тогда:
1) пользуйся методом BlockTableRecord.GetBlockReferenceIds для получения всех вставок блока.
2) потом для каждой вставки находи свойство BlockId для определения в каком блоке он находится.
3) если же наш блок динамический, то задача усложняется. В этом случае кроме того, что мы проделали для обычного блока нужно еще и найти все его анонимные блоки (BlockTableRecord) при помощи BlockTableRecord.GetAnonymousBlockIds
4) для каждого анонимного блока из 3) переходим к пункту 1).
Вот и весь алгоритм.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
Описание блока.
А нужно найти в какие блоки есть вставки этого блока?  Тогда:
1) пользуйся методом BlockTableRecord.GetBlockReferenceIds для получения всех вставок блока.
2) потом для каждой вставки находи свойство BlockId для определения в каком блоке он находится.
3) если же наш блок динамический, то задача усложняется. В этом случае кроме того, что мы проделали для обычного блока нужно еще и найти все его анонимные блоки (BlockTableRecord) при помощи BlockTableRecord.GetAnonymousBlockIds
4) для каждого анонимного блока из 3) переходим к пункту 1).
Вот и весь алгоритм.
Да, блок динамический. Спасибо! Я сделаю так и отпишусь.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Да, блок динамический. Спасибо! Я сделаю так и отпишусь.
Вот тебе заготовка для решения этой задачи: http://adn-cis.org/kak-najti-vse-vstavki-dinamicheskogo-bloka.html
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
Да, блок динамический. Спасибо! Я сделаю так и отпишусь.
Вот тебе заготовка для решения этой задачи: http://adn-cis.org/kak-najti-vse-vstavki-dinamicheskogo-bloka.html
Спасибо! Это я уже использую.

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

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
Описание блока.
А нужно найти в какие блоки есть вставки этого блока?  Тогда:
1) пользуйся методом BlockTableRecord.GetBlockReferenceIds для получения всех вставок блока.
2) потом для каждой вставки находи свойство BlockId для определения в каком блоке он находится.
3) если же наш блок динамический, то задача усложняется. В этом случае кроме того, что мы проделали для обычного блока нужно еще и найти все его анонимные блоки (BlockTableRecord) при помощи BlockTableRecord.GetAnonymousBlockIds
4) для каждого анонимного блока из 3) переходим к пункту 1).
Вот и весь алгоритм.
Работает, но BlockId выдаёт и *ModelSpace в качестве родительского блока. Вот такой код:
Код - vb.net [Выбрать]
  1. Dim blockTabRec As BlockTableRecord = tr.GetObject(blockTab(anchorBlockName), OpenMode.ForRead)
  2. 'Анонимные блоки - различные состояния динамического блока,
  3. 'поэтому ищем все анонимные блоки
  4. Dim anonBtrIDs As ObjectIdCollection = blockTabRec.GetAnonymousBlockIds
  5. Dim layerTab As LayerTable = tr.GetObject(db.LayerTableId, OpenMode.ForRead)
  6. For Each anonBtrID In anonBtrIDs
  7.     Dim anonBlockTabRec As BlockTableRecord = tr.GetObject(anonBtrID, OpenMode.ForRead)
  8.     'Получаем вхождения анонимых блоков
  9.     Dim brIDs As ObjectIdCollection = anonBlockTabRec.GetBlockReferenceIds(True, True)
  10.     For Each id In brIDs
  11.         Dim block As BlockReference = tr.GetObject(id, OpenMode.ForRead)
  12.         'Если блок динамический
  13.         If block.DynamicBlockReferencePropertyCollection.Count > 0 Then
  14.             Dim layerTabRec As LayerTableRecord = tr.GetObject(layerTab(block.Layer), OpenMode.ForRead)
  15.             If Not (layerTabRec.IsOff Or layerTabRec.IsFrozen) Then
  16.                 blockIDs.Add(id)
  17.                 Dim parentBlockTabRec As BlockTableRecord = tr.GetObject(block.BlockId, OpenMode.ForRead)
  18.                 ed.WriteMessage(vbCrLf & parentBlockTabRec.Name)
  19.             End If
  20.         Else
  21.             'Если блок не динамический
  22.             ed.WriteMessage(vbCrLf & "Блок {0} не соответствует требованиям: блок должен быть динамическим. ", anchorBlockName)
  23.         End If
  24.     Next
  25. Next
  26.  
Такой вывод:
Команда: WHOISMYPARENT
Какой-то блок
*Model_Space
Всё так и есть - один блок вставлен в Какой-то блок.
Другой просто находится в пространстве модели.
То есть работает-то работает, но не совсем как надо.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
1. Судя по коду ты обрабатываешь только анонимные блоки. Т.е. ты считаешь, что в неизменном виде этого динамического блока быть не может?
2. Вот эта проверка лишняя: If block.DynamicBlockReferencePropertyCollection.Count > 0 Then так как анонимные блоки ты получаешь только для динамического блока.
Всё так и есть - один блок вставлен в Какой-то блок.
Другой просто находится в пространстве модели.
То есть работает-то работает, но не совсем как надо.
Не понял что тебя не устраивает. Вроде бы это в точности постановка задачи. Или тебя не интересуют блоки вставленные прямо в Пространство модели? Если не интересуют, то ты можешь отсечь *Model_Space (а при желании и *Paper_Space) проверив, что BlockTableRecord.IsLayout для него возвращает false
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
1. Судя по коду ты обрабатываешь только анонимные блоки. Т.е. ты считаешь, что в неизменном виде этого динамического блока быть не может?
2. Вот эта проверка лишняя: If block.DynamicBlockReferencePropertyCollection.Count > 0 Then так как анонимные блоки ты получаешь только для динамического блока.
Всё так и есть - один блок вставлен в Какой-то блок.
Другой просто находится в пространстве модели.
То есть работает-то работает, но не совсем как надо.
Не понял что тебя не устраивает. Вроде бы это в точности постановка задачи. Или тебя не интересуют блоки вставленные прямо в Пространство модели? Если не интересуют, то ты можешь отсечь *Model_Space (а при желании и *Paper_Space) проверив, что BlockTableRecord.IsLayout для него возвращает false
Да, Вы правы. Всё исправил и сделал проверку IsLayout. Теперь получилось всё, как я хотел.
Спасибо в третий раз!

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

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

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

  • ADN OPEN
  • **
  • Сообщений: 66
  • Карма: 2
Вот код:
Код - vb.net [Выбрать]
  1. <Autodesk.AutoCAD.Runtime.CommandMethod("BXYZDIFFS")> _
  2. Public Sub BXYZDIFFS()
  3.  
  4.     Const anchorBlockName As String = "Анкер (Стандарт)"
  5.     Const anchorBlockLayer As String = "0_АНКЕРА"
  6.  
  7.     doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
  8.     ed = doc.Editor
  9.     db = doc.Database
  10.  
  11.     Dim blockIDs As ObjectIdCollection = New ObjectIdCollection
  12.  
  13.     Try
  14.  
  15.         Using lockDoc As DocumentLock = doc.LockDocument()
  16.  
  17.             Using tr As Transaction = db.TransactionManager.StartTransaction
  18.  
  19.                 Using layerTab As LayerTable = tr.GetObject(db.LayerTableId, OpenMode.ForRead)
  20.                     If layerTab.Has(anchorBlockLayer) = False Then
  21.                         ed.WriteMessage(vbCrLf & "В чертеже не найден слой {0}. ", anchorBlockLayer)
  22.                         Exit Sub
  23.                     Else
  24.                         Using layerTabRec As LayerTableRecord = tr.GetObject(layerTab(anchorBlockLayer), OpenMode.ForRead)
  25.                             If (layerTabRec.IsOff Or layerTabRec.IsFrozen) Then
  26.                                 ed.WriteMessage(vbCrLf & "Слой {0} выключен и/или заморожен. ", anchorBlockLayer)
  27.                                 Exit Sub
  28.                             End If
  29.                         End Using
  30.                     End If
  31.                 End Using
  32.  
  33.                 Dim blockTab As BlockTable = tr.GetObject(db.BlockTableId, OpenMode.ForRead)
  34.                 If blockTab.Has(anchorBlockName) Then
  35.                     Dim blockTabRec As BlockTableRecord = tr.GetObject(blockTab(anchorBlockName), OpenMode.ForRead)
  36.                     'Анонимные блоки - различные состояния динамического блока,
  37.                     'поэтому ищем все анонимные блоки
  38.                     Dim anonBtrIDs As ObjectIdCollection = blockTabRec.GetAnonymousBlockIds
  39.                     Dim layerTab As LayerTable = tr.GetObject(db.LayerTableId, OpenMode.ForRead)
  40.                     For Each anonBtrID In anonBtrIDs
  41.                         Dim anonBlockTabRec As BlockTableRecord = tr.GetObject(anonBtrID, OpenMode.ForRead)
  42.                         'Получаем вхождения анонимых блоков
  43.                         Dim brIDs As ObjectIdCollection = anonBlockTabRec.GetBlockReferenceIds(True, True)
  44.                         For Each id In brIDs
  45.                             Dim block As BlockReference = tr.GetObject(id, OpenMode.ForRead)
  46.                             Dim layerTabRec As LayerTableRecord = tr.GetObject(layerTab(block.Layer), OpenMode.ForRead)
  47.                             If Not (layerTabRec.IsOff Or layerTabRec.IsFrozen) Then
  48.                                 Dim parentBlockTabRec As BlockTableRecord = tr.GetObject(block.BlockId, OpenMode.ForRead)
  49.                                 If parentBlockTabRec.IsLayout Then
  50.                                     blockIDs.Add(id)
  51.                                 End If
  52.                             End If
  53.                         Next
  54.                     Next
  55.                     'Ищем блоки в неизменном состояния
  56.                     Dim btrIDs As ObjectIdCollection = blockTabRec.GetBlockReferenceIds(True, True)
  57.                     For Each btrID In btrIDs
  58.                         Dim block As BlockReference = tr.GetObject(btrID, OpenMode.ForRead)
  59.                         Dim layerTabRec As LayerTableRecord = tr.GetObject(layerTab(block.Layer), OpenMode.ForRead)
  60.                         If Not (layerTabRec.IsOff Or layerTabRec.IsFrozen) Then
  61.                             Dim parentBlockTabRec As BlockTableRecord = tr.GetObject(block.BlockId, OpenMode.ForRead)
  62.                             If parentBlockTabRec.IsLayout Then
  63.                                 blockIDs.Add(btrID)
  64.                             End If
  65.                         End If
  66.                     Next
  67.                 Else
  68.                     ed.WriteMessage(vbCrLf & "Не найден блок {0}. ", anchorBlockName)
  69.                     Exit Sub
  70.                 End If
  71.  
  72.                 ed.WriteMessage(vbCrLf & blockIDs.Count.ToString & " ")
  73.  
  74.                 tr.Commit()
  75.  
  76.             End Using
  77.  
  78.         End Using
  79.  
  80.     Catch ex As Exception
  81.         ed.WriteMessage(vbCrLf & "Во время выполнения произошла ошибка. " & ex.Message)
  82.     End Try
  83.  
  84. End Sub
А непрохождение проверки IsLayout гарантирует, что блок вставлен в блок?

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
А непрохождение проверки IsLayout гарантирует, что блок вставлен в блок?
Гарантирует, что блок вставлен в блок, отличный от Пространства Листа или Пространство Модели. Пространство Листа и Пространство Модели - это тоже блоки. Причем если Пространство Модели может быть только одно, то Пространств Листа может быть множество.

Если я правильно понял логику твоей программы, то вместо
Код - vb.net [Выбрать]
  1. If parentBlockTabRec.IsLayout Then
  2.         blockIDs.Add(btrID)
  3. End If
должно быть
Код - vb.net [Выбрать]
  1. If Not parentBlockTabRec.IsLayout Then
  2.         blockIDs.Add(btrID)
  3. End If
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение