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

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

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

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

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

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

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
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
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь 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
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь 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
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь 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
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Re: Как перебирать только блоки?
« Ответ #12 : 31-08-2015, 15:44:59 »
1. Динамический блок при изменениях меняет свое имя, так что указанным тобой способом ты его не получишь.
2. Пробуй не полный перебор, а выбор с фильтром.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь 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. Теперь только их и перебираем.

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

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

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

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

А давайте попробуем обойти это ограничение.


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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #17 : 31-08-2015, 16:03:24 »
Попробуй оба варианта, сравни и выбери нужный.

Оба, в смысле перебор и выбор с фильтром.

Очень близко тому, что я хочу! Спасибо, попробую! Только уже завтра.

Аллилуйя, то, что и искал!

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #18 : 31-08-2015, 16:03:45 »
Типа *U80, *U81 и т.д?
Да.
Александр, не поймите меня неправильно, но в этом коде я вижу как перебираются все объекты (допустим, что их 25 006 объектов), у меня даже 10324 объекта долго перебираются (и этот чертеж всего 650 килобайт), а что если мне принесут на тест чертеж 13 Мб (я уже боюсь представить, что такой модуль просто где-нибудь встанет)
Код - vb.net: [Выделить]

    For Each acObjId As ObjectId In acBlkTblRec ' Здесь перебираются все объекты
      If acObjId.ObjectClass().DxfName = "INSERT" Then
      ' здесь обработка только блоков
      End If
    Next


Я уже это делать умею, но время на перебор затрачивается достаточно большое. А я хочу обойти это с другой стороны.
Это очень быстрая операция. Просто возьми и проверь. Не нужно теоретизировать. У меня есть программы, которые перебирают все объекты в чертеже (не только в пространстве модели), да еще и модифицируют его (REMOVEALLPROXY). И работает это единицы секунд на чертежах размером в десятки мегабайт. Быстрее можно только если все нужные тебе блоки видны на экране. И тогда можно их отфильтровать (но не по имени).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #19 : 31-08-2015, 16:11:15 »
А давайте попробуем обойти это ограничение.
Ну-ну. Хочу посмотреть как это тебе удастся сделать.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #20 : 31-08-2015, 16:13:29 »
Это очень быстрая операция. Просто возьми и проверь. Не нужно теоретизировать. Быстрее можно только если все нужные тебе блоки видны на экране. И тогда можно их отфильтровать (но не по имени).

Я это уже сделал на VBA, но нужно на VB.NET

Около минуты просто перебираются объекты и спрашивается у них, а вы "AcDbBlockReference"? И я еще даже с ними ничего не делал.
Дело в том, что вывожу в командную строку информацию об объекте. Может это мешает. Но всё становится еще хуже, когда, я использую форму и отображаю процесс выполнения задачи. Поэтому лишнее нужно железно убирать из перебора заранее.

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #21 : 31-08-2015, 16:14:37 »
Ну-ну. Хочу посмотреть как это тебе удастся сделать

Надеюсь, что завтра все получится.

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

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Re: Как перебирать только блоки?
« Ответ #22 : 31-08-2015, 16:16:56 »
Судя по вот этому AcDbBlockReference, хочется задать вопрос, а Вы на .NET пишите?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #23 : 31-08-2015, 16:21:29 »
Дело в том, что вывожу в командную строку информацию об объекте. Может это мешает.
Именно это и мешает.
Но всё становится еще хуже, когда, я использую форму и отображаю процесс выполнения задачи.
Попробуй ProgressMeter. Пример использования: http://adndevblog.typepad.com/autocad/2013/02/return-to-command-prompt-when-escape-is-pressed-using-net.html
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #24 : 31-08-2015, 16:23:35 »
Судя по вот этому AcDbBlockReference, хочется задать вопрос, а Вы на .NET пишите?
Ну точно не на C++ с использованием ObjectARX. :) Это он имя класса получает при помощи COM/ActiveX.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Re: Как перебирать только блоки?
« Ответ #25 : 31-08-2015, 16:25:42 »
Это он имя класса получает при помощи COM/ActiveX.
Так я вот именно про это, что он не методы .net api использует...

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #26 : 31-08-2015, 16:35:35 »
Надеюсь, что завтра все получится.
Я проверил скорость обработки твоего чертежа-примера. Только при помощи команды _ARRAY увеличил количество рамок в сто раз (объектов в чертеже стало около 500000). REMOVEALLPROXY отработала менее чем за секунду. Делай выводы.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Re: Как перебирать только блоки?
« Ответ #27 : 31-08-2015, 16:51:04 »
но в этом коде я вижу как перебираются все объекты (допустим, что их 25 006 объектов), у меня даже 10324 объекта долго перебираются (и этот чертеж всего 650 килобайт), а что если мне принесут на тест чертеж 13 Мб (я уже боюсь представить, что такой модуль просто где-нибудь встанет)
Долго получать объект и проверять его, а проверить его указатель (ObjectId) - это очень быстрая опреация и не забывайте, что через COM - вы не только получаете объект, но и пересылаете его целиком на каждой операции получения - .Net же работает "изнутри" автокада.

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #28 : 01-09-2015, 07:02:48 »
Я проверил скорость обработки твоего чертежа-примера. Только при помощи команды _ARRAY увеличил количество рамок в сто раз (объектов в чертеже стало около 500000). REMOVEALLPROXY отработала менее чем за секунду. Делай выводы.

Сделал. Но Вы прекрасно знаете, что я пока не готов к этому. Мне Ваш пример с C# на VB.NET перевести еще нужно (из темы Как указать рамку видовому экрану на листе область объекта). Я про нее не забыл. Буду Ваши примеры на VB.NET переводить. Это единственное, что я сейчас могу сделать по факту.

Долго получать объект и проверять его, а проверить его указатель (ObjectId) - это очень быстрая опреация и не забывайте, что через COM - вы не только получаете объект, но и пересылаете его целиком на каждой операции получения - .Net же работает "изнутри" автокада.

 Спасибо, я пониманию почему теряю время. Главное, что теперь решение есть. Готовое решение выложу в двух вариантах (COM и VB.NET).

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #29 : 01-09-2015, 07:58:56 »
Первый вариант AutoCAD NET Interop COM / ActiveX:

Код - vb.net [Выбрать]
  1. Imports Autodesk.AutoCAD.Runtime
  2. Imports Autodesk.AutoCAD.Interop.Common
  3. Imports Autodesk.AutoCAD.Interop
  4.  
  5. Public Class Gal_Search_Blocks_In_Model
  6.     Public Class SearchBlock
  7.  
  8.         <CommandMethod("GALSEARCHBLOCKONLY")> _
  9.         Public Sub Search_Block()
  10.             Dim acApp As AcadApplication
  11.             Dim acDoc As AcadDocument
  12.  
  13.             acApp = Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication
  14.             acDoc = acApp.ActiveDocument
  15.  
  16.             Dim i As Long
  17.  
  18.             ' Проверяем наличие ненужных выборок
  19.             For i = 0 To acDoc.SelectionSets.Count - 1
  20.                 acDoc.SelectionSets.Item(0).Delete()
  21.             Next i
  22.  
  23.             ' Создаем выборку
  24.             Dim sset As AcadSelectionSet
  25.             sset = acDoc.SelectionSets.Add("MySelSet")
  26.  
  27.             ' Определяем фильтр, по которому будет проводить отбор
  28.             Dim FT(0) As Short ' Здесь была запарка (в документации здесь стоял Integer)
  29.             Dim FD(0) As Object
  30.             FT(0) = 0
  31.             FD(0) = "INSERT"
  32.  
  33.             ' Проводим выборку всех объектов, но в выборке должны остаться только блоки
  34.             sset.Select(AcSelect.acSelectionSetAll, , , FT, FD)
  35.  
  36.             ' Покажем в сообщении сколько объектов попало в выборку
  37.             MsgBox("Количество выделенных объектов: " & sset.Count)
  38.  
  39.             ' В конце очищаем выборку
  40.             sset.Delete()
  41.  
  42.  
  43.         End Sub
  44.     End Class
  45. End Class

Работает невероятно шустро!

Со вторым вариантом придется поупираться, но выложу!
« Последнее редактирование: 01-09-2015, 09:39:20 от Пашин Евгений »

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #30 : 01-09-2015, 08:32:57 »
Dim FT(0) As Short ' Здесь была запарка (в документации здесь стоял Integer)
Документация написана для VBA. А Integer в VBA - это Short в VB.NET (и в C#).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #31 : 01-09-2015, 09:09:29 »
Документация написана для VBA. А Integer в VBA - это Short в VB.NET (и в C#).

Шаг за шагом и чистый VB.NET освою.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #32 : 01-09-2015, 12:18:14 »
Весь оффтопик перебросил сюда: http://adn-cis.org/forum/index.php?topic=2956.0
Прошу в дальнейшем придерживаться темы!
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #33 : 01-09-2015, 12:22:11 »
Второй вариант решения (на чистом NET):

Код - vb.net [Выбрать]
  1. Imports Autodesk.AutoCAD.Runtime
  2. Imports Autodesk.AutoCAD.ApplicationServices
  3. Imports Autodesk.AutoCAD.DatabaseServices
  4. Imports Autodesk.AutoCAD.EditorInput
  5.  
  6. Public Class Gal_Search_Blocks_In_Model
  7.     Public Class SearchBlockNET
  8.  
  9.         <CommandMethod("GALSEARCHBLOCKONLYNET")> _
  10.         Public Sub Search_Block_NET()
  11.  
  12.             ' Получение редактора текущего документа (напрашивается вопрос: что под редактором текущего документа подразумевается)
  13.             Dim acDocEd As Editor = Application.DocumentManager.MdiActiveDocument.Editor
  14.  
  15.             ' Создание массива acFilter для определение параметров фильтра
  16.             Dim acFilter(0) As TypedValue ' Класс Автокада для определения параметров фильтра
  17.             acFilter.SetValue(New TypedValue(DxfCode.Start, "INSERT"), 0)
  18.  
  19.             ' Создание нового класса SelectionFilter и присвоение ему значений параметрво фильтра
  20.             Dim acSelectionFilter As SelectionFilter = New SelectionFilter(acFilter)
  21.  
  22.             ' Создание класса выборки
  23.             Dim acSelSet As PromptSelectionResult
  24.             acSelSet = acDocEd.SelectAll(acSelectionFilter)
  25.  
  26.             ' Если всё OK, тогда объекты выбраны
  27.             If acSelSet.Status = PromptStatus.OK Then
  28.                 Dim acSSet As SelectionSet = acSelSet.Value
  29.                 Application.ShowAlertDialog("Количество выбранных объектов: " & acSSet.Count.ToString())
  30.             Else
  31.                 Application.ShowAlertDialog("Количество выбранных объектов: 0")
  32.             End If
  33.         End Sub
  34.     End Class

Работает также как и первый вариант: быстро!

Это здесь кажется должно быть.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #34 : 01-09-2015, 13:58:19 »
Только сейчас обратил внимание на то, что у тебя вложенные классы. Это что такое и зачем?

Вот тебе и третий вариант. Сравни его по скорости:
Код - vb.net [Выбрать]
  1. Imports Autodesk.AutoCAD.Runtime
  2. Imports Autodesk.AutoCAD.ApplicationServices
  3. Imports Autodesk.AutoCAD.DatabaseServices
  4. Imports Autodesk.AutoCAD.EditorInput
  5. Namespace RAN
  6. Public Class SearchBlockNET
  7.         <CommandMethod("CountInserts")> _
  8.         Public Sub CountInserts()
  9.             Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
  10.             Dim acCurDb As Database = acDoc.Database
  11.             Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
  12.                 Dim acBlkTbl As BlockTable
  13.                 acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)
  14.                 Dim acBlkTblRec As BlockTableRecord
  15.                 acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), _
  16.                                                 OpenMode.ForRead)
  17.                 Dim nInserts as Integer
  18.                 nInserts = 0
  19.                 For Each acObjId As ObjectId In acBlkTblRec ' Здесь перебираются все объекты
  20.                    If (acObjId.ObjectClass().DxfName = "INSERT") Then ' Отбираем только вставки блоков  
  21.                       nInserts = nInserts + 1
  22.                    End If
  23.                 Next
  24.                 acTrans.Commit() ' Так будет быстрее работать
  25.             End Using
  26.             Application.ShowAlertDialog("Количество найденых блоков: " & nInserts.ToString())  
  27.         End Sub
  28.     End Class
  29. End Namespace
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #35 : 01-09-2015, 14:23:40 »
Работает  :)

Тоже быстро! Этот модуль действительно перебирает все объекты? Или у меня глюки?

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

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Re: Как перебирать только блоки?
« Ответ #36 : 01-09-2015, 15:27:32 »
в 26 строке nInserts вне зоны видимости, или я что то опять перепутал.
На всякий случай, операторы += и -= в VB.net вполне себе работают и уже довольно давно(
Извините, вам запрещён просмотр содержимого спойлеров.
)
Извините, вам запрещён просмотр содержимого спойлеров.


Отмечено как Решение Александр Ривилис 02-09-2015, 01:46:21

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #37 : 01-09-2015, 15:29:17 »
Я забыл, что Dim nInserts As Integer двигал повыше )))

Код - vb.net [Выбрать]
  1. Imports Autodesk.AutoCAD.Runtime
  2. Imports Autodesk.AutoCAD.ApplicationServices
  3. Imports Autodesk.AutoCAD.DatabaseServices
  4. Imports Autodesk.AutoCAD.EditorInput
  5.  
  6.  
  7. Namespace RAN
  8.     Public Class SearchBlockNET
  9.         <CommandMethod("CountInserts")> _
  10.         Public Sub CountInserts()
  11.             Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
  12.             Dim acCurDb As Database = acDoc.Database
  13.  
  14.             Dim nInserts As Integer
  15.  
  16.             Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
  17.                 Dim acBlkTbl As BlockTable
  18.                 acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)
  19.                 Dim acBlkTblRec As BlockTableRecord
  20.                 acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), _
  21.                                                 OpenMode.ForRead)
  22.  
  23.                 nInserts = 0
  24.                 For Each acObjId As ObjectId In acBlkTblRec ' Здесь перебираются все объекты
  25.                     If (acObjId.ObjectClass().DxfName = "INSERT") Then ' Отбираем только вставки блоков  
  26.                         nInserts = nInserts + 1
  27.                     End If
  28.                 Next
  29.                 acTrans.Commit() ' Так будет быстрее работать
  30.             End Using
  31.             Application.ShowAlertDialog("Количество найденых блоков: " & nInserts.ToString())
  32.         End Sub
  33.     End Class
  34. End Namespace

Все правильно, просто забыл Александру об этом сказать. Главное работает.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как перебирать только блоки?
« Ответ #38 : 01-09-2015, 15:42:39 »
в 26 строке nInserts вне зоны видимости, или я что то опять перепутал.
Ничего не перепутал. Это я в FAR'е правил текст и само-собой его не проверял. Ну бывает и на старуху проруха...
Тоже быстро! Этот модуль действительно перебирает все объекты? Или у меня глюки?
Перебирает все, но считает только вставки блоков. А ты думаешь что Editor.SelectAll() с фильтром работает иначе? Нет конечно. Проход по всем и сравнение с фильтром.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как перебирать только блоки?
« Ответ #39 : 01-09-2015, 15:45:15 »
Проход по всем и сравнение с фильтром.

Хорошая штука!