Как перебирать только блоки?

Автор Тема: Как перебирать только блоки?  (Прочитано 19513 раз)

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

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

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Есть пример кода, где перебираются все объекты в пространстве модели, их может быть много и потому было бы корректно не перебирать их все, а лишь только те, кто является блоком:

Код - vb.net [Выбрать]
  1.         <CommandMethod("OpenTransactionManager")> _
  2.         Public Sub OpenTransactionManager()
  3.             '' Get the current document and database
  4.             Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
  5.             Dim acCurDb As Database = acDoc.Database
  6.  
  7.             '' Start a transaction
  8.             Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
  9.  
  10.                 '' Open the Block table for read
  11.                 Dim acBlkTbl As BlockTable
  12.                 acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)
  13.  
  14.                 '' Open the Block table record Model space for read
  15.                 Dim acBlkTblRec As BlockTableRecord
  16.                 acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), _
  17.                                                 OpenMode.ForRead)
  18.  
  19.                 '' Step through the Block table record
  20.                 For Each acObjId As ObjectId In acBlkTblRec ' Здесь перебираются все объекты
  21.                     acDoc.Editor.WriteMessage(vbLf & "DXF name: " & acObjId.ObjectClass().DxfName)
  22.                     acDoc.Editor.WriteMessage(vbLf & "ObjectID: " & acObjId.ToString())
  23.                     acDoc.Editor.WriteMessage(vbLf & "Handle: " & acObjId.Handle.ToString())
  24.                     acDoc.Editor.WriteMessage(vbLf)
  25.                 Next
  26.  
  27.                 '' Dispose of the transaction
  28.             End Using
  29.         End Sub
  30.     End Class

Как сделать так, чтобы перебирались только блоки?

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

  • Administrator
  • *****
  • Сообщений: 13193
  • Карма: 1701
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #1 : 31-08-2015, 12:31:09 »
В любом случае перебор идёт по всем примитивам, так что быстрее не будет.
Тебе просто нужно сделать что-то такое:
Код - vb.net [Выбрать]
  1. For Each acObjId As ObjectId In acBlkTblRec ' Здесь перебираются все объекты
  2.   If acObjId.ObjectClass().DxfName = "INSERT" Then
  3.   ' здесь обработка только блоков
  4.   End If
  5. Next


Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 579
  • Карма: 138
    • ПГСу Бложик
Re: Как перебирать только блоки?
« Ответ #2 : 31-08-2015, 12:49:08 »
А если получить таблицу блоков, взять от туда описания блоков и для каждого описания получить вхождения?
Или так не прокатит и есть подводные камни?
Код - vb.net [Выбрать]
  1.  BlockTableRecord.GetBlockReferenceIds(true, true) - я про этот метод.
  2.  

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

  • Administrator
  • *****
  • Сообщений: 13193
  • Карма: 1701
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #3 : 31-08-2015, 12:53:25 »
А если получить таблицу блоков, взять от туда описания блоков и для каждого описания получить вхождения?
Или так не прокатит и есть подводные камни?
1. Не думаю, что это будет быстрее, так как всё-равно идёт сканирование базы данных. Причем не только Пространства Модели, а и всех блоков (в том числе и относящихся к Layout).
2. Полученные ObjectId придётся отфильтровывать на предмет принадлежности к Пространству Модели. А это уже требует получения объекта на основе его ObjectId.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 579
  • Карма: 138
    • ПГСу Бложик
Re: Как перебирать только блоки?
« Ответ #4 : 31-08-2015, 13:01:44 »
Нда... про пространство модели я пропустил, в простом переборе с получением класса через RXClass.GetClass быстрее будет. Вот он камешек.

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #5 : 31-08-2015, 14:25:01 »
Полученные ObjectId придётся отфильтровывать на предмет принадлежности к Пространству Модели. А это уже требует получения объекта на основе его ObjectId.

То есть данный перебор объектов происходит по всем объектам чертежа и даже листов? Вот этого точно не надо.



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

  • Administrator
  • *****
  • Сообщений: 13193
  • Карма: 1701
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #6 : 31-08-2015, 14:46:35 »
То есть данный перебор объектов происходит по всем объектам чертежа и даже листов?
Да. И не только по ним, но и по всем блокам. Пространство модели - это блок с именем "*Model_Space". Кроме него в чертеже может быть еще куча разных блоков (описаний блоков - BlockTableRecord), которые также будут просмотрены. И это явно не то, что тебе нужно.

P.S.: Я надеюсь, что ты говоришь не о коде, который сам показал, а о коде Boxa.Shu.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #7 : 31-08-2015, 14:47:49 »
Обалдеть, так это, мне бы потом не помешало бы научиться перебирать объекты внутри блоков тоже )

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

  • Administrator
  • *****
  • Сообщений: 13193
  • Карма: 1701
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #8 : 31-08-2015, 14:50:42 »
Обалдеть, так это, мне бы потом не помешало бы научиться перебирать объекты внутри блоков тоже )
Ну если у тебя вместо:
Код - vb.net [Выбрать]
  1.                 Dim acBlkTblRec As BlockTableRecord
  2.                 acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), _
  3.                                                 OpenMode.ForRead)
будет
Код - vb.net [Выбрать]
  1.                 Dim acBlkTblRec As BlockTableRecord
  2.                 acBlkTblRec = acTrans.GetObject(acBlkTbl("имя_нужного_тебе_блока"), _
  3.                                                 OpenMode.ForRead)
то код будет перебирать примитивы внутри блока.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #9 : 31-08-2015, 14:54:13 »
Получается, если у меня будут блоки с одинаковыми именами, то перебирать он будет по всем блокам с одинаковыми именами? Правильно понимаю?

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

  • Administrator
  • *****
  • Сообщений: 13193
  • Карма: 1701
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #10 : 31-08-2015, 15:04:02 »
Получается, если у меня будут блоки с одинаковыми именами, то перебирать он будет по всем блокам с одинаковыми именами? Правильно понимаю?
Или я не понял вопроса или ты не понимаешь сути блоков в AutoCAD. Есть "описания блоков" (класс BlockTableRecord) - запись таблицы блоков, которая содержит все примитивы, содержащиеся внутри блока. А есть "вставки блоков" (класс BlockReference) - примитив, ссылающийся на "описание блока". Так вот "описание блока" с одним именем в чертеже может быть только одно, а  "вставок блоков" с одним именем может быть сколько угодно, а может и вообще не быть ни одного. И "вставки блоков" могут быть внутри любых других "описаний блоков". В том числе и внутри Пространства модели - "описания блока" с именем "*Model_Space". В отличие от других "описаний блоков" Пространство модели не может иметь никаких вставок в другие "описания блоков".
Надеюсь, что я смог доступно описать разницу между "вставкой блока" и "описанием блока"
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #11 : 31-08-2015, 15:37:00 »
Я попробую уточнить:
список блоков в чертеже.



Итак, не так давно я выкладывал блок рамки, но могу выложить снова.
1. Рамка имеет видимость A4 Вертикальный, А4 Горизонтальный, A3 Вертикальный ... и т.д. Все форматы в одном динамическом блоке. Грубо говоря, в зависимости от видимости формата, одни полилинии становятся видимыми, а другие скрытыми. В одном блоке очень много полилиниий, под каждый формат свои полилинии.



2. Имя у этого блока Рамка_v4 (рис. выше)
3. Таких рамок в пространстве модели может быть множество и каждая из них может быть настроена свой формат. Допустим в модели 6 рамок с именем Рамка_v4: где 1 рамка установлена на формат А4 Вертикальный, 2 рамки установлены на формат А3 Горизонтальный, 3 рамки на формат А2 Вертикальный. А также в пространстве модели еще к примеру 25 000 всевозможных объектов.
4. Исходя из Ваших слов, я понял, что с помощью

Код - vb.net [Выбрать]
  1.                 Dim acBlkTblRec As BlockTableRecord
  2.                 acBlkTblRec = acTrans.GetObject(acBlkTbl("Рамка_v4"), OpenMode.ForRead)

я смогу определять внутри блока примитивы, из которого он состоит.
5. Перебирая объекты внутри блока, хочется определять их видимость, а затем и размеры. И так для каждой рамки в пространстве модели (в моем примере 6 штук).
6. Сейчас мне нужно понять как сделать так, чтобы не пробегать все до единого объекты (к ним я отношу линии, дуги, окружности, размеры, тексты, таблицы и т.д.) в пространстве модели, а только блоки (DXF код которых "INSERT"), так как процедура перебора объектов занимает много времени.

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 579
  • Карма: 138
    • ПГСу Бложик
Re: Как перебирать только блоки?
« Ответ #12 : 31-08-2015, 15:44:59 »
1. Динамический блок при изменениях меняет свое имя, так что указанным тобой способом ты его не получишь.
2. Пробуй не полный перебор, а выбор с фильтром.

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

  • Administrator
  • *****
  • Сообщений: 13193
  • Карма: 1701
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #13 : 31-08-2015, 15:45:36 »
4. Исходя из Ваших слов, я понял, что с помощью

Код - vb.net: [Выделить]

                    Dim acBlkTblRec As BlockTableRecord
                    acBlkTblRec = acTrans.GetObject(acBlkTbl("Рамка_v4"), OpenMode.ForRead)


я смогу определять внутри блока примитивы, из которого он состоит.
Да. Но только с "исходным" состоянием этого динамического блока.
5. Перебирая объекты внутри блока, хочется определять их видимость, а затем и размеры. И так для каждой рамки в пространстве модели (в моем примере 6 штук).
Для этого лезть в этот (!!!) блок не нужно. В зависимости от параметров видимости и других динамических свойств "вставки блока" будут иметь реально разные имена.
6. Сейчас мне нужно понять как сделать так, чтобы не пробегать все до единого объекты (к ним я отношу линии, дуги, окружности, размеры, тексты, таблицы и т.д.) в пространстве модели, а только блоки (DXF код которых "INSERT").
Как это сделать я тебе уже выше написал здесь: http://adn-cis.org/forum/index.php?topic=2964.msg11191#msg11191
Но похоже ты не читаешь или не понимаешь что я тебе пишу :(
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #14 : 31-08-2015, 15:57:22 »
реально разные имена

Типа *U80, *U81 и т.д?

Но похоже ты не читаешь или не понимаешь что я тебе пишу

Александр, не поймите меня неправильно, но в этом коде я вижу как перебираются все объекты (допустим, что их 25 006 объектов), у меня даже 10324 объекта долго перебираются (и этот чертеж всего 650 килобайт), а что если мне принесут на тест чертеж 13 Мб (я уже боюсь представить, что такой модуль просто где-нибудь встанет)

Код - vb.net [Выбрать]
  1. For Each acObjId As ObjectId In acBlkTblRec ' Здесь перебираются все объекты
  2.   If acObjId.ObjectClass().DxfName = "INSERT" Then
  3.   ' здесь обработка только блоков
  4.   End If
  5. Next

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

1. Вручную мы уже умеем выделять объекты используя фильтр (к примеру выделяем рамкой объекты, а в выделение попадают только объекты "INSERT")
2. Теперь только их и перебираем.

Вот как-то так хочется.

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