Связь между объектами чертежа. Есть ли какие-нибудь инструменты?

Автор Тема: Связь между объектами чертежа. Есть ли какие-нибудь инструменты?  (Прочитано 63422 раз)

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

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

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

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Эх... Смешно до слез! Сколько времени я потратил на разработку этого инструмента! Сколько багов отловили пользователи! Сколько нервов это стоило и мне и им! А оказалось, что это просто велосипед. И все уже давно сделано и работает как надо.
Принцип прост: берем Id объекта и добавляем его в запись словаря другого объекта под кодом HardPointerId или SoftPointerId. И всё, больше ничего делать не надо! Все остальное берут на себя внутренние механизмы AutoCAD! Никаких обработчиков событий, актуализаторов и прочей головной боли! :-\

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Все остальное берут на себя внутренние механизмы AutoCAD! Никаких обработчиков событий, актуализаторов и прочей головной боли! :-\
К сожалению это работает не во всех сценариях даже для Custom Object/Entity.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Тестирую. Пока что никаких проблем не обнаружил. Закрывал-открывал чертеж, копировал объекты через буфер и командами, чистил, экспортировал из Civil в AutoCAD... Подскажете, что надо сделать, чтобы вызвать сбой?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Подскажете, что надо сделать, чтобы вызвать сбой?
Возможно в твоём сценарии использования связи между объектами чертежа на такой сбой никогда не попадёшь. У меня были проблемы с редактированием ручек Custom Entity, когда необходимо было обработать связанные примитивы.

P.S.: Кстати, это у тебя связи между примитивами (наследниками Entity) или между объектами (наследниками DBObject)? Если примитивами, то какая реакция на обычное копирование (команда _COPY) должна с ними быть?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Связь между примитивами.
Реакция на обычное копирование сейчас реализована таким образом, что если копируются оба объекта, то между их копиями создается новая связь. Если копируется только один объект из пары - то никакой реакции.
Во внутреннем механизме AutoCAD это реализовано немного иначе. Если объекты копируются парами - то так же как у меня, а вот если один объект из пары - то у копии появляется связь к связанному объекту оригинала.
Можете сами попробовать:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;
  5. using System;
  6. using System.Linq;
  7.  
  8. namespace AcadTest
  9. {
  10.     public class ObjectLinkTest
  11.     {
  12.         const string HardPointerRecordName = "HardPointer";
  13.         const string SoftPointerRecordName = "SoftPointer";
  14.         /*
  15.          * Handle не пересчитываются автоматически
  16.          * и хранятся в виде строки
  17.         const string HandleRecordName = "Handle";
  18.        
  19.          * Ownerships коды не записываются в Xrecord        
  20.         const string HardOwnershipRecordName = "HardOwner";
  21.         const string SoftOwnershipRecordName = "SoftOwner";
  22.         */
  23.  
  24.         [CommandMethod("AddSoftPointerLink")]
  25.         public void AddSoftPointerLink()
  26.         {
  27.             AddLink(DxfCode.SoftPointerId);
  28.         }
  29.  
  30.         [CommandMethod("AddHardPointerLink")]
  31.         public void AddHardPointerLink()
  32.         {
  33.             AddLink(DxfCode.HardPointerId);
  34.         }
  35.  
  36.         [CommandMethod("GetSoftPointerLinkedObject")]
  37.         public void GetSoftPointerLinkedObject()
  38.         {
  39.             SelectLinked(DxfCode.SoftPointerId);
  40.         }
  41.  
  42.         [CommandMethod("GetHardPointerLinkedObject")]
  43.         public void GetHardPointerLinkedObject()
  44.         {
  45.             SelectLinked(DxfCode.HardPointerId);
  46.         }
  47.  
  48.         static void AddLink(DxfCode code)
  49.         {
  50.             SupportMethods.InitializeVars(out Document adoc,
  51.                 out Editor ed, out Database db);
  52.  
  53.             if (!ed.SelectEntity(out ObjectId firstId, "\nSelect object for write: ")
  54.                 || !ed.SelectEntity(out ObjectId secondId, "\nSelect object for reference: "))
  55.                 return;
  56.  
  57.             WriteObjectIdToDict(firstId, secondId, code);
  58.         }
  59.  
  60.         static void SelectLinked(DxfCode code)
  61.         {
  62.             SupportMethods.InitializeVars(out Document adoc,
  63.                 out Editor ed, out Database db);
  64.  
  65.             if (!ed.SelectEntity(out ObjectId objId, "\nSelect object: "))
  66.                 return;
  67.  
  68.             ObjectId linkedId = GetObjectIdFromDict(objId, code);
  69.             if (linkedId.IsValid
  70.                 && linkedId.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(Entity))))
  71.             {
  72.                 ed.SetImpliedSelection(new[] { linkedId });
  73.             }
  74.         }
  75.  
  76.         static void WriteObjectIdToDict(ObjectId objId, ObjectId writedId, DxfCode code)
  77.         {
  78.             ObjectId dictId;
  79. #pragma warning disable CS0618 // Type or member is obsolete
  80.             using (DBObject obj = objId.Open(OpenMode.ForRead))
  81. #pragma warning restore CS0618 // Type or member is obsolete
  82.             {
  83.                 dictId = obj.ExtensionDictionary;
  84.                 if (!dictId.IsValid)
  85.                 {
  86.                     obj.UpgradeOpen();
  87.                     obj.CreateExtensionDictionary();
  88.                     dictId = obj.ExtensionDictionary;
  89.                 }
  90.             }
  91.  
  92. #pragma warning disable CS0618 // Type or member is obsolete
  93.             using (DBDictionary dict = dictId.Open(OpenMode.ForWrite) as DBDictionary)
  94. #pragma warning restore CS0618 // Type or member is obsolete
  95.             using (Xrecord xrec = new Xrecord())
  96.             using (ResultBuffer resBuff = new ResultBuffer(new TypedValue((int)code, writedId)))
  97.             {
  98.                 string entryName = GetLinkRecordName(code);
  99.                 if (dict.Contains(entryName))
  100.                 {
  101.                     dict.Remove(entryName);
  102.                 }
  103.                 xrec.Data = resBuff;                                
  104.                 dict.SetAt(entryName, xrec);
  105.             }
  106.         }
  107.  
  108.         static ObjectId GetObjectIdFromDict(ObjectId objId, DxfCode code)
  109.         {
  110.             ObjectId dictId = ObjectId.Null;
  111. #pragma warning disable CS0618 // Type or member is obsolete
  112.             using (DBObject obj = objId.Open(OpenMode.ForRead))
  113. #pragma warning restore CS0618 // Type or member is obsolete
  114.             {
  115.                 dictId = obj.ExtensionDictionary;
  116.             }
  117.  
  118.             string entryName = GetLinkRecordName(code);
  119.  
  120.             if (!dictId.IsValid) return ObjectId.Null;
  121.  
  122.             ObjectId xrecId = ObjectId.Null;
  123.  
  124. #pragma warning disable CS0618 // Type or member is obsolete
  125.             using (DBDictionary dict = dictId.Open(OpenMode.ForRead) as DBDictionary)
  126. #pragma warning restore CS0618 // Type or member is obsolete
  127.             {
  128.                 if (dict.Contains(entryName))
  129.                 {
  130.                     xrecId = dict.GetAt(entryName);
  131.                 }
  132.             }
  133.  
  134.             if (!xrecId.IsValid) return ObjectId.Null;
  135.  
  136. #pragma warning disable CS0618 // Type or member is obsolete
  137.             using (Xrecord xrec = xrecId.Open(OpenMode.ForRead) as Xrecord)
  138. #pragma warning restore CS0618 // Type or member is obsolete
  139.             using (ResultBuffer resBuf = xrec.Data)
  140.             {
  141.                 TypedValue[] tVals;
  142.                 if (resBuf != null && (tVals = resBuf.AsArray()).Length > 0)
  143.                 {
  144.                     object val = tVals.FirstOrDefault
  145.                         (item => item.TypeCode == (int)code).Value;
  146.                     if (val != null && val is ObjectId id)
  147.                     {
  148.                         return id;
  149.                     }
  150.                 }
  151.             }
  152.             return ObjectId.Null;
  153.         }
  154.  
  155.         static string GetLinkRecordName(DxfCode code)
  156.         {
  157.             switch (code)
  158.             {
  159.                 case DxfCode.HardPointerId:
  160.                     return HardPointerRecordName;
  161.                 case DxfCode.SoftPointerId:
  162.                     return SoftPointerRecordName;
  163.                 default:
  164.                     throw new ArgumentException("Undefinded dxf code");
  165.             }
  166.         }
  167.     }
  168.  
  169.     static class Support
  170.     {
  171.         public static void InitializeVars(out Document adoc, out Editor ed, out Database db)
  172.         {
  173.             adoc = Application.DocumentManager.MdiActiveDocument;
  174.             ed = adoc.Editor;
  175.             db = adoc.Database;
  176.         }
  177.  
  178.         public static bool SelectEntity(this Editor ed, out ObjectId id, string msg = "\nSelect entity: ")
  179.         {
  180.             PromptEntityResult entRes = ed.GetEntity(msg);
  181.             id = entRes.ObjectId;
  182.             return entRes.Status == PromptStatus.OK;
  183.         }
  184.     }
  185. }
  186.  

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Во внутреннем механизме AutoCAD это реализовано немного иначе. Если объекты копируются парами - то так же как у меня, а вот если один объект из пары - то у копии появляется связь к связанному объекту оригинала.
Фактически об этом я и говорил. И это в моём случае было недопустимо. Т.е. если выбран один из объектов для копирования, то необходимо было добавить в набор все связанные объекты для копирования. И в копиях ссылки должны были быть на копии, а не на оригиналы.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Кирилл Захаров

  • ADN OPEN
  • ***
  • Сообщений: 119
  • Карма: 5
Желательно сразу включить запись лога в файл, так как будет очень много сообщений
Извините, не относится к теме обсуждения.
Александр, подскажите пожалуйста как включить запись лога в файл в ARXDBG.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Александр, подскажите пожалуйста как включить запись лога в файл в ARXDBG.
Так это же стандартный AutoCAD'овский log-файл. Т.е. включается/выключается командами _LOGFILEON/_LOGFILEOFF
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Кирилл Захаров

  • ADN OPEN
  • ***
  • Сообщений: 119
  • Карма: 5
Спасибо, Александр. Не знал об этой команде

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Спасибо, Александр. Не знал об этой команде
Есть еще системная переменная LOGFILEPATH для задания пути к log-файлу: http://help.autodesk.com/view/ACD/2017/RUS/?guid=GUID-0E2D4DF2-4C26-48AC-ACBC-819E3C46CE59
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение