Параметры динамического блока

Автор Тема: Параметры динамического блока  (Прочитано 9880 раз)

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

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

Оффлайн bargoolАвтор темы

  • ADN Club
  • ***
  • Сообщений: 111
  • Карма: 6
Пока сложно даже сформулировать вопрос, по-этому буду повторяться, наверняка.
Как пример данных, которые мне надо получить: в редакторе блоков есть палитра, называется "Parameter manager", через которую есть доступ ко всем параметрам блока.
Можно ли получить доступ к тем же самым параметрам? Мне нужны имена всех параметров и закреплённые за ними "Expression".
Насколько я понял, ссылки на вычисляемые параметры хранятся в словаре "ACAD_ENCHANCEDBLOCK", прикреплённом к BlockTableRecord блока. Судя по всему, больше всего меня интересуют AcDbBlockUserParameter (это ведь они вычисляются с формулами?)
Ещё раз: как бы получить данные, соответствующие тому что отображается в столбцах Name и Expression вышеобозначенной палитры?
Алексей

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

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

Оффлайн bargoolАвтор темы

  • ADN Club
  • ***
  • Сообщений: 111
  • Карма: 6
Re: Параметры динамического блока
« Ответ #2 : 19-03-2014, 18:03:03 »
Александр, к сожалению, не то. Нужная мне палитра вызывается по другой кнопке (см. вложение), хотя эта статья может дать направление для дальнейшего исследования
Алексей

Отмечено как Решение Александр Ривилис 16-11-2020, 17:03:55

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Параметры динамического блока
« Ответ #3 : 19-03-2014, 20:00:01 »
Имена и значения параметров в конкретной вставка ты можешь получить отсюда:
Код - C# [Выбрать]
  1. [CommandMethod("TestBref")]
  2. public void TestBref()
  3. {
  4.     Document doc = AcadApp.DocumentManager.MdiActiveDocument;
  5.     Editor ed = doc.Editor;
  6.     PromptEntityResult res = ed.GetEntity("\nВыберите вставку блока: ");
  7.     if (res.Status != PromptStatus.OK) return;
  8.     if (!res.ObjectId.ObjectClass.IsDerivedFrom(Entity.GetClass(typeof(BlockReference)))) {
  9.         ed.WriteMessage("\nЭто не блок!"); return;
  10.     }
  11.     using (Transaction tr = doc.TransactionManager.StartTransaction())
  12.     {
  13.         BlockReference br =
  14.                      tr.GetObject(res.ObjectId, OpenMode.ForRead) as BlockReference;
  15.         if (br != null)
  16.         {
  17.             DynamicBlockReferencePropertyCollection col =
  18.                        br.DynamicBlockReferencePropertyCollection;
  19.             foreach (DynamicBlockReferenceProperty dp in col)
  20.             {
  21.                 ed.WriteMessage("\nName= {0} Value = {1}",
  22.                       dp.PropertyName, dp.Value);
  23.             }
  24.         }
  25.         tr.Commit();
  26.     }
  27. }
  28.  
А вот чтобы добраться до формул придется очень попотеть, так как API для этого нет. Особенно непросто это на .NET, так как в нём нет встроенных средств работы с DXF, а тут придется всё делать на них.
Я приведу картинки, а ты уже сам подумай, как это можно использовать:





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

Оффлайн bargoolАвтор темы

  • ADN Club
  • ***
  • Сообщений: 111
  • Карма: 6
Re: Параметры динамического блока
« Ответ #4 : 19-03-2014, 21:39:25 »
Спасибо, Александр,
с конкретной вставкой всё понятно, а вот с формулами..
До третьего скриншота я уже добрался =) а вот за четвёртый - спасибо большое =)
Алексей

Оффлайн bargoolАвтор темы

  • ADN Club
  • ***
  • Сообщений: 111
  • Карма: 6
Re: Параметры динамического блока
« Ответ #5 : 20-03-2014, 17:06:28 »
Докладываю о результатах исследования:
- Для AcDbAssocVariable есть Autodesk.AutoCAD.DatabaseServices.AssocVariable (соответственно, там есть свойства Name и Expression)
- Мне кажется, что я получил ссылки через зад, но для того, что бы получить AssocVariable, которые относятся к конкретному параметру, пришлось воспользоваться доработанным DwgFiler'ом от нашего замечательного Тони (больше ничего на ум не пришло). Прошу совета, как это сделать проще.
Кстати, а где почитать, что такое EvalGraph, и как с ним работать (я вроде и так понимаю, но почему было просто не прочитать записи ExtensionDictionary)?

Я про вот это вот:
Код - C# [Выбрать]
  1. // Открываем словарь ENHANCEDBLOCK
  2. Autodesk.AutoCAD.Internal.DatabaseServices.EvalGraph graph =
  3.         trans.GetObject(extDic.GetAt("ACAD_ENHANCEDBLOCK"),
  4.                         OpenMode.ForRead) as EvalGraph;

Ну и сам код. Сделан на коленке, уж простите
Код - C# [Выбрать]
  1. /// <summary>
  2. /// Получение пользовательских параметров блока. Выводятся имена и вычисляемые выражения
  3. /// Код на основе http://adn-cis.org/chtenie-tabliczyi-svojstv-bloka-dlya-dinamicheskogo-bloka.html
  4. /// </summary>
  5. [CommandMethod("ReadBlockVariables")]
  6. static public void CmdReadBlockVariables()
  7. {
  8.         Editor ed = Application.DocumentManager.
  9.                 MdiActiveDocument.Editor;
  10.        
  11.         // Выбор вставки блока
  12.         PromptEntityOptions peo = new PromptEntityOptions("Выберите вставку динамического блока: ");
  13.         peo.SetRejectMessage("Только вставка блока ");
  14.         peo.AddAllowedClass(typeof(BlockReference), false);
  15.         PromptEntityResult per = ed.GetEntity(peo);
  16.         if (per.Status != PromptStatus.OK)
  17.                 return;
  18.         ObjectId blockRefId = per.ObjectId;
  19.        
  20.         // Получаем базу данных и стартуем транзакцию
  21.         Database db = HostApplicationServices.WorkingDatabase;
  22.         using (Transaction trans = db
  23.                .TransactionManager.StartTransaction())
  24.         {
  25.                 // Открываем вставку блока
  26.                 BlockReference blockRef = trans.GetObject(
  27.                         blockRefId, OpenMode.ForRead) as BlockReference;
  28.                 if (!blockRef.IsDynamicBlock) return;
  29.                
  30.                 // Получаем запись таблицы блоков для динамического блока
  31.                 BlockTableRecord blockDef = trans.GetObject(
  32.                         blockRef.DynamicBlockTableRecord,
  33.                         OpenMode.ForRead) as BlockTableRecord;
  34.                
  35.                 // Открываем её словарь расширения
  36.                 if (blockDef.ExtensionDictionary.IsNull) return;
  37.                 DBDictionary extDic = trans.GetObject(
  38.                         blockDef.ExtensionDictionary, OpenMode.ForRead)
  39.                         as DBDictionary;
  40.                
  41.                 // Открываем словарь ENHANCEDBLOCK
  42.                 Autodesk.AutoCAD.Internal.DatabaseServices.EvalGraph graph =
  43.                         trans.GetObject(extDic.GetAt("ACAD_ENHANCEDBLOCK"),
  44.                                         OpenMode.ForRead) as EvalGraph;
  45.                
  46.                 int[] nodeIds = graph.GetAllNodes();
  47.                 foreach (uint nodeId in nodeIds)
  48.                 {
  49.                         // Открываем узел по его ID
  50.                         DBObject node = graph.GetNode(nodeId,
  51.                                                       OpenMode.ForRead, trans);
  52.                         if (node.ObjectId.ObjectClass.Name.Contains("UserParameter"))
  53.                         {
  54.                                 foreach (ObjectId varId in getAllVariables(db))
  55.                                 {
  56.                                         RefSearchFiler filer = new RefSearchFiler(varId);
  57.                                         filer.Find(node);
  58.                                         if (filer.ReferencingObjectIds.Count > 0)
  59.                                         {
  60.                                                 AssocVariable variable = (AssocVariable)trans.GetObject(varId, OpenMode.ForRead);
  61.                                                 ed.WriteMessage("AssocVariable Name={0} Expression={1}", variable.Name, variable.Expression)
  62.                                         }
  63.                                 }
  64.                         }
  65.                 }
  66.                 trans.Commit();
  67.         }
  68. }
  69.  
  70. static private IEnumerable<Handle> generateHandles(Database db)
  71. {
  72.         for (Int64 i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++)
  73.                 yield return new Handle(i);
  74. }
  75.  
  76. static private IEnumerable<ObjectId> getAllVariables(Database db)
  77. {
  78.         ObjectId result = ObjectId.Null;
  79.         foreach (Handle hnd in generateHandles(db))
  80.         {
  81.                 if (db.TryGetObjectId(hnd, out result) && !result.IsNull && result.IsValid && !result.IsErased && result.ObjectClass.Name == "AcDbAssocVariable")
  82.                         yield return result;
  83.         }
  84. }
И filer =)
Код - C# [Выбрать]
  1. /// <summary>
  2. /// See http://www.theswamp.org/index.php?topic=42034.msg471839#msg471839
  3. /// </summary>
  4. public class RefSearchFiler : Autodesk.AutoCAD.DatabaseServices.DwgFiler
  5. {
  6.         private ObjectId referencedId;
  7.         private DBObject current = null;
  8.        
  9.         private ObjectIdCollection referencingObjectIds = new ObjectIdCollection();
  10.         // Pass the Id of the object to find references to:
  11.        
  12.         public RefSearchFiler( ObjectId referencedId )
  13.         {
  14.                 this.referencedId = referencedId;
  15.         }
  16.        
  17.         // Search the parameter for references to the referencedId:
  18.        
  19.         public void Find( DBObject obj )
  20.         {
  21.                 this.current = obj;
  22.                 try
  23.                 {
  24.                         obj.DwgOut( this );
  25.                 }
  26.                 finally
  27.                 {
  28.                         this.current = null;
  29.                 }
  30.         }
  31.        
  32.         // The ObjectIds of all referencing objects:
  33.        
  34.         public ObjectIdCollection ReferencingObjectIds
  35.         {
  36.                 get
  37.                 {
  38.                         return referencingObjectIds;
  39.                 }
  40.         }
  41.        
  42.         public override void WriteSoftOwnershipId( ObjectId value )
  43.         {
  44.                 OnWriteReference( value );
  45.         }
  46.        
  47.         public override void WriteSoftPointerId( ObjectId value )
  48.         {
  49.                 OnWriteReference( value );
  50.         }
  51.        
  52.         public override void WriteHardOwnershipId( ObjectId value )
  53.         {
  54.                 OnWriteReference( value );
  55.         }
  56.        
  57.         public override void WriteHardPointerId( ObjectId value )
  58.         {
  59.                 OnWriteReference( value );
  60.         }
  61.        
  62.         // In this case, we don't care about whether a reference
  63.         // is hard/soft/owner/pointer, but we could discriminate
  64.         // further if needed.
  65.        
  66.         void OnWriteReference( ObjectId value )
  67.         {
  68.                 if( value == referencedId && this.current != null )
  69.                 {
  70.                         referencingObjectIds.Add( this.current.ObjectId );
  71.                         this.current = null;
  72.                 }
  73.         }
  74.         // ************************************************************
  75.        
  76.         public override void WriteVector3d(Autodesk.AutoCAD.Geometry.Vector3d value)
  77.         {
  78.         }
  79.        
  80.         public override void WriteVector2d(Autodesk.AutoCAD.Geometry.Vector2d value)
  81.         {
  82.         }
  83.        
  84.         public override void WriteUInt64(ulong value)
  85.         {
  86.         }
  87.        
  88.         public override void WriteUInt32(uint value)
  89.         {
  90.         }
  91.        
  92.         public override void WriteUInt16(ushort value)
  93.         {
  94.         }
  95.        
  96.         public override void WriteString(string value)
  97.         {
  98.         }
  99.        
  100.         public override void WriteScale3d(Autodesk.AutoCAD.Geometry.Scale3d value)
  101.         {
  102.         }
  103.        
  104.         public override void WritePoint3d(Autodesk.AutoCAD.Geometry.Point3d value)
  105.         {
  106.         }
  107.        
  108.         public override void WritePoint2d(Autodesk.AutoCAD.Geometry.Point2d value)
  109.         {
  110.         }
  111.        
  112.         public override void WriteInt64(long value)
  113.         {
  114.         }
  115.        
  116.         public override void WriteInt32(int value)
  117.         {
  118.         }
  119.        
  120.         public override void WriteInt16(short value)
  121.         {
  122.         }
  123.        
  124.         public override void WriteHandle(Autodesk.AutoCAD.DatabaseServices.Handle handle)
  125.         {
  126.         }
  127.        
  128.         public override void WriteDouble(double value)
  129.         {
  130.         }
  131.        
  132.         public override void WriteBytes(byte[] value)
  133.         {
  134.         }
  135.        
  136.         public override void WriteByte(byte value)
  137.         {
  138.         }
  139.        
  140.         public override void WriteBoolean(bool value)
  141.         {
  142.         }
  143.        
  144.         public override void WriteBinaryChunk(byte[] chunk)
  145.         {
  146.         }
  147.        
  148.         public override void WriteAddress(IntPtr value)
  149.         {
  150.         }
  151.        
  152.         public override void Seek(long offset, int method)
  153.         {
  154.         }
  155.        
  156.         public override void ResetFilerStatus()
  157.         {
  158.         }
  159.        
  160.         public override Autodesk.AutoCAD.Geometry.Vector3d ReadVector3d()
  161.         {
  162.                 throw new NotImplementedException();
  163.         }
  164.        
  165.         public override Autodesk.AutoCAD.Geometry.Vector2d ReadVector2d()
  166.         {
  167.                 throw new NotImplementedException();
  168.         }
  169.        
  170.         public override ulong ReadUInt64()
  171.         {
  172.                 throw new NotImplementedException();
  173.         }
  174.        
  175.         public override uint ReadUInt32()
  176.         {
  177.                 throw new NotImplementedException();
  178.         }
  179.        
  180.         public override ushort ReadUInt16()
  181.         {
  182.                 throw new NotImplementedException();
  183.         }
  184.        
  185.         public override string ReadString()
  186.         {
  187.                 throw new NotImplementedException();
  188.         }
  189.        
  190.         public override Autodesk.AutoCAD.DatabaseServices.ObjectId ReadSoftPointerId()
  191.         {
  192.                 throw new NotImplementedException();
  193.         }
  194.        
  195.         public override Autodesk.AutoCAD.DatabaseServices.ObjectId ReadSoftOwnershipId()
  196.         {
  197.                 throw new NotImplementedException();
  198.         }
  199.        
  200.         public override Autodesk.AutoCAD.Geometry.Scale3d ReadScale3d()
  201.         {
  202.                 throw new NotImplementedException();
  203.         }
  204.        
  205.         public override Autodesk.AutoCAD.Geometry.Point3d ReadPoint3d()
  206.         {
  207.                 throw new NotImplementedException();
  208.         }
  209.        
  210.         public override Autodesk.AutoCAD.Geometry.Point2d ReadPoint2d()
  211.         {
  212.                 throw new NotImplementedException();
  213.         }
  214.        
  215.         public override long ReadInt64()
  216.         {
  217.                 throw new NotImplementedException();
  218.         }
  219.        
  220.         public override int ReadInt32()
  221.         {
  222.                 throw new NotImplementedException();
  223.         }
  224.        
  225.         public override short ReadInt16()
  226.         {
  227.                 throw new NotImplementedException();
  228.         }
  229.        
  230.         public override Autodesk.AutoCAD.DatabaseServices.ObjectId ReadHardPointerId()
  231.         {
  232.                 throw new NotImplementedException();
  233.         }
  234.        
  235.         public override Autodesk.AutoCAD.DatabaseServices.ObjectId ReadHardOwnershipId()
  236.         {
  237.                 throw new NotImplementedException();
  238.         }
  239.        
  240.         public override Autodesk.AutoCAD.DatabaseServices.Handle ReadHandle()
  241.         {
  242.                 throw new NotImplementedException();
  243.         }
  244.        
  245.         public override double ReadDouble()
  246.         {
  247.                 throw new NotImplementedException();
  248.         }
  249.        
  250.         public override void ReadBytes(byte[] value)
  251.         {
  252.                 throw new NotImplementedException();
  253.         }
  254.        
  255.         public override byte ReadByte()
  256.         {
  257.                 throw new NotImplementedException();
  258.         }
  259.        
  260.         public override bool ReadBoolean()
  261.         {
  262.                 throw new NotImplementedException();
  263.         }
  264.        
  265.         public override byte[] ReadBinaryChunk()
  266.         {
  267.                 throw new NotImplementedException();
  268.         }
  269.        
  270.         public override IntPtr ReadAddress()
  271.         {
  272.                 throw new NotImplementedException();
  273.         }
  274.        
  275.         public override long Position {
  276.                 get {
  277.                         throw new NotImplementedException();
  278.                 }
  279.         }
  280.        
  281.         public override Autodesk.AutoCAD.DatabaseServices.FilerType FilerType {
  282.                 get {
  283.                         return FilerType.BagFiler;
  284.                 }
  285.         }
  286.        
  287.         public override Autodesk.AutoCAD.Runtime.ErrorStatus FilerStatus {
  288.                 get {
  289.                         return new ErrorStatus();
  290.                 }
  291.                 set {
  292.                         throw new NotImplementedException();
  293.                 }
  294.         }
  295. }
Алексей

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Параметры динамического блока
« Ответ #6 : 20-03-2014, 17:15:19 »
Ну честно говоря зачем сканировать весь чертеж мне не очень понятно. Лучше поищи как сделать P/Invoke для acdbEntget().
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн bargoolАвтор темы

  • ADN Club
  • ***
  • Сообщений: 111
  • Карма: 6
Re: Параметры динамического блока
« Ответ #7 : 20-03-2014, 17:20:33 »
Ну честно говоря зачем сканировать весь чертеж мне не очень понятно. Лучше поищи как сделать P/Invoke для acdbEntget().
Это вот это? http://www.caduser.ru/forum/index.php?PAGE_NAME=message&FID=49&TID=44327&MID=248040#message248040
Алексей

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Параметры динамического блока
« Ответ #8 : 20-03-2014, 17:24:30 »
Да. Только посмотри там под какие версии AutoCAD. Возможно имя dll нужно поменять, возможно сигнатуру имени функции. По хорошему нужно сделать более-менее универсальную обертку, которая бы не зависела от разрядности и версии AutoCAD.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение