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

ADN Club => AutoCAD .NET API => Тема начата: Алексей (IdeaSoft) от 15-11-2017, 17:31:12

Название: Выбор набора примитивов по Entity
Отправлено: Алексей (IdeaSoft) от 15-11-2017, 17:31:12
К примеру есть объект Entity

Мне нужно через класс SelectionSet выбрать подобные объекты
1) По слою. (Тут все мне понятно просто передать Entity.Layer)
2) По классу примитива. (А как быть с типом примитива?)

Как из объекта Entity взять информацию что это к примеру "LWPOLYLINE"?
Чтобы передать в фильтр объекта SelectionSet
 

Название: Re: Выбор набора примитивов по Entity
Отправлено: Александр Пекшев aka Modis от 15-11-2017, 17:32:29
object.GetType().Name

Хотя, это не будет Dxf-имя...

В общем - подходов много на самом деле
Название: Re: Выбор набора примитивов по Entity
Отправлено: Александр Пекшев aka Modis от 15-11-2017, 17:40:28
А можно не использовать фильтр вообще, а просто перебрать все объекты в базе и взять те, которые подходят по условию. И могу сказать сразу - это быстро работает (если конечно не косячно сделать)
И говорю я так потому-что уже сто лет назад реализовал такую функцию (https://modplus.org/ru/help/mpselsim). Надо видео сделать

В таком случае проверять то, что это нужный объект можно так
Код - C# [Выбрать]
  1. if(ent is Polyline polyline)
  2. {
  3. //....
  4. }
Или так
Код - C# [Выбрать]
  1. if(baseEnt.GetType().Equals(ent.GetType())
  2. {
  3. //....
  4. }
Ну и еще можно придумать варианты =)
Название: Re: Выбор набора примитивов по Entity
Отправлено: Алексей (IdeaSoft) от 15-11-2017, 17:47:14
А можно не использовать фильтр вообще, а просто перебрать все объекты в базе
А перебрать не медленнее будет чем SelectionSet?
Название: Re: Выбор набора примитивов по Entity
Отправлено: Александр Ривилис от 15-11-2017, 17:47:31
object.GetType().Name

Хотя, это не будет Dxf-имя...
Как-то так без проверки:
Код - C# [Выбрать]
  1. RXClass.GetClass(ent.GetType()).DxfName;
Название: Re: Выбор набора примитивов по Entity
Отправлено: Александр Ривилис от 15-11-2017, 17:47:54
А перебрать не медленнее будет чем SelectionSet?
Будет намного быстрее.
Название: Re: Выбор набора примитивов по Entity
Отправлено: RevitTormentor от 16-11-2017, 21:04:14
А можно не использовать фильтр вообще, а просто перебрать все объекты в базе и взять те, которые подходят по условию. И могу сказать сразу - это быстро работает (если конечно не косячно сделать)

Есть код, как сделать это не "косячно"?
И ещё путаница небольшая есть. Чем отличается Entity от DBObject? DBObject это любой объект в базе? И пока что непонятно какой объект, а как только делаем as Entity то автокад стал понимать что перед ним например либо полилиния либо круг либо размер?
Название: Re: Выбор набора примитивов по Entity
Отправлено: Александр Ривилис от 16-11-2017, 22:48:19
Есть код, как сделать это не "косячно"?
А что такое "косячно"?
Чем отличается Entity от DBObject? DBObject это любой объект в базе?
Да. Например слой (LayerTableRecord) или блок (BlockTableRecord) или полилиния (Polyline), но только последний из них еще и примитив (Entity)
Название: Re: Выбор набора примитивов по Entity
Отправлено: RevitTormentor от 17-11-2017, 06:49:23
А что такое "косячно"?
Не знаю. Александр написал, лишь бы сделать некосячно. Может нюансы есть.


Название: Re: Выбор набора примитивов по Entity
Отправлено: Владимир Шу от 17-11-2017, 07:35:33
Чем отличается Entity от DBObject?
Я предполагаю, что Вы знакомы с основными принципами ООП и думаю для полной ясности кто и что, достаточно будет посмотреть диаграмму классов в файле ...\ObjectARX_20ХХ\classmap\classmap.dwg , раздел ObjectARX  20XX Managed Class Hierarchy
Название: Re: Выбор набора примитивов по Entity
Отправлено: RevitTormentor от 18-11-2017, 07:42:28
Чем отличается Entity от DBObject?
Я предполагаю, что Вы знакомы с основными принципами ООП и думаю для полной ясности кто и что, достаточно будет посмотреть диаграмму классов в файле ...\ObjectARX_20ХХ\classmap\classmap.dwg , раздел ObjectARX  20XX Managed Class Hierarchy
:) Не очень знаком. Но данная диаграммка полезная штука кое что прояснилось. Спасибо.

Т.е. у объекта не может быть слоя например. И так, как в коде ниже можно найти только объекты, потом из них сделать Entity и дальше отсеивать по слоям и XData?
Код - C# [Выбрать]
  1.          foreach (ObjectId id in btr)
  2.                 {
  3.                     if (id.ObjectClass.DxfName == "CIRCLE" && id... == "NameLayer")
  4.                     {
  5.                         ids.Add(id);
  6.                     }
  7.                 }
  8.  
Название: Re: Выбор набора примитивов по Entity
Отправлено: Александр Ривилис от 18-11-2017, 09:41:14
И так, как в коде ниже можно найти только объекты, потом из них сделать Entity и дальше отсеивать по слоям и XData?
Ниже не код, а обрывок кода. Каким образом кто-то может узнать что такое btr и как ты его получил?
По типу примитива можно отобрать не открывая объект, а только зная его ObjectId. А вот чтобы проверить его слой или анализировать Xdata его придётся открыть (с транзакцией или без - не столь существенно).
Название: Re: Выбор набора примитивов по Entity
Отправлено: RevitTormentor от 18-11-2017, 11:18:40
Прошу прощения.
Код - C# [Выбрать]
  1.             ObjectIdCollection ids = new ObjectIdCollection();
  2.             Database db = HostApplicationServices.WorkingDatabase;
  3.             using (Transaction tr = db.TransactionManager.StartTransaction())
  4.             {
  5.                 BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  6.                 BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
  7.                 foreach (ObjectId id in btr)
  8.                 {
  9.                     if (id.ObjectClass.DxfName == "CIRCLE")
  10.                     {
  11.                         ids.Add(id);
  12.                     }
  13.                 }
  14.                 tr.Commit();
  15.             }
  16.             return ids;
  17.  
Название: Re: Выбор набора примитивов по Entity
Отправлено: Александр Ривилис от 18-11-2017, 11:38:18
Это тоже огрызок, хотя и подлиннее. А вот это законченная функция:
Код - C# [Выбрать]
  1. /// <summary>
  2. /// Функция отбирает все окружности на заданном слое, имеющие расширенные данные заданного приложения
  3. /// </summary>
  4. /// <param name="layerName">Имя слоя</param>
  5. /// <param name="appname">Имя приложения</param>
  6. /// <returns></returns>
  7. static ObjectIdCollection GetAllCirclesOnLayerAndApplication(string layerName, string appname)
  8. {
  9.   ObjectIdCollection ids = new ObjectIdCollection();
  10.   Database db = HostApplicationServices.WorkingDatabase;
  11.   using (Transaction tr = db.TransactionManager.StartTransaction())
  12.   {
  13.     BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  14.     BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
  15.     foreach (ObjectId id in btr)
  16.     {
  17.       if (id.ObjectClass.Name == RXClass.GetClass(typeof(Circle)).Name)
  18.       {
  19.         Circle circle = tr.GetObject(id, OpenMode.ForRead) as Circle;
  20.         if (circle.Layer.ToUpper() == layerName.ToUpper())
  21.         using (ResultBuffer rb = circle.GetXDataForApplication(appname))
  22.         {
  23.             if (rb != null) ids.Add(id);
  24.         }
  25.       }
  26.     }
  27.     tr.Commit();
  28.   }
  29.   return ids;
  30. }
Название: Re: Выбор набора примитивов по Entity
Отправлено: RevitTormentor от 18-11-2017, 12:27:41
Александр можете объяснить по этому фрагменту
Код - C# [Выбрать]
  1. ...
  2.     BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  3.     BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
  4.     foreach (ObjectId id in btr)
  5.     {
  6.       if (id.ObjectClass.Name == RXClass.GetClass(typeof(Circle)).Name)
  7.       {
  8.         Circle circle = tr.GetObject(id, OpenMode.ForRead) as Circle;
  9. ...
  10. }

Код - C# [Выбрать]
  1. ObjectId id in btr
здесь id - это объект
А
Код - C# [Выбрать]
  1.  Circle circle = tr.GetObject(id, OpenMode.ForRead) as Circle;
здесь опять GetObject опять какой то объект получаем. Получается circle это ещё один какой то объект или это уже Entity. Или Entity он станет, когда написать circle as Entity.

И вообще проходясь циклом по BlockTableRecord
Код - C# [Выбрать]
  1. foreach (ObjectId id in btr)
вроде как находим объект circle внутри BlockTableRecord
а объект получаем почему то из транзакции
Код - C# [Выбрать]
  1. Circle circle = tr.GetObject(id,
В BlockTableRecord не хранятся сами объекты? Там только ссылки какие то?
Название: Re: Выбор набора примитивов по Entity
Отправлено: Владимир Шу от 18-11-2017, 12:29:49
ObjectId - ссылка на объект
Код - C# [Выбрать]
  1. Circle circle = tr.GetObject(id, OpenMode.ForRead) as Circle;
Получение объекта по ссылке
Название: Re: Выбор набора примитивов по Entity
Отправлено: D_TRex от 09-05-2022, 17:33:38
Здравствуйте, а можно пример на VB NET. Я знаю objectID а вот мне с этим делать не знаю? Надо выбрать примитив (блок) считать его имя, координаты и атрибут.
Название: Re: Выбор набора примитивов по Entity
Отправлено: Александр Ривилис от 09-05-2022, 18:18:45
Здравствуйте, а можно пример на VB NET. Я знаю objectID а вот мне с этим делать не знаю? Надо выбрать примитив (блок) считать его имя, координаты и атрибут.
Здесь все коды приведены из расчета использования AutoCAD .NET API, а не COM/ActiveX
Тебе нужно искать примеры на VBA и переводить их на VB.NET если собираешься и в дальнейшем использовать COM/ActiveX с AutoCAD. Так как этим практически никто не занимается, то тебе придется это делать самостоятельно.
Название: Re: Выбор набора примитивов по Entity
Отправлено: D_TRex от 09-05-2022, 19:15:46
Не давно начал  разбираться и пока не понимаю в чём разница то есть где писать код, но спасибо за ответ.
Название: Re: Выбор набора примитивов по Entity
Отправлено: Александр Ривилис от 09-05-2022, 19:26:47
Не давно начал  разбираться и пока не понимаю в чём разница то есть где писать код, но спасибо за ответ.
Разница в том, что использовать AutoCAD .NET API можно только в dll-сборке, которая загружается внутрь AutoCAD (команда _NETLOAD). И возможностей в AutoCAD .NET API на порядок больше, чем в COM/ActiveX (которое можно использовать вне AutoCAD и которое или запускает AutoCAD или подключается к уже запущенному). Заодно сразу рекомендую изучать C# вместо VB.NET - даже по этому форуму видно, что из 10 программистов 9 использует C# и только одни VB.NET. И соответственно примеров на C# в 10 раз больше.
Название: Re: Выбор набора примитивов по Entity
Отправлено: D_TRex от 10-05-2022, 09:30:31
Я не профессиональный программист, я инженер ВК и попросту раньше баловался макросами. Вообще раньше автокад очень не любил различные надстройки - фатальной ошибкой часто завершалась работа и поэтому я не сторонник надстроек. Всю бьюсь над разбивкой листов программно и для этого мне нужны били свойства блоков и саму структуру я плохо понимаю автокада, но нашёл материалы от самого авкада и по ним всё получилось (только сбор данных создание листов и настройка ещё впереди)
Код - vb.net [Выбрать]
  1.         Dim msObj As AcadObject ' переменная для перебора примитивов модели
  2.         Dim CadBlock As AcadBlockReference ' переменная для получения информации по блокам
  3.  
  4.         For i = 0 To CadDoc.ModelSpace.Count - 1 'для всех объектов в простр. модели
  5.             msObj = CadDoc.ModelSpace.Item(i)
  6.             If (msObj.ObjectName = "AcDbBlockReference") Then ' проверяю что за примитив
  7.                 CadBlock = msObj ' и присваиваю его другой переменной, на прямую не получилось, тут же в принципе можно сортировать по имени и по слою
  8.                 grdPrint.Rows.Add()
  9.                 grdPrint.Rows(grdPrint.RowCount - 2).HeaderCell.Value = Str(grdPrint.RowCount - 1) ' просто счётчик
  10.                 grdPrint.Rows(grdPrint.RowCount - 2).Cells(0).Value = CadBlock.EffectiveName ' имя которое я дал блоку, а не то что сгенерировал автокад
  11.                 grdPrint.Rows(grdPrint.RowCount - 2).Cells(1).Value = "X_S=" & CadBlock.XScaleFactor & ", Y_S =" & CadBlock.YScaleFactor & ", Z_S =" & CadBlock.ZScaleFactor ' масштабы по осям
  12.                 grdPrint.Rows(grdPrint.RowCount - 2).Cells(2).Value = "X=" & CadBlock.InsertionPoint(0) & ", Y =" & CadBlock.InsertionPoint(1) & ", Z =" & CadBlock.InsertionPoint(2) ' точка вставки
  13.                 ' получаю атрибуты
  14.                 X = LBound(CadBlock.GetAttributes) ' значения доступных атрибутов
  15.                 Do Until X = UBound(CadBlock.GetAttributes) + 1
  16.                     grdPrint.Rows(grdPrint.RowCount - 2).Cells(3).Value = grdPrint.Rows(grdPrint.RowCount - 2).Cells(3).Value & CadBlock.GetAttributes(X).TagString & ", " & CadBlock.GetAttributes(X).TextString & ";"
  17.                     X = X + 1
  18.                 Loop
  19.             End If
  20.         Next

А читал тему тут про перебор всех примитивов в чертеже - но у меня не заработало (теперь знаю по чему). Перевожу данные из одного типа в другой просто знаком равенства. В общем код далёк от образца, но он работает правда иногда выскакивает исключение типа
(https://i.postimg.cc/nM93fjjk/2022-05-10-122850722.png) (https://postimg.cc/nM93fjjk)
тоже видел несколько Ваших постов, но пока не пойму как реализовать.

В общем я искал как обратиться по ObjectID а оказалось надо сразу менять тип переменной и считывать свойства.
Название: Re: Выбор набора примитивов по Entity
Отправлено: Алексей Кулик от 10-05-2022, 12:41:16
А это точно VB.NET, а не VBA?
Название: Re: Выбор набора примитивов по Entity
Отправлено: Александр Ривилис от 10-05-2022, 13:23:17
но он работает правда иногда выскакивает исключение типа
Стандартное исключение, которое возникает при работе через COM/ActiveX.
Название: Re: Выбор набора примитивов по Entity
Отправлено: D_TRex от 10-05-2022, 14:15:40
Алексей Кулик, Visual Studio 2017 да поэтому и начал и продолжаю VB.NET так как в те далёкие года макросы были более распространены

Примеры оказывается лежат вот тут "Program Files\Common Files\Autodesk Shared" и вот по ним я более или менее стал понимать структуру обращения и именование примитивов, ну как стал понимать )) просто получилось извлечь данные.

DLL наверное хорошая вещь, я вот смотрю и понимаю что Civil наверное на нём построен, но надо отделать графику от расчётов, он в какой то момент начинает ужасно тормозить при любых манипуляциях. Это уже не по теме. Спасибо за помощь с клонированием листа Александр я видел Ваш ответ, но пока не пробовал.
Название: Re: Выбор набора примитивов по Entity
Отправлено: Алексей Кулик от 11-05-2022, 11:56:05
http://docs.autodesk.com/ACD/2011/ENU/filesMDG/WS1a9193826455f5ff-3859b43c1209703a838778b.htm не поможет в качестве примера?
Название: Re: Выбор набора примитивов по Entity
Отправлено: D_TRex от 14-06-2022, 18:46:14
Алексей Кулик, помогло, спасибо, пока пробую и извлекаю полезное