Ссылки через Xrecord и коды SoftPointerId и HardPointerId. Тонкости.

Автор Тема: Ссылки через Xrecord и коды SoftPointerId и HardPointerId. Тонкости.  (Прочитано 4002 раз)

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

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Пытаюсь разобраться с этими кодами. В реализации разницы никакой - можно хоть SoftPointerId записать, хоть HardPointerId. По поведению, вроде, тоже разницы нет. Хотя, иногда в тестах, если использовалась ссылка типа HardPointerId, при копировании через буфер двух связанных объектов один из объектов (на который ссылались) просто пропадал. При попытке записать это на видео, такое поведение прекратилось и больше не удалось воспроизвести. Но "осадочек остался". Может быть, есть мысли, почему такое могло произойти? Возможно, тут какую-то роль играет то, что объект, в Extension Dictionary которого записывалась связь - это мультивыноска.
Второй момент - описание таких связей в ObjectARX Guide:
Цитировать
A hard pointer reference protects an object from purge. For example, an entity contains a hard pointer reference to a layer. Therefore, you can't purge a layer that is pointed to by one or more entities. When a new database is written out from an existing one (for example, in a WBLOCK operation), all hard pointers are copied into the new database.
Я попробовал создавать ссылки с помощью SoftPointerId и HardPointerId и сделать _WBLOCK связанных объектов, ожидая, что в случае с SoftPointerId связь пропадет. Но этого не произошло! Так в чем же разница тогда между этими кодами?
Для тестов использовал следующий код (из темы http://adn-cis.org/forum/index.php?topic=743.0):
Код - 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
Я попробовал создавать ссылки с помощью SoftPointerId и HardPointerId и сделать _WBLOCK связанных объектов, ожидая, что в случае с SoftPointerId связь пропадет. Но этого не произошло!
Ты делал _WBLOCK с одним из объектов или с обоими?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Я попробовал все варианты - оба объекта, только тот, который ссылается, только тот, на который ссылается. Вы предполагаете, что при использовании Hard связанный объект будет тоже экспортироваться, даже если его не выбрали? Мои тесты показали, что этого не происходит.

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

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

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

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

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Возможно в случае DBDictionary.TreatElementsAsHard == true что-то изменится.
Нет, не изменилось поведение. Связанный объект не подхватывается.
Если они связаны напрямую, то да.
А код добавления такой связи на ObjectARX возможно будет написать? Или это можно сделать только для Custom-объектов?

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

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