Создание поля ссылающегося на динамический параметр динамического блока

Автор Тема: Создание поля ссылающегося на динамический параметр динамического блока  (Прочитано 18427 раз)

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

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

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 629
  • Карма: 161
    • ПГСу Бложик
Вот код:
Код - C# [Выбрать]
  1.         [Rtm.CommandMethod("FieldDynProp", "fdp", Rtm.CommandFlags.Redraw | Rtm.CommandFlags.Modal)]
  2.         public static void SetFieldByDynProp()
  3.         {
  4.             App.Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  5.             Db.Database db = doc.Database;
  6.             Ed.Editor ed = doc.Editor;
  7.  
  8.             Ed.PromptEntityOptions peo = new Ed.PromptEntityOptions("\nУкажите экземпляр блока:");
  9.             peo.AllowNone = false;
  10.             peo.AllowObjectOnLockedLayer = true;
  11.             peo.SetRejectMessage("\nВыбран неправильный объект!");
  12.             peo.AddAllowedClass(typeof(Db.BlockReference), true);
  13.  
  14.             Ed.PromptEntityResult per = ed.GetEntity(peo);
  15.  
  16.             if (per.Status != Ed.PromptStatus.OK)
  17.                 return;
  18.  
  19.             using (Db.Transaction tr = db.TransactionManager.StartTransaction())
  20.             {
  21.                 Db.BlockReference acBlock = (Db.BlockReference)tr.GetObject(per.ObjectId, Db.OpenMode.ForRead);
  22.                 if (acBlock.IsDynamicBlock)
  23.                 {
  24.                     //Получение дин св-в по имени
  25.                     Db.DynamicBlockReferenceProperty blockReferenceProperty = (
  26.                         (from Db.DynamicBlockReferenceProperty blockRefProperty in acBlock.DynamicBlockReferencePropertyCollection
  27.                         where blockRefProperty.PropertyName.Equals("ДЛИНА", StringComparison.OrdinalIgnoreCase)
  28.                         select blockRefProperty).FirstOrDefault()) as Db.DynamicBlockReferenceProperty;
  29.                    
  30.                     Db.Field fieldobj = new Db.Field();
  31.                     fieldobj.EvaluationOption = Db.FieldEvaluationOptions.Automatic;
  32.                     //Формирование кода поля
  33.                     string fieldCode = "%<\\AcObjProp Object(%<\\_ObjId " + per.ObjectId.OldId.ToString() + ">%).Parameter(1).UpdatedDistance \\f \"%lu2%pr0\">%";
  34.                     fieldobj.SetFieldCode(fieldCode);
  35.                     Db.MText mtextobj = new Db.MText();
  36.                     mtextobj.SetDatabaseDefaults();
  37.                     mtextobj.SetField("Text", fieldobj);
  38.                     fieldobj.Evaluate(0, db);
  39.                     mtextobj.Location = per.PickedPoint;
  40.                     Db.BlockTableRecord btr = (Db.BlockTableRecord)tr.GetObject(db.CurrentSpaceId, Db.OpenMode.ForWrite);
  41.                     btr.AppendEntity(mtextobj);
  42.                     tr.AddNewlyCreatedDBObject(mtextobj, true);
  43.                     tr.Commit();                              
  44.                }
  45.             }
  46.         }
  47.  
Непонятка в строке 33, в ней указывается номер параметра, в данном примере 1.
Собственно я не понял, как получить этот номер для вставки в поле.
Попробовал посмотреть порядковый номер в DynamicBlockReferencePropertyCollection, не подходит (в одном из блоков  порядковый номер в коллекции был 4, а номер параметра 80). Методов для получения этого номера по имеющемуся  DynamicBlockReferenceProperty так же не нашел.

Собственно вопрос, как получить номер параметра?

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

  • Administrator
  • *****
  • Сообщений: 13923
  • Карма: 1793
  • Рыцарь ObjectARX
  • Skype: rivilis
На 100% не уверен, но очень похоже:


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

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

  • Administrator
  • *****
  • Сообщений: 13923
  • Карма: 1793
  • Рыцарь ObjectARX
  • Skype: rivilis
Похоже там всё несколько сложнее. Задал вопрос в ADN DevHelp.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 629
  • Карма: 161
    • ПГСу Бложик
Вот, искал искал...
Похожую тему нашел (ссылка), но все равно не получается этот номер получить.
До BlockParameter дохожу и все =о(
Извините, вам запрещён просмотр содержимого спойлеров.

Извините, вам запрещён просмотр содержимого спойлеров.

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

  • Administrator
  • *****
  • Сообщений: 13923
  • Карма: 1793
  • Рыцарь ObjectARX
  • Skype: rivilis
Нашёл на просторах интернета:
Код - Auto/Visual Lisp [Выбрать]
  1. ;;;
  2. ;;; Функция получения списка для динамического блока в виде:
  3. ;;;          (ParameterName . ParameterNumber).
  4. ;;;
  5. (defun GetParameterNumber (blkName     /           EntData
  6.                            BlkRecData  DictData    tempData
  7.                            DataList    ParamData
  8.                           )
  9.   (setq EntData (entget (tblobjname "block" blkName)))
  10.   (setq BlkRecData (entget (cdr (assoc 330 EntData))))
  11.   (setq DictData (dictsearch
  12.                    (cdr (assoc 360 BlkRecData))
  13.                    "ACAD_ENHANCEDBLOCK"
  14.                  )
  15.   )
  16.   (while (setq tempData (car DictData))
  17.     (if
  18.       (and
  19.         (equal (car tempData) 95)      
  20.         (equal (caadr DictData) 360)
  21.         (wcmatch
  22.           (strcase
  23.             (cdr (assoc 0 (setq ParamData (entget (cdadr DictData)))))
  24.           )                    
  25.           "*PARAMETER"         
  26.         ) ;_ end of wcmatch
  27.       ) ;_ end of and
  28.        (progn
  29.          (setq DataList (cons  
  30.                           (cons (cdr (assoc 300 ParamData)); Parameter Name
  31.                                 (cdr tempData) ;Parameter Number
  32.                           ) ;_ end of cons
  33.                           DataList
  34.                         ) ;_ end of cons
  35.          ) ;_ end of setq
  36.          (setq DictData (cddr DictData))
  37.        ) ;_ end of progn
  38.        (setq DictData (cdr DictData))
  39.     ) ;_ end of if
  40.   ) ;_ end of while
  41.   (reverse DataList)
  42. ) ;_ end of defun

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

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 629
  • Карма: 161
    • ПГСу Бложик
Я в лиспе совсем нуб, очень нужны пояснения для того, что бы смог переписать на C#/
Буду очень признателен.

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

  • Administrator
  • *****
  • Сообщений: 13923
  • Карма: 1793
  • Рыцарь ObjectARX
  • Skype: rivilis
Ты пока проверь на своих блоках. Для этой цели сохрани код в файл C:\test.lsp
При помощи _APPLOAD загружаешь этот файл и в командной строке AutoCAD:
Код - Auto/Visual Lisp [Выбрать]
  1. (GetParameterNumber "имя твоего блока")
Если сработает, то я вечером распишу что и как. В чистом виде с lisp на C# переписать будет не очень просто, т.к. в C# нет аналога (entget) (т.е. acedEntGet нужно вызывать через P/Invoke).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13923
  • Карма: 1793
  • Рыцарь ObjectARX
  • Skype: rivilis
И еще. Глянь чему у тебя равен nodeId.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 629
  • Карма: 161
    • ПГСу Бложик
Извините, вам запрещён просмотр содержимого спойлеров.

Извините, вам запрещён просмотр содержимого спойлеров.

Осталось соотнести Autodesk.AutoCAD.Internal.DatabaseServices.BlockParameter.Name (Linear) и DynamicBlockReferenceProperty.PropertyName (ДЛИНА) и все получится.


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

  • Administrator
  • *****
  • Сообщений: 13923
  • Карма: 1793
  • Рыцарь ObjectARX
  • Skype: rivilis
Осталось соотнести Autodesk.AutoCAD.Internal.DatabaseServices.BlockParameter.Name (Linear) и DynamicBlockReferenceProperty.PropertyName (ДЛИНА) и все получится.
А они по порядку не совпадают?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 629
  • Карма: 161
    • ПГСу Бложик
А они по порядку не совпадают?
нет, нод порядка 60 штук, а динамических свойств 24

Вроде бы есть еще один путь (во вложении), только я не понял пока как его реализовать..


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

  • Administrator
  • *****
  • Сообщений: 13923
  • Карма: 1793
  • Рыцарь ObjectARX
  • Skype: rivilis
Если не разберёшься - вечером сделаю.
Есть еще один вариант - через DXF:



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

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 629
  • Карма: 161
    • ПГСу Бложик
Разобрался и написал.
Вот лог работы:
Извините, вам запрещён просмотр содержимого спойлеров.

Вот основной код:
Код - C# [Выбрать]
  1. // Открываем узел по его ID
  2.  Db.DBObject node = graph.GetNode(nodeId,Db.OpenMode.ForRead, tr);
  3.  
  4. Autodesk.AutoCAD.Internal.DatabaseServices.BlockParameter variable =
  5. tr.GetObject(node.ObjectId, Db.OpenMode.ForRead) as Autodesk.AutoCAD.Internal.DatabaseServices.BlockParameter;
  6.  
  7. Autodesk.AutoCAD.Internal.DatabaseServices.BlockParameterPropertyDescriptorCollection nodeProp =
  8. variable.PropertyDescription.SyncRoot as Autodesk.AutoCAD.Internal.DatabaseServices.BlockParameterPropertyDescriptorCollection;
  9.                                    
  10. if (variable != null)
  11. {
  12.    ed.WriteMessage("\nПараметр {0} - Имя{1} - Номер{2}",
  13.     variable.Name, nodeProp[0].PropertyName, nodeId.ToString());
  14. }
  15.  


PS/
Наткнулся на просторы интернета =о)
http://forums.augi.com/showthread.php?117056-Create-Field-to-DB-Param-Pragramatically но уже не понадобилось.

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

  • Administrator
  • *****
  • Сообщений: 13923
  • Карма: 1793
  • Рыцарь ObjectARX
  • Skype: rivilis
Наткнулся на просторы интернета =о)
Это как раз оттуда немного переделанный lisp я и выложил.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Владимир Шу 24-09-2015, 16:59:57

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 629
  • Карма: 161
    • ПГСу Бложик
Вот решение:
Извините, вам запрещён просмотр содержимого спойлеров.
Код - C# [Выбрать]
  1.         [Rtm.CommandMethod("FieldDynProp", "fdp", Rtm.CommandFlags.Redraw | Rtm.CommandFlags.Modal)]
  2.         public static void SetFieldByDynProp()
  3.         {
  4.             App.Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  5.             Db.Database db = doc.Database;
  6.             Ed.Editor ed = doc.Editor;
  7.  
  8.             Ed.PromptEntityOptions peo = new Ed.PromptEntityOptions("\nУкажите экземпляр блока:");
  9.             peo.AllowNone = false;
  10.             peo.AllowObjectOnLockedLayer = true;
  11.             peo.SetRejectMessage("\nВыбран неправильный объект!");
  12.             peo.AddAllowedClass(typeof(Db.BlockReference), true);
  13.  
  14.             Ed.PromptEntityResult per = ed.GetEntity(peo);
  15.  
  16.             if (per.Status != Ed.PromptStatus.OK)
  17.                 return;
  18.  
  19.             using (Db.Transaction tr = db.TransactionManager.StartTransaction())
  20.             {
  21.                 Db.BlockReference acBlock = (Db.BlockReference)tr.GetObject(per.ObjectId, Db.OpenMode.ForRead);
  22.                 if (acBlock.IsDynamicBlock)
  23.                 {
  24.                     // Получаем запись таблицы блоков для динамического блока
  25.                     Db.BlockTableRecord blockDef = tr.GetObject(
  26.                             acBlock.DynamicBlockTableRecord,
  27.                             Db.OpenMode.ForRead) as Db.BlockTableRecord;
  28.  
  29.                     String NameTab = "ACAD_ENHANCEDBLOCK";
  30.                     using (Db.DBDictionary dict = (Db.DBDictionary)blockDef.ExtensionDictionary.GetObject(Db.OpenMode.ForRead))
  31.                     {
  32.                         if (dict.Contains(NameTab))
  33.                         {
  34.                             Db.ObjectId NameTabId = dict.GetAt(NameTab);
  35.                              
  36.                             Autodesk.AutoCAD.Internal.DatabaseServices.EvalGraph graph =
  37.                                     tr.GetObject(NameTabId,
  38.                             Db.OpenMode.ForRead) as Autodesk.AutoCAD.Internal.DatabaseServices.EvalGraph;
  39.  
  40.                             int[] nodeIds = graph.GetAllNodes();
  41.                             foreach (uint nodeId in nodeIds)
  42.                             {
  43.                                 // Открываем узел по его ID
  44.                                 Db.DBObject node = graph.GetNode(nodeId,
  45.                                                               Db.OpenMode.ForRead, tr);
  46.                                
  47.  
  48.                                 if (node.ObjectId.ObjectClass.Name.Contains("Parameter"))
  49.                                 {
  50.  
  51.                                     Autodesk.AutoCAD.Internal.DatabaseServices.BlockParameter variable =
  52.                                         tr.GetObject(node.ObjectId, Db.OpenMode.ForRead)
  53.                                         as Autodesk.AutoCAD.Internal.DatabaseServices.BlockParameter;
  54.  
  55.                                     Autodesk.AutoCAD.Internal.DatabaseServices.BlockParameterPropertyDescriptorCollection nodeProp =
  56.                                         variable.PropertyDescription.SyncRoot as Autodesk.AutoCAD.Internal.DatabaseServices.BlockParameterPropertyDescriptorCollection;
  57.                                    
  58.                                     if (variable != null)
  59.                                     {
  60.                                         ////Получение дин св-в по имени
  61.                                       Db.DynamicBlockReferenceProperty blockReferenceProperty = (
  62.                                      (from Db.DynamicBlockReferenceProperty blockRefProperty in acBlock.DynamicBlockReferencePropertyCollection
  63.                                       where blockRefProperty.PropertyName.Equals(nodeProp[0].PropertyName, StringComparison.OrdinalIgnoreCase)
  64.                                       select blockRefProperty).FirstOrDefault()) as Db.DynamicBlockReferenceProperty;            
  65.                                        
  66.                                         ed.WriteMessage("\nПараметр {0} - Имя {1} - Номер {2} - Значение {3}",
  67.                                             variable.Name, nodeProp[0].PropertyName, nodeId.ToString(), blockReferenceProperty.Value.ToString());
  68.                                     }
  69.                                 }
  70.                             }
  71.                         }
  72.                     }
  73.                     tr.Commit();                              
  74.                }
  75.             }
  76.         }
  77.