Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Atomohod от 12-04-2021, 11:30:29

Название: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 12-04-2021, 11:30:29
Здравствуйте

Такой вопрос - есть объект с XData добавленными самим Автокадом. Мой код тоже добавляет данные в XData затирая имеющиеся там данные. Как сохранить уже записанные Автокадом данные и при этом добавить свои?
(https://i.postimg.cc/t7xbW6z1/2021-04-12-112856.jpg) (https://postimg.cc/t7xbW6z1)
Название: Re: Как избежать затирание информации в Xdata
Отправлено: avc от 12-04-2021, 11:37:47
Зарегистрировать свое приложение (RegAppTableRecord) и правильно заполнять буфер XData, начиная с кода приложения
Код - C# [Выбрать]
  1. new ResultBuffer(new TypedValue((int)DxfCode.ExtendedDataRegAppName, XDAppName))
Этого достаточно, что Автокад не стер данные других приложений в XData
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 12-04-2021, 13:01:56
Этого достаточно, что Автокад не стер данные других приложений в 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.                 }

Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 12-04-2021, 13:09:33
У меня вроде так и сделано, но исходные  данные все равно заменяются
Только если имя твоего приложения (appName) совпадает с именем, которое использует AutoCAD.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 12-04-2021, 13:36:38
Только если имя твоего приложения (appName) совпадает с именем, которое использует AutoCAD.
Нет, они разные. В чем и проблема. До у меня AcDbBlockRepETag, после - данные моего приложения. Предыдущих нет. Возможно ли что хData обнуляются сами при вставке(программно через sourceDb.WblockCloneObjects(Drawing.GetObjects(sourceDb, layersToSync), idMSpace, idMap, DuplicateRecordCloning.Ignore, false);) в новый чертеж?
Алгоритм моего кода такой: в исходном чертеже отобрать объекты, прикрепить к ним xdata и вставить в новый чертеж при помощи sourceDb.WblockCloneObjects.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 12-04-2021, 13:42:08
Возможно ли что хData обнуляются сами при вставке(программно через sourceDb.WblockCloneObjects(Drawing.GetObjects(sourceDb, layersToSync), idMSpace, idMap, DuplicateRecordCloning.Ignore, false);) в новый чертеж?
Алгоритм моего кода такой: в исходном чертеже отобрать объекты, прикрепить к ним xdata и вставить в новый чертеж при помощи sourceDb.WblockCloneObjects.
А ты RegAppTableRecord копируешь в новый чертеж? Если ты сейчас говоришь об алгоритме, который в предыдущей теме, то тогда понятно откуда у тебя ошибка. В новом чертеже нет этой RegAppTableRecord если ты её не скопировал или не создал до копирования.
Кстати, а что такое layersToSync? И что делает Drawing.GetObjects(sourceDb, layersToSync)?
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 12-04-2021, 13:54:52
layersToSync
Это список слоев (string) объекты с которых нужно скопировать.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 12-04-2021, 13:56:34
Выкладываю 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.         }
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 12-04-2021, 14:00:39
Atomohod,
Я бы на твоём месте добавлял XData в уже скопированные объекты. Благо, что в idMap сохраняются пары исходный ObjectId и скопированный ObjectId.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 12-04-2021, 14:33:39
В новом чертеже нет этой RegAppTableRecord если ты её не скопировал или не создал до копирования.
То есть ее нужно копировать вручную? Я думал что sourceDb.WblockCloneObjects переносит все данные всех объектов без потерь, то есть делает глубокую копию, выходит что я ошибаюсь?
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 12-04-2021, 14:54:45
Я думал что sourceDb.WblockCloneObjects переносит все данные всех объектов без потерь
Это не так. Тут есть много нюансов.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 12-04-2021, 14:58:28
что в idMap сохраняются пары исходный ObjectId и скопированный ObjectId.
Как до них добраться? Через idMap.Lookup? Разобрался, через Lookup ---IdPair idpair = idMap.Lookup(b.ObjectId);
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 12-04-2021, 15:00:16
много нюансов.
В моем случае предыдущую xData нужно копировать вручную и ее отсутствие вызывает ошибки? Так?
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 12-04-2021, 15:02:40
В моем случае предыдущую xData нужно копировать вручную и ее отсутствие вызывает ошибки? Так?
Не XData копировать, а RegAppTableRecord
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 12-04-2021, 15:29:31
Не XData копировать, а RegAppTableRecord
Как ее правильно скопировать через WblockCloneObjects? Можно пример?
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 12-04-2021, 17:50:06
Atomohod,
В качестве idOwner - передаёшь destDb.RegAppTableId. 
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 12-04-2021, 18:05:55
В моем случае предыдущую xData нужно копировать вручную и ее отсутствие вызывает ошибки? Так?
Не XData копировать, а RegAppTableRecord
Стоп. Ты меня совсем запутал. В исходной базе тебе нужно добавлять XData к твоим объектам? Если нет, то тогда создаёшь свою RegAppTableRecord в базе, в которую копируешь и добавляешь XData к скопированным объектам. И еще. WblockCloneObjects крайне желательно вызывать вне всяких транзакций. Кстати, как я заметил, у тебя куча вложенных транзакций. Это допустимо, но нежелательно. Если без этого можно обойтись (а у тебя точно можно), то лучше обойтись без вложенных транзакций.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 08:30:28
Благо, что в idMap сохраняются пары исходный ObjectId и скопированный ObjectId.
При замене порядка - то есть не присваивать xData внутри чертежа источника, а сначала скопировать объекты в конечный чертеж и присваивать там, я хватаю ошибку и Автокад падает.  В момент  работы с IdPair. Такие дела.
(https://i.postimg.cc/34BpDnYQ/2021-04-13-082439.jpg) (https://postimg.cc/34BpDnYQ)
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 10:02:51
Atomohod,
Код покажешь или предлагаешь лечить по картинке?
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 10:20:46
Полный код класса:
Код - C# [Выбрать]
  1.  public static class Synchronizer
  2.     {
  3.         [CommandMethod("syncdrawings")]
  4.         public static void SynchronizeDrawings()
  5.         {
  6.             List<string> fileNames = Drawing.SelectDrawings();
  7.             if (fileNames.Count == 0)
  8.             {
  9.                 return;
  10.             }
  11.  
  12.             Document acDoc = Application.DocumentManager.MdiActiveDocument;
  13.             Database destDb = acDoc.Database;
  14.             ObjectId idMSpace = ObjectId.Null;
  15.             var layerResourcePath = PluginConfigurator.GetResourcePath("layer");
  16.             List<string> layersToSync = EntityProcessor.GetLayersToSync(layerResourcePath);
  17.             var blockListPath = PluginConfigurator.GetResourcePath("block");
  18.             List<string> blockNames = EntityProcessor.GetBlockNames(blockListPath);
  19.             using (Transaction acTrans = destDb.TransactionManager.StartTransaction())
  20.             {
  21.                 BlockTable acBlkTbl = acTrans.GetObject(destDb.BlockTableId, OpenMode.ForRead) as BlockTable;
  22.                 idMSpace = acBlkTbl[BlockTableRecord.ModelSpace];
  23.  
  24.                 var startTime = System.Diagnostics.Stopwatch.StartNew();
  25.  
  26.                 foreach (string fileName in fileNames)
  27.                 {
  28.                     using (Database sourceDb = new Database(false, true))
  29.                     {
  30.                         sourceDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, false, null);
  31.                         string areaNumber = null;
  32.                         try
  33.                         {
  34.                             areaNumber = sourceDb.GetBuildingAreaNumber();
  35.                         }
  36.                         catch (NullReferenceException)
  37.                         {
  38.                             // Application.ShowAlertDialog("Set construction area number in source drawing by Drawing properties => subject");
  39.                         }
  40.  
  41.                         DeletePreviousEntities(areaNumber, destDb);
  42.                         using (IdMapping idMap = new IdMapping())
  43.                         {
  44.                             ObjectIdCollection iDrObjects = Drawing.GetObjects(sourceDb, layersToSync);
  45.                             sourceDb.WblockCloneObjects(iDrObjects, idMSpace, idMap, DuplicateRecordCloning.Ignore, false);
  46.  
  47.                             ObjectIdCollection iDrObjects2 = new ObjectIdCollection();
  48.                             foreach (ObjectId item in iDrObjects)
  49.                             {
  50.                                 IdPair idpair = idMap.Lookup(item);
  51.                                 iDrObjects2.Add(idpair.Value);
  52.                             }
  53.  
  54.                             Marker.AttachXDataToSelectionSetObjects(iDrObjects2, destDb, areaNumber);
  55.  
  56.  
  57.                         }
  58.  
  59.                     }
  60.                     startTime.Stop();
  61.                     var resultTime = startTime.Elapsed;
  62.                     string elapsedTime = String.Format("{0:00}:m{1:00}:s{2:00}.{3:000}",
  63.                         resultTime.Hours,
  64.                         resultTime.Minutes,
  65.                         resultTime.Seconds,
  66.                         resultTime.Milliseconds);
  67.                     Logger logger = new Logger();
  68.                     logger.CreateSynchronizationLog(fileName, elapsedTime);
  69.                     startTime.Restart();
  70.                 }
  71.                 EntityProcessor.SetDynamicBlockProperty(destDb, blockNames);
  72.  
  73.                 acTrans.Commit();
  74.             }
  75.         }
  76.  
  77.         public static void DeletePreviousEntities(string label, Database db)
  78.         {
  79.             Transaction tr = db.TransactionManager.StartTransaction();
  80.  
  81.             using (tr)
  82.             {
  83.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  84.                 ObjectId btrId = bt[BlockTableRecord.ModelSpace];
  85.                 {
  86.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead);
  87.                     foreach (ObjectId entId in btr)
  88.                     {
  89.                         Entity ent = tr.GetObject(entId, OpenMode.ForRead) as Entity;
  90.                         if ((ent != null) && ent.GetXData2().Contains(label))
  91.                         {
  92.                             ent.UpgradeOpen();
  93.                             ent.Erase();
  94.                             ent.DowngradeOpen();
  95.                         }
  96.                     }
  97.                 }
  98.  
  99.                 tr.Commit();
  100.             }
  101.         }
  102.                
  103.  
  104.         public static List<string> GetXData2(this DBObject item)
  105.  
  106.         {
  107.             Document doc = Application.DocumentManager.MdiActiveDocument;
  108.  
  109.             Editor ed = doc.Editor;
  110.  
  111.             Transaction tr = doc.TransactionManager.StartTransaction();
  112.             List<string> xData = new List<string>();
  113.             using (tr)
  114.  
  115.             {
  116.                 DBObject obj = tr.GetObject(item.ObjectId, OpenMode.ForRead);
  117.  
  118.                 ResultBuffer rb = obj.XData;
  119.  
  120.                 if (rb != null)
  121.  
  122.                 {
  123.                     foreach (TypedValue tv in rb)
  124.  
  125.                     {
  126.                         xData.Add(tv.Value.ToString());
  127.                     }
  128.  
  129.                     rb.Dispose();
  130.                 }
  131.             }
  132.  
  133.             return xData;
  134.         }
  135.     }
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Lemieux от 13-04-2021, 10:28:35
Atomohod, оформи код в теги C#
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 11:00:54
Atomohod,
По поводу форматирования тебе уже написали. Теперь по поводу кода. Создай новый проект с нуля. В него помести код. Проект в zip-архиве сюда. Мне надоело смотреть на обрывки кода.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 11:31:29
По поводу форматирования тебе уже написали.
Каюсь, второпях не уследил.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 11:33:12
Проект в zip-архиве сюда. Мне надоело смотреть на обрывки кода.
Прикладываю проект в архиве. txt файлики для конфига тоже.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 11:42:27
Atomohod,
Ты видимо не понял. У меня нет ни времени, ни желания изучать все твои классы и методы. Нужен минимальный тестовый пример, созданный с нуля, который воспроизводит ошибку. В противном случае я ничем тебе помочь не смогу.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 13:33:11
Нужен минимальный тестовый пример, созданный с нуля, который воспроизводит ошибку.
Александр Ривилис, фишка то в том и есть, что я получаю разные ошибки (перетертые xData, AcDbRegAppTable(9) Invalid Entry, pure virtual function call, исчезновение ранее добавленных объектов) причем хаотично - 20 раз отработает нормально, на 21 выдаст ошибку, на 22 норм, затем совершенно другая ошибка и снова нормально.
На тех файлах, что я сейчас приложил к этому сообщению воспроизводится, по крайней мере у меня, одна из ошибок - исчезновение ранее добавленных объектов.
Это самая критичная - проверить после сборки из 20 чертежей, что где-то исчезла пара объектов нереально.


Последовательность моих действий:
Запускаю код - команда syncdrawings
Выбираю 1.dwg.
Код отрабатывает.
Выбираю 2.dwg.
Код отрабатывает и после его работы исчезает часть объектов из 1.dwg, добавленных ранее.

Пытался запускать несколько чертежей конвейером (в коде предусмотрен выбор одновременно нескольких файлов) результат тот же.

Audit выдает либо ноль ошибок, либо AcDbRegAppTable(9) Invalid Entry - заранее не угадаешь. Либо в процессе работы pure virtual function call - пока словил один раз.

Код один и тот же. Все dwg одни и те же. Сборку единого чертежа всегда провожу в чистый новый файл.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 13:34:15
Новый пример с dwg.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 19:03:46
Atomohod,
Я пас. Ты или не понимаешь что я прошу или тебе лень это делать. Дальше сам.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 19:26:51
Ты или не понимаешь что я прошу
Не понимаю, что не так. Чертежи с нуля с объектами приложил, все решение с файлами необходимыми для сборки и для конфига тоже.
Нужен минимальный тестовый пример, созданный с нуля, который воспроизводит ошибку
В моем случае стабильно воспроизводится одна проблема - исчезновение ранее добавленных объектов после вставки последующих. Другие ошибки я хватаю хаотично на ЭТОМ ЖЕ коде, не меняя его. Воспроизвести их нарочно у меня нет возможности - я не знаю что их вызывает и условия под это мне не создать.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 19:44:57
Не понимаю, что не так. Чертежи с нуля с объектами приложил, все решение с файлами необходимыми для сборки и для конфига тоже.
Зачем мне тратить моё время на изучение логики твоей программы? В этом главный вопрос.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 20:04:58
Я по диагонали просмотрел твой код. У тебя есть несколько грубейших ошибок.
1. В методе SetDynamicBlockProperty (файл EntityProcessor.cs) ты открываешь BlockReference для чтения, а затем модифицируешь его динамические свойства. Это как???
2. В методе GetXData2 (файл Synchronizer.cs) ты открываешь транзакцию, но не вызываешь Commit. Соответственно происходит откат. И вообще этот метод бред в чистейшем виде. Ты передаешь в него DBObject, т.е. объект уже открыт. Но ты зачем-то решил стартовать еще транзакцию, и снова открыть этот же объект. В моей голове это не укладывается.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 20:31:30
Зачем мне тратить моё время на изучение логики твоей программы
Тут я прошу прощения, алгоритм и цель кода я действительно подробно не рассказал.
Мой код собирает в единый большой чертеж объекты из множества детализированных чертежей. Отбор идет по положению объектов чертежа-источника на специально предназначенных слоях и внутри замкнутой полилинии. Если два этих условия соблюдаются, то объект переносится(копируется из источника) в чертеж-сборку. При переносе в xdata записывается признак чертежа-источника(его номер) из которого получены объекты. Затем, при обновлении чертежа сборки, по данным из xdata происходит отбор и удаление объектов предыдущего поколения, чтобы в сборке не было наслоения объектов друг на друга.
Такая цель моего кода.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 21:04:21
Обратил внимание, что ты копируешь между базами с флагом Ignore. Ты подумал что будет при наличии одноименных блоков, имеющих разное содержимое?
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 21:21:59
Ты подумал что будет при наличии одноименных блоков, имеющих разное содержимое
Последующие переопределятся на основе первого описания блока, которое было добавлено раньше.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 21:32:50
Последующие переопределятся на основе первого описания блока, которое было добавлено раньше.
Если это динамические блоки, то я очень сомневаюсь, что это будет корректно работать.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 21:37:08
что это будет корректно работать.
Возможны ошибки во время работы кода или потеря свойств самого блока?
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 21:39:50
что это будет корректно работать.
Возможны ошибки во время работы кода или потеря свойств самого блока?
И то и другое. И у тебя еще и просто ошибка в коде при изменении свойства видимости блока.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 21:55:00
В методе SetDynamicBlockProperty (файл EntityProcessor.cs) ты открываешь BlockReference для чтения, а затем модифицируешь его динамические свойства. Это как???
2. В методе GetXData2 (файл Synchronizer.cs) ты открываешь транзакцию, но не вызываешь Commit. Соответственно происходит откат. И вообще этот метод бред в чистейшем виде. Ты передаешь в него DBObject, т.е. объект уже открыт.

За вложенностью транзакций действительно не уследил. Спасибо. Блок сделал ForWrite. Но проблема исчезновения ранее добавленных объектов не ушла - они исчезают. Причем те что имеют в xdata AcDbBlockRepETag и мной добавленные xdata как раз и исчезают. Но ошибку про AcDbRegAppTable(9) Invalid Entry Audit не дает. Вот такая непонятка.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 22:02:22
Причем те что имеют в xdata AcDbBlockRepETag и мной добавленные xdata как раз и исчезают.
Ну это как раз очевидно. Ты сначала меняешь для BlockReference его XData, а затем меняешь динамические свойства. Изменение динамического свойства приводит к созданию нового BlockReference и добавленные тобой XData исчезают. Попробуй убрать строку
Код - C# [Выбрать]
  1. EntityProcessor.SetDynamicBlockProperty(destDb, blockNames);
Будут ли исчезать твои XData?
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 22:03:59
Но проблема исчезновения ранее добавленных объектов не ушла - они исчезают. Причем те что имеют в xdata AcDbBlockRepETag и мной добавленные xdata как раз и исчезают
Исчезают объекты или исчезает XData?
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 22:23:33
Исчезают объекты. Это и получается если использовать мой код и два dwg из архива, что я выкладывал как пример.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 22:25:39
Atomohod,
Повторюсь.
Попробуй убрать строку
Код - C# [Выбрать]

    EntityProcessor.SetDynamicBlockProperty(destDb, blockNames);

Будут ли исчезать твои XData?
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 22:43:50
Попробуй убрать строку
Попробовал - объекты исчезают. Исчезает ли в них xdata никак не проверить - объект в чертеже отсутствует. Тут нужно наверно уточнить - пропадают не только блоки но и полилинии и другие объекты. Объекты я здесь применяю как широкий термин - все что отображается/нарисовано в чертеже.
AcDbBlockRepETag есть также у меня в свойствах полилинии при открытии MgdDbg.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 22:50:51
AcDbBlockRepETag есть также у меня в свойствах полилинии при открытии MgdDbg.
Бред какой-то. Эта RegApp должна быть только у динамических блоков.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 23:02:29
Atomohod,
Я вижу, что у тебя в чертеже следы NanoSPDS. Если он установлен, как и другие сторонние или твои приложения - всё снеси и проверяй на чистом AutoCAD со всеми установленными обновлениями. ARXDBG и MGDDBG можешь оставить.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 23:04:15
Вот и я полазил по всем интернетам, пытаясь разобраться - пока не смог. Но факт остается фактом, прикладываю скриншот
(https://i.postimg.cc/vDgvpgzd/2021-04-13-230032.jpg) (https://postimg.cc/vDgvpgzd)
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 23:04:24
Вот и я полазил по всем интернетам, пытаясь разобраться - пока не смог. Но факт остается фактом, прикладываю скриншот
(https://i.postimg.cc/vDgvpgzd/2021-04-13-230032.jpg) (https://postimg.cc/vDgvpgzd)

Какой то глюк - сообщение задвоилось.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 23:07:22
Я вижу, что у тебя в чертеже следы NanoSPDS
А как Вы это увидели? Где можно посмотреть? У нас есть чертежи контрагентов, он рисуют в Нанокаде. Но чертежи на которых исчезают объекты сделаны в Автокадах 2015 и 2010. В Нанокаде они не разрабатывались.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 23:10:04
он рисуют в Нанокаде
Я не сказал Нанокад. Я сказал NonoSPDS:

(https://live.staticflickr.com/65535/51114152731_02b2fd6585_o.png)

Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 23:12:42
Какой то глюк - сообщение задвоилось.
Скриншота не вижу.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 13-04-2021, 23:17:20
Кстати оба чертежа редактировались не в AutoCAD:
(https://live.staticflickr.com/65535/51114074488_969ff19101_o.png)

Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 13-04-2021, 23:43:37
Скриншота не вижу.
Картинка почему-то не прикрепляется. Попытаюсь еще раз.


(https://i.postimg.cc/vDgvpgzd/2021-04-13-230032.jpg) (https://postimg.cc/vDgvpgzd)
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 14-04-2021, 12:55:44
всё снеси и проверяй на чистом AutoCAD со всеми установленными обновлениями
На чистой установке тоже самое.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 14-04-2021, 15:17:05
всё снеси и проверяй на чистом AutoCAD со всеми установленными обновлениями
На чистой установке тоже самое.
Значит спишем на баг AutoCAD 2015, который давно не поддерживается и то, что чертежи редактировались не только в AutoCAD.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 14-04-2021, 15:22:23
Как тогда быть с исчезающими объектами? Можно не пытаться отлаживать мой код или есть какие-то возможности обходного пути? Например пройти по всем элементам и те что не блоки очистить от xdata с AcDbBlockRepETag вручную.
В качестве догадки  - может ли этот AcDbBlockRepETag унаследовть полилиния которая раньше была внутри блока, затем блок разбили, а AcDbBlockRepETag унаследовался линией?
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 14-04-2021, 15:33:44
Например пройти по всем элементам и те что не блоки очистить от xdata с AcDbBlockRepETag вручную.
Попробуй.
В качестве догадки  - может ли этот AcDbBlockRepETag унаследовть полилиния которая раньше была внутри блока, затем блок разбили, а AcDbBlockRepETag унаследовался линией?
Только если это баг или разбивали блок не стандартной командой _EXPLODE, а какими-то сторонними методами.
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Atomohod от 15-04-2021, 14:55:36
Цитата: Atomohod от 14-04-2021, 15:22:23

    Например пройти по всем элементам и те что не блоки очистить от xdata с AcDbBlockRepETag вручную.

Попробуй.

Есть ли какая-нибудь особенность обнуления xdata? Я написал простой код, он не срабатывает. Ошибок нет, просто xdata после его работы остаются на своем месте.
Код - C# [Выбрать]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows.Forms;
  4.  
  5. using Autodesk.AutoCAD.ApplicationServices;
  6. using Autodesk.AutoCAD.DatabaseServices;
  7. using Autodesk.AutoCAD.Runtime;
  8. using OpenFileDialog = Autodesk.AutoCAD.Windows.OpenFileDialog;
  9.  
  10. namespace Xdata
  11. {
  12.     public static class Class1
  13.     {
  14.         public static List<string> SelectDrawings()
  15.         {
  16.             List<string> fileNames = new List<string>();
  17.             try
  18.             {
  19.                 OpenFileDialog ofd = new OpenFileDialog("Выбрать чертеж", "", "dwg", "did", OpenFileDialog.OpenFileDialogFlags.AllowMultiple);
  20.                 DialogResult yy = ofd.ShowDialog();
  21.                 if (yy == DialogResult.OK)
  22.                 {
  23.                     foreach (string file in ofd.GetFilenames())
  24.                     {
  25.                         fileNames.Add(file);
  26.                     }
  27.                 }
  28.             }
  29.             catch (System.Exception ex)
  30.             {
  31.                 Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.ToString());
  32.             }
  33.  
  34.             return fileNames;
  35.         }
  36.  
  37.         public static void GetObjects(Database db)
  38.         {
  39.            
  40.             List<Entity> entities = new List<Entity>();
  41.  
  42.             try
  43.             {
  44.                 Transaction tr = db.TransactionManager.StartTransaction();
  45.                 using (tr)
  46.                 {
  47.                     BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false, true);
  48.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
  49.                     foreach (ObjectId item in btr)
  50.                     {
  51.                         Entity ent = (Entity)tr.GetObject(item, OpenMode.ForWrite, false, true);
  52.                         entities.Add(ent);
  53.                     }
  54.  
  55.                     foreach (var ent in entities)
  56.                     {
  57.                         ClearXData(ent);
  58.                     }
  59.  
  60.                    
  61.                     tr.Commit();
  62.                 }
  63.             }
  64.             catch (System.Exception ex)
  65.             {
  66.                 Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.ToString());
  67.             }
  68.  
  69.            
  70.         }
  71.  
  72.         public static void ClearXData(Entity item)
  73.         {
  74.             ResultBuffer rb = item.XData;
  75.             if (rb != null)
  76.             {
  77.                 item.XData = new ResultBuffer();
  78.          
  79.             }
  80.         }
  81.         [CommandMethod("CXD")]
  82.         public static void SynchronizeDrawings()
  83.         {
  84.             List<string> fileNames = SelectDrawings();
  85.             if (fileNames.Count == 0)
  86.             {
  87.                 return;
  88.             }
  89.  
  90.             Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  91.             Database destDb = acDoc.Database;
  92.             ObjectId idMSpace = ObjectId.Null;
  93.  
  94.             using (Transaction acTrans = destDb.TransactionManager.StartTransaction())
  95.             {
  96.                 BlockTable acBlkTbl = acTrans.GetObject(destDb.BlockTableId, OpenMode.ForRead, false, true) as BlockTable;
  97.                 idMSpace = acBlkTbl[BlockTableRecord.ModelSpace];
  98.  
  99.                 var startTime = System.Diagnostics.Stopwatch.StartNew();
  100.  
  101.                 foreach (string fileName in fileNames)
  102.                 {
  103.                     using (Database sourceDb = new Database(false, true))
  104.                     {
  105.                         sourceDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, false, null);
  106.                         GetObjects(sourceDb);
  107.                         sourceDb.SaveAs(fileName, DwgVersion.Current);
  108.                     }
  109.                 }
  110.  
  111.                 acTrans.Commit();
  112.             }
  113.         }
  114.     }
  115. }
Название: Re: Как избежать затирание информации в Xdata
Отправлено: Александр Ривилис от 15-04-2021, 15:05:03
Есть ли какая-нибудь особенность обнуления xdata?
Есть. Во-первых, полностью обнулять XData нельзя. Ты так совсем испортишь чертеж. Во-вторых, чтобы обнулить XData для конкретного приложения, нужно (appName - это имя конкретного приложения, например "AcDbBlockRepETag", только удалять его нужно у всего кроме BlockReference):
Код - C# [Выбрать]
  1. using (ResultBuffer rb = new ResultBuffer())
  2. {
  3.    rb.Add(new TypedValue((int)DxfCode.ExtendedDataRegAppName, appName));
  4.    Entity ent = tr.GetObject(id, OpenMode.ForWrite) as Entity;
  5.    if (ent != null) ent.XData = rb;
  6. }