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

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

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

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

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

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


Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Зарегистрировать свое приложение (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
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь 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
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь 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
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Atomohod,
Я бы на твоём месте добавлял XData в уже скопированные объекты. Благо, что в idMap сохраняются пары исходный ObjectId и скопированный ObjectId.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

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

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

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

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

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

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

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

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

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Благо, что в idMap сохраняются пары исходный ObjectId и скопированный ObjectId.
При замене порядка - то есть не присваивать xData внутри чертежа источника, а сначала скопировать объекты в конечный чертеж и присваивать там, я хватаю ошибку и Автокад падает.  В момент  работы с IdPair. Такие дела.


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

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Полный код класса:
Код - 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.     }
« Последнее редактирование: 13-04-2021, 10:50:47 от Александр Ривилис »

Оффлайн Lemieux

  • ADN OPEN
  • ****
  • Сообщений: 384
  • Карма: 21
Atomohod, оформи код в теги C#

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

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
По поводу форматирования тебе уже написали.
Каюсь, второпях не уследил.

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Проект в zip-архиве сюда. Мне надоело смотреть на обрывки кода.
Прикладываю проект в архиве. txt файлики для конфига тоже.

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

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Нужен минимальный тестовый пример, созданный с нуля, который воспроизводит ошибку.
Александр Ривилис, фишка то в том и есть, что я получаю разные ошибки (перетертые 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 одни и те же. Сборку единого чертежа всегда провожу в чистый новый файл.

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Новый пример с dwg.

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

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Ты или не понимаешь что я прошу
Не понимаю, что не так. Чертежи с нуля с объектами приложил, все решение с файлами необходимыми для сборки и для конфига тоже.
Нужен минимальный тестовый пример, созданный с нуля, который воспроизводит ошибку
В моем случае стабильно воспроизводится одна проблема - исчезновение ранее добавленных объектов после вставки последующих. Другие ошибки я хватаю хаотично на ЭТОМ ЖЕ коде, не меняя его. Воспроизвести их нарочно у меня нет возможности - я не знаю что их вызывает и условия под это мне не создать.

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

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

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Я по диагонали просмотрел твой код. У тебя есть несколько грубейших ошибок.
1. В методе SetDynamicBlockProperty (файл EntityProcessor.cs) ты открываешь BlockReference для чтения, а затем модифицируешь его динамические свойства. Это как???
2. В методе GetXData2 (файл Synchronizer.cs) ты открываешь транзакцию, но не вызываешь Commit. Соответственно происходит откат. И вообще этот метод бред в чистейшем виде. Ты передаешь в него DBObject, т.е. объект уже открыт. Но ты зачем-то решил стартовать еще транзакцию, и снова открыть этот же объект. В моей голове это не укладывается.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Зачем мне тратить моё время на изучение логики твоей программы
Тут я прошу прощения, алгоритм и цель кода я действительно подробно не рассказал.
Мой код собирает в единый большой чертеж объекты из множества детализированных чертежей. Отбор идет по положению объектов чертежа-источника на специально предназначенных слоях и внутри замкнутой полилинии. Если два этих условия соблюдаются, то объект переносится(копируется из источника) в чертеж-сборку. При переносе в xdata записывается признак чертежа-источника(его номер) из которого получены объекты. Затем, при обновлении чертежа сборки, по данным из xdata происходит отбор и удаление объектов предыдущего поколения, чтобы в сборке не было наслоения объектов друг на друга.
Такая цель моего кода.

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

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

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

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

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

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

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

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

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

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
В методе SetDynamicBlockProperty (файл EntityProcessor.cs) ты открываешь BlockReference для чтения, а затем модифицируешь его динамические свойства. Это как???
2. В методе GetXData2 (файл Synchronizer.cs) ты открываешь транзакцию, но не вызываешь Commit. Соответственно происходит откат. И вообще этот метод бред в чистейшем виде. Ты передаешь в него DBObject, т.е. объект уже открыт.

За вложенностью транзакций действительно не уследил. Спасибо. Блок сделал ForWrite. Но проблема исчезновения ранее добавленных объектов не ушла - они исчезают. Причем те что имеют в xdata AcDbBlockRepETag и мной добавленные xdata как раз и исчезают. Но ошибку про AcDbRegAppTable(9) Invalid Entry Audit не дает. Вот такая непонятка.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Причем те что имеют в xdata AcDbBlockRepETag и мной добавленные xdata как раз и исчезают.
Ну это как раз очевидно. Ты сначала меняешь для BlockReference его XData, а затем меняешь динамические свойства. Изменение динамического свойства приводит к созданию нового BlockReference и добавленные тобой XData исчезают. Попробуй убрать строку
Код - C# [Выбрать]
  1. EntityProcessor.SetDynamicBlockProperty(destDb, blockNames);
Будут ли исчезать твои XData?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Но проблема исчезновения ранее добавленных объектов не ушла - они исчезают. Причем те что имеют в xdata AcDbBlockRepETag и мной добавленные xdata как раз и исчезают
Исчезают объекты или исчезает XData?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Исчезают объекты. Это и получается если использовать мой код и два dwg из архива, что я выкладывал как пример.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Atomohod,
Повторюсь.
Попробуй убрать строку
Код - C# [Выбрать]

    EntityProcessor.SetDynamicBlockProperty(destDb, blockNames);

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Попробуй убрать строку
Попробовал - объекты исчезают. Исчезает ли в них xdata никак не проверить - объект в чертеже отсутствует. Тут нужно наверно уточнить - пропадают не только блоки но и полилинии и другие объекты. Объекты я здесь применяю как широкий термин - все что отображается/нарисовано в чертеже.
AcDbBlockRepETag есть также у меня в свойствах полилинии при открытии MgdDbg.

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

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

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Atomohod,
Я вижу, что у тебя в чертеже следы NanoSPDS. Если он установлен, как и другие сторонние или твои приложения - всё снеси и проверяй на чистом AutoCAD со всеми установленными обновлениями. ARXDBG и MGDDBG можешь оставить.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Вот и я полазил по всем интернетам, пытаясь разобраться - пока не смог. Но факт остается фактом, прикладываю скриншот


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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Вот и я полазил по всем интернетам, пытаясь разобраться - пока не смог. Но факт остается фактом, прикладываю скриншот

Какой то глюк - сообщение задвоилось.

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Я вижу, что у тебя в чертеже следы NanoSPDS
А как Вы это увидели? Где можно посмотреть? У нас есть чертежи контрагентов, он рисуют в Нанокаде. Но чертежи на которых исчезают объекты сделаны в Автокадах 2015 и 2010. В Нанокаде они не разрабатывались.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
он рисуют в Нанокаде
Я не сказал Нанокад. Я сказал NonoSPDS:



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

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

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

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Кстати оба чертежа редактировались не в AutoCAD:


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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Скриншота не вижу.
Картинка почему-то не прикрепляется. Попытаюсь еще раз.




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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
всё снеси и проверяй на чистом AutoCAD со всеми установленными обновлениями
На чистой установке тоже самое.

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

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Как тогда быть с исчезающими объектами? Можно не пытаться отлаживать мой код или есть какие-то возможности обходного пути? Например пройти по всем элементам и те что не блоки очистить от xdata с AcDbBlockRepETag вручную.
В качестве догадки  - может ли этот AcDbBlockRepETag унаследовть полилиния которая раньше была внутри блока, затем блок разбили, а AcDbBlockRepETag унаследовался линией?

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

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Цитата: 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. }

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Есть ли какая-нибудь особенность обнуления 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. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение