Реализовать аналог ssget"_X" на NET

Автор Тема: Реализовать аналог ssget"_X" на NET  (Прочитано 6515 раз)

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

Оффлайн Алексей КуликАвтор темы

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
Возникла задача - выбрать все примитивы (к примеру, вхождения блоков) на всех листах и пространстве модели. Учитывая, что в NET я понимаю очень немного, попытался нарисовать такой вот вариант:
Код - C# [Выбрать]
  1. [CommandMethod("get-all-layout")]
  2. public static void GetAllLayoutsBlockReferencesCommand()
  3. {
  4.     Document doc = Application.DocumentManager.MdiActiveDocument;
  5.     Database dbase = doc.Database;
  6.     using (Transaction trans = dbase.TransactionManager.StartTransaction())
  7.     {
  8.         BlockTable bt = trans.GetObject(dbase.BlockTableId, OpenMode.ForRead) as BlockTable;
  9.         List<ObjectId> blockRefList = new List<ObjectId>();
  10.  
  11.         DBDictionary layoutsDict = trans.GetObject(dbase.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
  12.  
  13.         foreach (DBDictionaryEntry layout in layoutsDict)
  14.         {
  15.             using (BlockTableRecord space = trans.GetObject(layout.Value, OpenMode.ForRead) as BlockTableRecord)
  16.                 // space = null!
  17.             {
  18.                 foreach (ObjectId id in space)
  19.                 {
  20.                     if (id.ObjectClass.DxfName == "INSERT")
  21.                     {
  22.                         blockRefList.Add(id);
  23.                     }
  24.                 }
  25.             }
  26.         }
  27.     }
  28. }
Но уже при попытке обработки space я получаю ошибку, приводящую к падению ACAD (space == null). Отпуск совсем мне остатки мозгов привел в невменяемое состояние? Что я делаю не так?
ACAD2021
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Re: Реализовать аналог ssget"_X" на NET
« Ответ #1 : 15-08-2024, 07:52:27 »
открытые через транзакцию объекты не обязательно диспозить и соответственно использовать юзинг. 
в LayoutDictionaryId хранятлся листы Layout. а у листов есть BlockTableRecordId

Оффлайн Алексей КуликАвтор темы

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
Re: Реализовать аналог ssget"_X" на NET
« Ответ #2 : 15-08-2024, 11:19:07 »
открытые через транзакцию объекты не обязательно диспозить и соответственно использовать юзинг. 
в LayoutDictionaryId хранятлся листы Layout. а у листов есть BlockTableRecordId
Это как - в Id чего-то там хранится? Может, имеется в виду как раз DBDictionary? В нем да, записи есть, по которым я и прохожу. Только вот у layout есть только Key (имя листа) и Value, который вроде бы похож на ObjectId.
А, понял, кажись. С 13 строки и далее надо работать примерно так:
Код - C# [Выбрать]
  1. foreach (DBDictionaryEntry layoutEntry in layoutsDict)
  2. {
  3.     Layout ent = trans.GetObject(layoutEntry.Value, OpenMode.ForRead) as Layout;
  4.     using (BlockTableRecord space =
  5.            trans.GetObject(ent.BlockTableRecordId, OpenMode.ForRead) as BlockTableRecord)
  6.  
Верно я понимаю и делаю? Результат-то пока вроде бы корректный, но мало ли чего не учитываю...
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Re: Реализовать аналог ssget"_X" на NET
« Ответ #3 : 15-08-2024, 14:25:48 »
да, нормуль) 
я так понимаю, на лиспе переменные зло. ну и имена переменных туда же)

Оффлайн Алексей КуликАвтор темы

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
Re: Реализовать аналог ssget"_X" на NET
« Ответ #4 : 15-08-2024, 14:51:43 »
да, нормуль) 
Спасибо )
я так понимаю, на лиспе переменные зло. ну и имена переменных туда же)
Почему такой вывод? Я без наездов, если что )
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Re: Реализовать аналог ssget"_X" на NET
« Ответ #5 : 15-08-2024, 15:10:09 »
ent не очень имя для листа 
код ревью)

Оффлайн Алексей КуликАвтор темы

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
Re: Реализовать аналог ssget"_X" на NET
« Ответ #6 : 15-08-2024, 15:20:13 »
Там вообще сначала был var :) Я пытаюсь исправиться, получается пока не очень )))
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Re: Реализовать аналог ssget"_X" на NET
« Ответ #7 : 15-08-2024, 15:31:16 »
было бы интересно посмотреть на c# код в стиле лиспа) наверно F# больше подходит

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Re: Реализовать аналог ssget"_X" на NET
« Ответ #8 : 15-08-2024, 15:46:22 »
Возникла задача - выбрать все примитивы (к примеру, вхождения блоков) на всех листах и пространстве модели.
Делал подобное.

Я бы задумался, правильно ли сформулирована задача?

1. Все примитивы в пространствах. С точки зрения примитивов ок, но блоки вложены в блоки в них еще примитивы. таким образом будут выбраны примитивы верхнего уровня решит ли это задачу "выбрать все примитивы".

2. В примере выбор осуществляется как DxfName == "INSERT" с выбором, не только по DxfName есть нюансы.
Надергал из моей программы
Локализованное имя/NET/ARX/DXF
Вхождение блока   BlockReference   AcDbBlockReference   INSERT
Внешняя ссылка   BlockReference   AcDbBlockReference   INSERT
Параллельный размер   AlignedDimension   AcDbAlignedDimension   DIMENSION
Угловой размер   LineAngularDimension2   AcDb2LineAngularDimension   DIMENSION
МПолигон   ImpEntity   AcDbMPolygon   MPOLYGON
2D-полилиния   Polyline2d   AcDb2dPolyline   POLYLINE
3D-полилиния   Polyline3d   AcDb3dPolyline   POLYLINE
AEC_BDG_SECTIONLINE   ImpCurve   AecDbBdgSectionLine   AEC_BDG_SECTIONLINE
AEC_2D_SECTION   ImpCurve   AecDb2dSection   AEC_2D_SECTION
 

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Re: Реализовать аналог ssget"_X" на NET
« Ответ #9 : 15-08-2024, 16:40:39 »
выбрать все примитивы
Возможно так, если нужны все примитивы в чертеже
Код - C# [Выбрать]
  1. Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  2. Editor ed = doc.Editor;
  3. Database db = HostApplicationServices.WorkingDatabase;
  4.  
  5. using (DocumentLock dl = doc.LockDocument())
  6. {
  7.         using (Transaction tr = db.TransactionManager.StartTransaction())
  8.         {
  9.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);
  10.                 var blocks = bt.Cast<ObjectId>().Select(id => (BlockTableRecord)tr.GetObject(id, OpenMode.ForWrite, false));
  11.                 blocks = blocks.Where(b => (!b.IsDependent && !b.IsResolved));
  12.  
  13.                 foreach (BlockTableRecord block in blocks)
  14.                 {
  15.                         IEnumerable<ObjectId> plineIds1 = block.Cast<ObjectId>().Where(id => !id.IsErased && id.ObjectClass.Name == "AcDbPolyline");
  16.                         IEnumerable<Polyline> plines1 = plineIds1.Select(id => (Polyline)tr.GetObject(id, OpenMode.ForWrite, false, true));
  17.                 }
  18.  
  19.                 tr.Commit();
  20.         }
  21. }

Оффлайн Алексей КуликАвтор темы

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
Re: Реализовать аналог ssget"_X" на NET
« Ответ #10 : 15-08-2024, 16:45:20 »
было бы интересно посмотреть на c# код в стиле лиспа) наверно F# больше подходит
Не знаю, я на F# не работал )
блоки вложены в блоки в них еще примитивы. таким образом будут выбраны примитивы верхнего уровня решит ли это задачу "выбрать все примитивы".
В поставленных условиях именно так и надо было, без учета вложенных.
Возможно так, если нужны все примитивы в чертеже
Спасибо за пример, буду думать ;)
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 546
  • Карма: 119
Re: Реализовать аналог ssget"_X" на NET
« Ответ #11 : 15-08-2024, 16:51:52 »
Но уже при попытке обработки space я получаю ошибку, приводящую к падению ACAD (space == null). Отпуск совсем мне остатки мозгов привел в невменяемое состояние? Что я делаю не так?

Очевидно в LayoutDictionary хранятся Id Layout, а не BlockTableRecord

Код - C# [Выбрать]
  1. var layoutDictionary = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
  2. var layoutEntrys = layoutDictionary.Cast<DictionaryEntry>();
  3. var layoutIds = layoutEntrys.Select(entry => (ObjectId)entry.Value);
  4. var layouts = layoutIds.Select(id => (Layout)tr.GetObject(id, OpenMode.ForRead));
  5. layouts = layouts.Where(l => !l.ModelType); //Отсекаем пространство модели.
  6. foreach (Layout layout in layouts)
  7. {
  8.         string LayoutName = layout.LayoutName;
  9.         ed.WriteMessage($"\nLayoutName:{LayoutName}");
  10.  
  11.         BlockTableRecord layoutBlock = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead);
  12. }

Оффлайн Алексей КуликАвтор темы

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
Re: Реализовать аналог ssget"_X" на NET
« Ответ #12 : 15-08-2024, 16:55:44 »
« Последнее редактирование: 16-08-2024, 17:47:15 от Александр Ривилис »
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!