Как избежать затирание информации в Xdata

Автор Тема: Как избежать затирание информации в Xdata  (Прочитано 20577 раз)

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Здравствуйте

Такой вопрос - есть объект с XData добавленными самим Автокадом. Мой код тоже добавляет данные в XData затирая имеющиеся там данные. Как сохранить уже записанные Автокадом данные и при этом добавить свои?


Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 822
  • Карма: 167
    • Мои плагины к Автокаду
Зарегистрировать свое приложение (RegAppTableRecord) и правильно заполнять буфер XData, начиная с кода приложения
Код - C# [Выбрать]
  1. new ResultBuffer(new TypedValue((int)DxfCode.ExtendedDataRegAppName, XDAppName))
Этого достаточно, что Автокад не стер данные других приложений в XData

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Этого достаточно, что Автокад не стер данные других приложений в XData

У меня вроде так и сделано, но исходные  данные все равно заменяются

Код - C# [Выбрать]
  1. using (Transaction tr = db.TransactionManager.StartTransaction())
  2.                 {
  3.                     RegAppTable regTab = tr.GetObject(db.RegAppTableId, OpenMode.ForWrite) as RegAppTable;
  4.                     if (!regTab.Has(appName))
  5.                     {
  6.                         RegAppTableRecord regTabRec = new RegAppTableRecord();
  7.                         regTabRec.Name = appName;
  8.                         regTab.Add(regTabRec);
  9.                         tr.AddNewlyCreatedDBObject(regTabRec, true);
  10.                     }
  11.                     tr.Commit();
  12.                 }
  13.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  14.                 {
  15.                     using (ResultBuffer rb = new ResultBuffer())
  16.                     {
  17.                         rb.Add(new TypedValue((int)DxfCode.ExtendedDataRegAppName, appName));
  18.                         rb.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, xdataStr));
  19.  
  20.                         foreach (ObjectId id in ids)
  21.                         {
  22.                             Entity ent = tr.GetObject(id, OpenMode.ForWrite, false, true) as Entity;
  23.                             if (ent != null) ent.XData = rb;
  24.                         }
  25.                     }
  26.                     tr.Commit();
  27.                 }


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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
У меня вроде так и сделано, но исходные  данные все равно заменяются
Только если имя твоего приложения (appName) совпадает с именем, которое использует AutoCAD.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Только если имя твоего приложения (appName) совпадает с именем, которое использует AutoCAD.
Нет, они разные. В чем и проблема. До у меня AcDbBlockRepETag, после - данные моего приложения. Предыдущих нет. Возможно ли что хData обнуляются сами при вставке(программно через sourceDb.WblockCloneObjects(Drawing.GetObjects(sourceDb, layersToSync), idMSpace, idMap, DuplicateRecordCloning.Ignore, false);) в новый чертеж?
Алгоритм моего кода такой: в исходном чертеже отобрать объекты, прикрепить к ним xdata и вставить в новый чертеж при помощи sourceDb.WblockCloneObjects.

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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Возможно ли что хData обнуляются сами при вставке(программно через sourceDb.WblockCloneObjects(Drawing.GetObjects(sourceDb, layersToSync), idMSpace, idMap, DuplicateRecordCloning.Ignore, false);) в новый чертеж?
Алгоритм моего кода такой: в исходном чертеже отобрать объекты, прикрепить к ним xdata и вставить в новый чертеж при помощи sourceDb.WblockCloneObjects.
А ты RegAppTableRecord копируешь в новый чертеж? Если ты сейчас говоришь об алгоритме, который в предыдущей теме, то тогда понятно откуда у тебя ошибка. В новом чертеже нет этой RegAppTableRecord если ты её не скопировал или не создал до копирования.
Кстати, а что такое layersToSync? И что делает Drawing.GetObjects(sourceDb, layersToSync)?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
layersToSync
Это список слоев (string) объекты с которых нужно скопировать.

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Выкладываю GetObjects
Код - C# [Выбрать]
  1. public static ObjectIdCollection GetObjects(Database db, List <string> layersToSync)
  2.         {
  3.             ObjectIdCollection filteredEntities = new ObjectIdCollection();
  4.             List < Entity > entities = new List < Entity >();
  5.            
  6.             try
  7.             {
  8.                 Transaction tr = db.TransactionManager.StartTransaction();
  9.                 using ( tr )
  10.                 {
  11.                     BlockTable bt = (BlockTable) tr.GetObject(db.BlockTableId, OpenMode.ForRead, false, false);
  12.                     BlockTableRecord btr = (BlockTableRecord) tr.GetObject(bt[ BlockTableRecord.ModelSpace ], OpenMode.ForRead);
  13.                     foreach ( ObjectId item in btr )
  14.                     {
  15.                         Entity ent = (Entity) tr.GetObject(item, OpenMode.ForRead);
  16.                         entities.Add(ent);
  17.                     }
  18.  
  19.                     var boundaries = Selector.GetBoundariesObjectId(db);
  20.                     var entitiesOnLayers = Selector.SelectEntityOnDesiredLayers(entities, layersToSync);
  21.                     foreach ( var ent in entitiesOnLayers )
  22.                     {
  23.                         if ( Selector.IsEntityValidForSync(ent, boundaries) )
  24.                         {
  25.                             filteredEntities.Add(ent.ObjectId);
  26.                         }
  27.                     }
  28.  
  29.                     Marker.AttachXDataToSelectionSetObjects(ref filteredEntities, db);
  30.                     tr.Commit();
  31.                 }
  32.             }
  33.             catch ( Exception ex )
  34.             {
  35.                 Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.ToString());
  36.             }
  37.  
  38.             return filteredEntities;
  39.         }

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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Atomohod,
Я бы на твоём месте добавлял XData в уже скопированные объекты. Благо, что в idMap сохраняются пары исходный ObjectId и скопированный ObjectId.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
В новом чертеже нет этой RegAppTableRecord если ты её не скопировал или не создал до копирования.
То есть ее нужно копировать вручную? Я думал что sourceDb.WblockCloneObjects переносит все данные всех объектов без потерь, то есть делает глубокую копию, выходит что я ошибаюсь?

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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Я думал что sourceDb.WblockCloneObjects переносит все данные всех объектов без потерь
Это не так. Тут есть много нюансов.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
что в idMap сохраняются пары исходный ObjectId и скопированный ObjectId.
Как до них добраться? Через idMap.Lookup? Разобрался, через Lookup ---IdPair idpair = idMap.Lookup(b.ObjectId);
« Последнее редактирование: 12-04-2021, 16:28:40 от Atomohod »

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
много нюансов.
В моем случае предыдущую xData нужно копировать вручную и ее отсутствие вызывает ошибки? Так?

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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
В моем случае предыдущую xData нужно копировать вручную и ее отсутствие вызывает ошибки? Так?
Не XData копировать, а RegAppTableRecord
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Не XData копировать, а RegAppTableRecord
Как ее правильно скопировать через WblockCloneObjects? Можно пример?