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

ADN Club => AutoCAD .NET API => Тема начата: Пашин Евгений от 31-08-2015, 12:23:35

Название: Как перебирать только блоки?
Отправлено: Пашин Евгений от 31-08-2015, 12:23:35
Есть пример кода, где перебираются все объекты в пространстве модели, их может быть много и потому было бы корректно не перебирать их все, а лишь только те, кто является блоком:

Код - 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

Как сделать так, чтобы перебирались только блоки?
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 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


Название: Re: Как перебирать только блоки?
Отправлено: Владимир Шу от 31-08-2015, 12:49:08
А если получить таблицу блоков, взять от туда описания блоков и для каждого описания получить вхождения?
Или так не прокатит и есть подводные камни?
Код - vb.net [Выбрать]
  1.  BlockTableRecord.GetBlockReferenceIds(true, true) - я про этот метод.
  2.  
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 31-08-2015, 12:53:25
А если получить таблицу блоков, взять от туда описания блоков и для каждого описания получить вхождения?
Или так не прокатит и есть подводные камни?
1. Не думаю, что это будет быстрее, так как всё-равно идёт сканирование базы данных. Причем не только Пространства Модели, а и всех блоков (в том числе и относящихся к Layout).
2. Полученные ObjectId придётся отфильтровывать на предмет принадлежности к Пространству Модели. А это уже требует получения объекта на основе его ObjectId.
Название: Re: Как перебирать только блоки?
Отправлено: Владимир Шу от 31-08-2015, 13:01:44
Нда... про пространство модели я пропустил, в простом переборе с получением класса через RXClass.GetClass быстрее будет. Вот он камешек.
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 31-08-2015, 14:25:01
Полученные ObjectId придётся отфильтровывать на предмет принадлежности к Пространству Модели. А это уже требует получения объекта на основе его ObjectId.

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


Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 31-08-2015, 14:46:35
То есть данный перебор объектов происходит по всем объектам чертежа и даже листов?
Да. И не только по ним, но и по всем блокам. Пространство модели - это блок с именем "*Model_Space". Кроме него в чертеже может быть еще куча разных блоков (описаний блоков - BlockTableRecord), которые также будут просмотрены. И это явно не то, что тебе нужно.

P.S.: Я надеюсь, что ты говоришь не о коде, который сам показал, а о коде Boxa.Shu.
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 31-08-2015, 14:47:49
Обалдеть, так это, мне бы потом не помешало бы научиться перебирать объекты внутри блоков тоже )
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 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)
то код будет перебирать примитивы внутри блока.
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 31-08-2015, 14:54:13
Получается, если у меня будут блоки с одинаковыми именами, то перебирать он будет по всем блокам с одинаковыми именами? Правильно понимаю?
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 31-08-2015, 15:04:02
Получается, если у меня будут блоки с одинаковыми именами, то перебирать он будет по всем блокам с одинаковыми именами? Правильно понимаю?
Или я не понял вопроса или ты не понимаешь сути блоков в AutoCAD. Есть "описания блоков" (класс BlockTableRecord) - запись таблицы блоков, которая содержит все примитивы, содержащиеся внутри блока. А есть "вставки блоков" (класс BlockReference) - примитив, ссылающийся на "описание блока". Так вот "описание блока" с одним именем в чертеже может быть только одно, а  "вставок блоков" с одним именем может быть сколько угодно, а может и вообще не быть ни одного. И "вставки блоков" могут быть внутри любых других "описаний блоков". В том числе и внутри Пространства модели - "описания блока" с именем "*Model_Space". В отличие от других "описаний блоков" Пространство модели не может иметь никаких вставок в другие "описания блоков".
Надеюсь, что я смог доступно описать разницу между "вставкой блока" и "описанием блока"
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 31-08-2015, 15:37:00
Я попробую уточнить:
список блоков в чертеже.
(https://adn-cis.org/forum/proxy.php?request=http%3A%2F%2Fs10.postimg.org%2Fe9udwunzp%2Fimage.jpg&hash=8a5a5133e9f1e2ddecf7ab2dadf57798) (http://postimg.org/image/e9udwunzp/)


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

(https://adn-cis.org/forum/proxy.php?request=http%3A%2F%2Fs24.postimg.org%2Ftqoje4hn5%2Fimage.jpg&hash=f79635d49a516eb99ee9fdfa3b59eada) (http://postimg.org/image/tqoje4hn5/)

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"), так как процедура перебора объектов занимает много времени.
Название: Re: Как перебирать только блоки?
Отправлено: Владимир Шу от 31-08-2015, 15:44:59
1. Динамический блок при изменениях меняет свое имя, так что указанным тобой способом ты его не получишь.
2. Пробуй не полный перебор, а выбор с фильтром.
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 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
Но похоже ты не читаешь или не понимаешь что я тебе пишу :(
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 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. Теперь только их и перебираем.

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

Не подумайте, что я проигнорировал Ваше сообщение. Пожалуй Вы единственный, чьи ответы я читаю с предельным вниманием, пытаясь вникнуть. А Вы уж поверьте я честно стараюсь.
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 31-08-2015, 15:59:37
так что быстрее не будет

А давайте попробуем обойти это ограничение.
Название: Re: Как перебирать только блоки?
Отправлено: Владимир Шу от 31-08-2015, 16:00:23
https://sites.google.com/site/bushmansnetlaboratory/translate-manual/sozdanie-i-redaktirovanie-obektov-autocad/rabota-s-vybrannymi-naborami/vybor-obektov-v-certeze
https://sites.google.com/site/bushmansnetlaboratory/translate-manual/sozdanie-i-redaktirovanie-obektov-autocad/rabota-s-vybrannymi-naborami/opredelenie-pravil-dla-filtrov-vybora/ispolzovanie-filtrov-vybora-dla-opredelenia-vybora-na-osnovanii-pravil
Попробуй оба варианта, сравни и выбери нужный.

Оба, в смысле перебор и выбор с фильтром.
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 31-08-2015, 16:03:24
Попробуй оба варианта, сравни и выбери нужный.

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

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

Аллилуйя, то, что и искал!
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 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). И работает это единицы секунд на чертежах размером в десятки мегабайт. Быстрее можно только если все нужные тебе блоки видны на экране. И тогда можно их отфильтровать (но не по имени).
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 31-08-2015, 16:11:15
А давайте попробуем обойти это ограничение.
Ну-ну. Хочу посмотреть как это тебе удастся сделать.
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 31-08-2015, 16:13:29
Это очень быстрая операция. Просто возьми и проверь. Не нужно теоретизировать. Быстрее можно только если все нужные тебе блоки видны на экране. И тогда можно их отфильтровать (но не по имени).

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

Около минуты просто перебираются объекты и спрашивается у них, а вы "AcDbBlockReference"? И я еще даже с ними ничего не делал.
Дело в том, что вывожу в командную строку информацию об объекте. Может это мешает. Но всё становится еще хуже, когда, я использую форму и отображаю процесс выполнения задачи. Поэтому лишнее нужно железно убирать из перебора заранее.
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 31-08-2015, 16:14:37
Ну-ну. Хочу посмотреть как это тебе удастся сделать

Надеюсь, что завтра все получится.
Название: Re: Как перебирать только блоки?
Отправлено: Владимир Шу от 31-08-2015, 16:16:56
Судя по вот этому AcDbBlockReference, хочется задать вопрос, а Вы на .NET пишите?
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 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
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 31-08-2015, 16:23:35
Судя по вот этому AcDbBlockReference, хочется задать вопрос, а Вы на .NET пишите?
Ну точно не на C++ с использованием ObjectARX. :) Это он имя класса получает при помощи COM/ActiveX.
Название: Re: Как перебирать только блоки?
Отправлено: Владимир Шу от 31-08-2015, 16:25:42
Это он имя класса получает при помощи COM/ActiveX.
Так я вот именно про это, что он не методы .net api использует...
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 31-08-2015, 16:35:35
Надеюсь, что завтра все получится.
Я проверил скорость обработки твоего чертежа-примера. Только при помощи команды _ARRAY увеличил количество рамок в сто раз (объектов в чертеже стало около 500000). REMOVEALLPROXY отработала менее чем за секунду. Делай выводы.
Название: Re: Как перебирать только блоки?
Отправлено: Дима_ от 31-08-2015, 16:51:04
но в этом коде я вижу как перебираются все объекты (допустим, что их 25 006 объектов), у меня даже 10324 объекта долго перебираются (и этот чертеж всего 650 килобайт), а что если мне принесут на тест чертеж 13 Мб (я уже боюсь представить, что такой модуль просто где-нибудь встанет)
Долго получать объект и проверять его, а проверить его указатель (ObjectId) - это очень быстрая опреация и не забывайте, что через COM - вы не только получаете объект, но и пересылаете его целиком на каждой операции получения - .Net же работает "изнутри" автокада.
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 01-09-2015, 07:02:48
Я проверил скорость обработки твоего чертежа-примера. Только при помощи команды _ARRAY увеличил количество рамок в сто раз (объектов в чертеже стало около 500000). REMOVEALLPROXY отработала менее чем за секунду. Делай выводы.

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

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

 Спасибо, я пониманию почему теряю время. Главное, что теперь решение есть. Готовое решение выложу в двух вариантах (COM и VB.NET).
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 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

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

Со вторым вариантом придется поупираться, но выложу!
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 01-09-2015, 08:32:57
Dim FT(0) As Short ' Здесь была запарка (в документации здесь стоял Integer)
Документация написана для VBA. А Integer в VBA - это Short в VB.NET (и в C#).
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 01-09-2015, 09:09:29
Документация написана для VBA. А Integer в VBA - это Short в VB.NET (и в C#).

Шаг за шагом и чистый VB.NET освою.
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 01-09-2015, 12:18:14
Весь оффтопик перебросил сюда: http://adn-cis.org/forum/index.php?topic=2956.0
Прошу в дальнейшем придерживаться темы!
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 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

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

Это здесь кажется должно быть.
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 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
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 01-09-2015, 14:23:40
Работает  :)

Тоже быстро! Этот модуль действительно перебирает все объекты? Или у меня глюки?
Название: Re: Как перебирать только блоки?
Отправлено: Владимир Шу от 01-09-2015, 15:27:32
в 26 строке nInserts вне зоны видимости, или я что то опять перепутал.
На всякий случай, операторы += и -= в VB.net вполне себе работают и уже довольно давно(
Извините, вам запрещён просмотр содержимого спойлеров.
)
Извините, вам запрещён просмотр содержимого спойлеров.

Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 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

Все правильно, просто забыл Александру об этом сказать. Главное работает.
Название: Re: Как перебирать только блоки?
Отправлено: Александр Ривилис от 01-09-2015, 15:42:39
в 26 строке nInserts вне зоны видимости, или я что то опять перепутал.
Ничего не перепутал. Это я в FAR'е правил текст и само-собой его не проверял. Ну бывает и на старуху проруха...
Тоже быстро! Этот модуль действительно перебирает все объекты? Или у меня глюки?
Перебирает все, но считает только вставки блоков. А ты думаешь что Editor.SelectAll() с фильтром работает иначе? Нет конечно. Проход по всем и сравнение с фильтром.
Название: Re: Как перебирать только блоки?
Отправлено: Пашин Евгений от 01-09-2015, 15:45:15
Проход по всем и сравнение с фильтром.

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