Копирование COGOPOINT из внешних ссылок.

Автор Тема: Копирование COGOPOINT из внешних ссылок.  (Прочитано 12771 раз)

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

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

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

  • ADN OPEN
  • Сообщений: 19
  • Карма: 0
Добрый день. У меня имеется чертеж, в котором вставлена внешняя ссылка. Ссылка представляет собой набор линий и copopoint'ов. У меня написан метод, который позволяет копировать объекты из внешних ссылок. Проблема заключается в том, что после копировании cogopoint'ов они становятся невидимыми на чертеже, хотя в базу данных чертежа  они успешно добавляются. Линии при этом копируются и отображаются нормально.  Не могу разобраться, в чем тут проблема.
ПО проверяется на  Civil 3D 2015.
Ниже привожу скриншоты чертежа и код методов копирования объектов.
1. Состояния чертежа до копирования объектов из внешних ссылок.


2. Состояние чертежа после копирования объектов из внешних ссылок.

На рис. 2 видно, что cogopoint'ы (зеленые крестики) не видны на чертеже.

3.Методы осуществляющий копирование объектов из внешних ссылок.

Код - C# [Выбрать]
  1.                  /// <summary>
  2.                 /// Запуск копирования объектов из внешней ссылки.
  3.                 /// </summary>
  4.                 public void Execute()
  5.                 {
  6.                         var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  7.                         _db = doc.Database;
  8.                         var layers = new List<string>();
  9.  
  10.                         var isSucsess = true;
  11.  
  12.                         _formProgress = new FormProgressBar(null) { Text = @"Копирование объектов" };
  13.                         System.Windows.Forms.Application.DoEvents();
  14.                         Autodesk.AutoCAD.ApplicationServices.Application.ShowModelessDialog(_formProgress);
  15.                         System.Windows.Forms.Application.DoEvents();
  16.  
  17.                         using (_trans = _db.TransactionManager.StartTransaction())
  18.                         using (var bt = (BlockTable)_trans.GetObject(_db.BlockTableId, OpenMode.ForWrite))
  19.                         using (_btr = (BlockTableRecord)_trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite))
  20.                         {
  21.                                 // Получаем наименование всех слоев.
  22.                                 var layerTable = (LayerTable)_trans.GetObject(doc.Database.LayerTableId, OpenMode.ForWrite);
  23.                                 foreach (var layerObjId in layerTable)
  24.                                 {
  25.                                         using (var layer = (LayerTableRecord)_trans.GetObject(layerObjId, OpenMode.ForRead))
  26.                                         {
  27.                                                 if (!layer.IsFrozen && !layer.IsOff)
  28.                                                 {
  29.                                                         layers.Add(layer.Name);
  30.                                                 }
  31.                                         }
  32.                                 }
  33.  
  34.                                 // Вытягиваем внешние ссылки.
  35.                                 var acadReferenceTree = Tap.CADGIS.AutoCAD.Utils.AcadReferenceTree.Create(doc);
  36.                                 acadReferenceTree.Build();
  37.                                 var nodes = acadReferenceTree.Nodes.Where(n => n.Type == AcadReferenceType.DRAWING && n.Database != null).ToList();
  38.                                 if (nodes.Count == 0)
  39.                                 {
  40.                                         MessageBox.Show("Документ не содержит внешних ссылок", "Внимание", MessageBoxButton.OK, MessageBoxImage.Warning);
  41.                                         _formProgress.Dispose();
  42.                                         return;
  43.                                 }
  44.  
  45.                                 layers.AddRange(nodes.Select(p => p.Name + "|0"));
  46.                                 foreach (var objId in _btr)
  47.                                 {
  48.                                         using (var ent = (Entity)_trans.GetObject(objId, OpenMode.ForWrite))
  49.                                         {
  50.  
  51.                                                 // Проверка элемента по игнор-листу
  52.                                                 if (ent.IsErased || ent is ProxyEntity || !ent.Visible || ent.GetType().ToString().Contains("Site"))
  53.                                                         continue;
  54.                                                 try
  55.                                                 {
  56.                                                         // Если объект блок референс
  57.                                                         var bref = ent as BlockReference;
  58.                                                         if (bref != null)
  59.                                                         {
  60.                                                                 // является ли объект внешней ссылкой
  61.                                                                 var isExternalRef = nodes.Any(p => p.Name.Equals(bref.Name));
  62.  
  63.                                                                 if (isExternalRef && !layers.Contains(bref.Layer))
  64.                                                                         continue;
  65.  
  66.                                                                 // Получаем объекты из внешних ссылок
  67.                                                                 var bferEntities = Tap.CADGIS.AutoCAD.Instruments.AcadEntityInstruments.GetEntityFromBlockReference(bref, layers);
  68.  
  69.                                                                 // Добавляем объекты в базу
  70.                                                                 AddEntitiesToBTR(bferEntities, isExternalRef, layers);
  71.  
  72.                                                                 // Скрываем внеш. ссылку.
  73.                                                                 bref.Visible = false;
  74.                                                                 //bref.Erase(true);
  75.                                                         }
  76.                                                 }
  77.                                                 catch
  78.                                                 {
  79.                                                         isSucsess = false;
  80.                                                 }
  81.                                         }
  82.                                 }
  83.  
  84.                                 _formProgress.SetMessage(100, string.Empty);
  85.                                 if (!isSucsess)
  86.                                         MessageBox.Show("Копирование объектов произошло с ошибкой", "Копирование", MessageBoxButton.OK, MessageBoxImage.Error);
  87.                                 else
  88.                                 {
  89.                                         doc.Editor.Regen();
  90.                                         _trans.Commit();
  91.                                         MessageBox.Show("Объекты успешно скопированы", "Копирование", MessageBoxButton.OK, MessageBoxImage.Information);
  92.                                 }
  93.  
  94.                                 if (_formProgress != null && !_formProgress.IsDisposed)
  95.                                 {
  96.                                         _formProgress.Dispose();
  97.                                 }
  98.                         }
  99.                 }
  100.  
  101.                 /// <summary>
  102.                 /// Добавление объектов в бд чертежа.
  103.                 /// </summary>
  104.                 /// <param name="bferEntities"></param>
  105.                 /// <param name="isExternalRef"></param>
  106.                 /// <param name="layers"></param>
  107.                 private void AddEntitiesToBTR(List<Entity> bferEntities, bool isExternalRef, List<string> layers)
  108.                 {
  109.                         var oldPercent = 0;
  110.                         var i = 0;
  111.  
  112.                         foreach (var brefEntity in bferEntities)
  113.                         {
  114.                                 if (brefEntity.Database == null)
  115.                                         brefEntity.SetDatabaseDefaults(_db);
  116.  
  117.                                 if (brefEntity is MLeader && brefEntity.Database == null)
  118.                                         continue;
  119.  
  120.                                 if (isExternalRef && !layers.Contains(brefEntity.Layer))
  121.                                         continue;
  122.  
  123.                                 if (!layers.Contains(brefEntity.Layer))
  124.                                         continue;
  125.  
  126.                                 // обновляем прогресс бар
  127.                                 if (++i * 100 / bferEntities.Count != oldPercent)
  128.                                 {
  129.                                         oldPercent = ++i * 100 / bferEntities.Count;
  130.                                         _formProgress.SetMessage(oldPercent, string.Empty);
  131.                                 }
  132.  
  133.                                 _btr.AppendEntity(brefEntity);
  134.                                 _trans.AddNewlyCreatedDBObject(brefEntity, true);
  135.                         }
  136.                 }
  137.  

4. Скриншоты при обнаружении cogopoint в коде.





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

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

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Насколько я помню Civil, то там есть группы точек и стили отображения. Может ваши точки нормально копируются, просто в самом чертеже не настроено их отображение?

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

  • ADN OPEN
  • Сообщений: 19
  • Карма: 0
1. Что происходит если этот чертеж сохранить, закрыть и снова открыть?
2. Функции копирования неудачные. Для полного копирования объектов (и всего, что с ними связано) между чертежами следует использовать метод Database.WblockCloneObjects.
Хорошо, сейчас попробую предложенные вами способы и отпишусь.

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

  • ADN OPEN
  • Сообщений: 19
  • Карма: 0
1. При закрытии и открытии документа стилизованные линии тоже не отображаются.
2. Переписал метод с использованием Database.WblockCloneObjects.
Код - C# [Выбрать]
  1.                  /// <summary>
  2.                 /// Запуск инструмента.
  3.                 /// </summary>
  4.                 [CommandMethod(Constants.CommandNames.ExtractObjects, CommandFlags.Modal)]
  5.                 public void Execute()
  6.                 {
  7.                         var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  8.                         _db = doc.Database;
  9.                         var layers = new List<string>();
  10.  
  11.                         var isSucsess = true;
  12.  
  13.                         _formProgress = new FormProgressBar(null) { Text = @"Копирование объектов" };
  14.                         System.Windows.Forms.Application.DoEvents();
  15.                         Autodesk.AutoCAD.ApplicationServices.Application.ShowModelessDialog(_formProgress);
  16.                         System.Windows.Forms.Application.DoEvents();
  17.  
  18.                         using (_trans = _db.TransactionManager.StartTransaction())
  19.                         using (var bt = (BlockTable)_trans.GetObject(_db.BlockTableId, OpenMode.ForWrite))
  20.                         using (_btr = (BlockTableRecord)_trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite))
  21.                         {
  22.                                 // Получаем наименование всех слоев.
  23.                                 var layerTable = (LayerTable)_trans.GetObject(doc.Database.LayerTableId, OpenMode.ForWrite);
  24.                                 foreach (var layerObjId in layerTable)
  25.                                 {
  26.                                         using (var layer = (LayerTableRecord)_trans.GetObject(layerObjId, OpenMode.ForRead))
  27.                                         {
  28.                                                 if (!layer.IsFrozen && !layer.IsOff)
  29.                                                 {
  30.                                                         layers.Add(layer.Name);
  31.                                                 }
  32.                                         }
  33.                                 }
  34.  
  35.                                 // Вытягиваем внешние ссылки.
  36.                                 var acadReferenceTree = Tap.CADGIS.AutoCAD.Utils.AcadReferenceTree.Create(doc);
  37.                                 acadReferenceTree.Build();
  38.                                 var nodes = acadReferenceTree.Nodes.Where(n => n.Type == AcadReferenceType.DRAWING && n.Database != null).ToList();
  39.                                 if (nodes.Count == 0)
  40.                                 {
  41.                                         MessageBox.Show("Документ не содержит внешних ссылок", "Внимание", MessageBoxButton.OK, MessageBoxImage.Warning);
  42.                                         _formProgress.Dispose();
  43.                                         return;
  44.                                 }
  45.  
  46.                                 layers.AddRange(nodes.Select(p => p.Name + "|0"));
  47.                                 foreach (var objId in _btr)
  48.                                 {
  49.                                         using (var ent = (Entity)_trans.GetObject(objId, OpenMode.ForWrite))
  50.                                         {
  51.                                                 // Проверка элемента по игнор-листу
  52.                                                 if (ent.IsErased || ent is ProxyEntity || !ent.Visible || ent.GetType().ToString().Contains("Site"))
  53.                                                         continue;
  54.                                                 try
  55.                                                 {
  56.                                                         // Если объект блок референс
  57.                                                         var bref = ent as BlockReference;
  58.                                                         if (bref != null)
  59.                                                         {
  60.                                                                 // является ли объект внешней ссылкой
  61.                                                                 var isExternalRef = nodes.Any(p => p.Name.Equals(bref.Name));
  62.  
  63.                                                                 if (isExternalRef && !layers.Contains(bref.Layer))
  64.                                                                         continue;
  65.  
  66.                                                                 // Получаем объекты из внешних ссылок
  67.                                                                 //var bferEntities = Tap.CADGIS.AutoCAD.Instruments.AcadEntityInstruments.GetEntityFromBlockReference(bref, layers);
  68.  
  69.                                                                 var objIds = new ObjectIdCollection { bref.ObjectId };
  70.  
  71.                                                                 _trans.TransactionManager.QueueForGraphicsFlush();
  72.                                                                 bref.Database.WblockCloneObjects(objIds, _db.CurrentSpaceId, new IdMapping(), DuplicateRecordCloning.Ignore, false);
  73.  
  74.                                                                 // Добавляем объекты в базу
  75.                                                                 //AddEntitiesToBTR(bferEntities, isExternalRef, layers);
  76.  
  77.                                                                 // Скрываем внеш. ссылку.
  78.                                                                 bref.Visible = false;
  79.                                                                 //bref.Erase(true);
  80.                                                         }
  81.                                                 }
  82.                                                 catch
  83.                                                 {
  84.                                                         isSucsess = false;
  85.                                                 }
  86.                                         }
  87.                                 }
  88.  
  89.                                 _formProgress.SetMessage(100, string.Empty);
  90.                                 if (!isSucsess)
  91.                                         MessageBox.Show("Копирование объектов произошло с ошибкой", "Копирование", MessageBoxButton.OK, MessageBoxImage.Error);
  92.                                 else
  93.                                 {
  94.                                         _trans.Commit();
  95.                                         doc.Editor.Regen();
  96.                                         MessageBox.Show("Объекты успешно скопированы", "Копирование", MessageBoxButton.OK, MessageBoxImage.Information);
  97.                                 }
  98.  
  99.                                 if (_formProgress != null && !_formProgress.IsDisposed)
  100.                                 {
  101.                                         _formProgress.Dispose();
  102.                                 }
  103.                         }
  104.                 }
  105.  

Результат работы метода.


Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
А если так:
Код - C# [Выбрать]
  1. _db.WblockCloneObjects(objIds, _db.CurrentSpaceId, new IdMapping(), DuplicateRecordCloning.Ignore, false);

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

  • ADN OPEN
  • Сообщений: 19
  • Карма: 0
А если так:
Код - C# [Выбрать]
  1. _db.WblockCloneObjects(objIds, _db.CurrentSpaceId, new IdMapping(), DuplicateRecordCloning.Ignore, false);

Что все-равно не получается


Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Вот нашел по теме - http://adn-cis.org/pri-ispolzovanii-wblockcloneobjects-skopirovannyie-v-prostranstvo-modeli-primitivyi-ischezayut-v-tekushhem-chertezhe.html
Еще интересное замечание нашел - нельзя прям в методе писать new IdMapping(). Нужно обязательно сначала создать переменную!

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

  • ADN OPEN
  • Сообщений: 19
  • Карма: 0
Вот нашел по теме - http://adn-cis.org/pri-ispolzovanii-wblockcloneobjects-skopirovannyie-v-prostranstvo-modeli-primitivyi-ischezayut-v-tekushhem-chertezhe.html
Еще интересное замечание нашел - нельзя прям в методе писать new IdMapping(). Нужно обязательно сначала создать переменную!
Хорошо, сейчас попробую все.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Добавлю еще.
1. Не следует вызвать WblockCloneObjects внутри транзакции.
2. Если не модифицируешь объект, то не нужно открывать его ForWrite.
3. Из кода я не понял из какой базы bref.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 19
  • Карма: 0
Все равно выскакивает ошибка WrongDatabase. Документ залочен.
1.

2.

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

  • ADN OPEN
  • Сообщений: 19
  • Карма: 0
Добавлю еще.
1. Не следует вызвать WblockCloneObjects внутри транзакции.
2. Если не модифицируешь объект, то не нужно открывать его ForWrite.
3. Из кода я не понял из какой базы bref.

3. bref берется  из базы текущего чертежа.

Сейчас закрою транзакции и попробую снова.

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

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

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

  • ADN OPEN
  • Сообщений: 19
  • Карма: 0
3. bref берется  из базы текущего чертежа.
Не понял. Совсем не понял.

Код - C# [Выбрать]
  1. var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  2. _db = doc.Database;
  3. .....
  4. using (var docLock = doc.LockDocument())
  5. using (_trans = _db.TransactionManager.StartTransaction())
  6. using (var bt = (BlockTable)_trans.GetObject(_db.BlockTableId, OpenMode.ForWrite))
  7. using (_btr = (BlockTableRecord)_trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite))
  8. {
  9. .......
  10.      foreach (var objId in _btr)
  11.     {
  12.         using (var ent = (Entity)_trans.GetObject(objId, OpenMode.ForWrite))
  13.        {
  14.             var bref = ent as BlockReference;
  15.             ......................
  16.        }
  17.  
  18.     }
  19. }
  20.  

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
А может стоит тогда попробовать DeepCloneObjects?
По логике, получается, что не происходит обращения к БД источника внешней ссылки. Хотя, могу и ошибаться

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

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

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Что вот это за ерунда:
Код - C# [Выбрать]
  1. using (var bt = (BlockTable)_trans.GetObject(_db.BlockTableId, OpenMode.ForWrite))
  2. using (_btr = (BlockTableRecord)_trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite))
???
Зачем всё открывать для записи? Ты же их не модифицируешь и при этом мешаешь работать другим методам,
которые не в состоянии открыть эти объекты для чтения, так как они уже открыты для записи.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
1. А почему здесь, а не в разделе по Civil 3D?
2. Каковы условия работы приложения? Запускается в Civil 3D или в голом AutoCAD? Вставляется в чертеж AutoCAD или в чертеж Civil3D?
3. После копирования, COGO-точки физически присутствуют в базе чертежа, в который выполнялось копирование? Проверяется это не визуальным отображением, а в навигаторе.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
1. А почему здесь, а не в разделе по Civil 3D?
Логично. Тему переношу.

2. Каковы условия работы приложения? Запускается в Civil 3D или в голом AutoCAD? Вставляется в чертеж AutoCAD или в чертеж Civil3D?
В первом сообщении указано, что работа идёт в Civil 3D 2015.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Что вот это за ерунда:
Код - C# [Выбрать]
  1. using (var bt = (BlockTable)_trans.GetObject(_db.BlockTableId, OpenMode.ForWrite))
  2. using (_btr = (BlockTableRecord)_trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite))
???
Зачем всё открывать для записи? Ты же их не модифицируешь и при этом мешаешь работать другим методам,
которые не в состоянии открыть эти объекты для чтения, так как они уже открыты для записи.
+ использование using здесь лишнее, т.к. объекты открываются через транзакцию и она управляет ими.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
+ использование using здесь лишнее, т.к. объекты открываются через транзакцию и она управляет ими.
Полностью согласен.
zavor,
Что касается использования Database.WblockCloneObjects - следует сначала отобрать все ObjectId для объектов из одной внешней ссылки в одну ObjectIdCollection и вызвать Database.WblockCloneObjects для копирования всей этой коллекции примитивов в текущую базу данных.
Ну и выполнить такую операцию в цикле для всех баз внешних ссылок.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Я вообще бы наказывал за использование объектов Civil 3D во внешних ссылках. Внешние ссылки - это механизм AutoCAD, в Civil совместная работа выполняется через быстрые ссылки. Вы что,
 и поверхности, и трассы, и коридоры и характерные линии собираетесь перетаскивать таким образом? Сдается мне, что это очень проблемный сценарий...

/* Убрал тэг offtop, так как это очень по существу темы. Александр Ривилис */
« Последнее редактирование: 17-04-2017, 12:46:14 от Александр Ривилис »

Отмечено как Решение zavor 20-04-2017, 11:17:46

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Александр Наумович, понял идею :) Просто я посчитал, что к коду мои размышления не относятся, поэтому запрятал их.
Немного поясню, в чем я вижу проблему такого копирования. Многие объекты Civil 3D взаимосвязаны в чертеже и очень часто являются зависимыми от других объектов. Что будет происходить с ними при копировании - неизвестно.
На примере COGO-точек: У точки есть стиль, метки. У меток тоже есть стили. Эти стили могут зависеть от параметров чертежа, от других стилей. Это все - объекты базы данных чертежа. Копируя одну точку из чертежа в чертеж вы тянете весь этот "хвост" зависимостей. Реализовано ли это в методах API для AutoCAD - большой вопрос. Я сталкивался уже с тем, что с объектами Civil 3D не всегда такие "продвинутые" методы работали корректно.
Даже если Вам удастся все это наладить и все будет нормально внедряться, в целевом чертеже Вы получите полную кашу из настроек и стилей. Часть из них останется из исходного чертежа, часть придет из внешних ссылок. Потом очень трудно будет разобраться в этом месиве.
Я бы просто пропускал все объекты Civil 3D при внедрении ссылок. Либо взрывал бы их до объектов AutoCAD. Еще, как вариант - не копировать объекты, а создавать их заново в целевом чертеже. К примеру, нашли COGO-точку во внешней ссылке, прочитали все ее параметры, создали новую точку в целевом чертеже методами Civil 3D API и задали ей все нужные свойства. Но я не понимаю смысла этого перетаскивания объектов Civil из чертежа в чертеж.

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

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

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

  • ADN OPEN
  • Сообщений: 19
  • Карма: 0
Постарался выкинуть все лишнее.

Код - C# [Выбрать]
  1. public void Action()
  2.                 {
  3.                         var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  4.                         var db = doc.Database;
  5.  
  6.                         using (var trans = db.TransactionManager.StartTransaction())
  7.                         using (var bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForWrite))
  8.                         using (var btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite))
  9.                         {
  10.                                 foreach (var objId in btr)
  11.                                 {
  12.                                         using (var ent = (Entity)trans.GetObject(objId, OpenMode.ForWrite))
  13.                                         {
  14.                                                 try
  15.                                                 {
  16.                                                         var bref = ent as BlockReference;
  17.                                                         if (bref != null)
  18.                                                         {
  19.                                                                 var bferEntities = new DBObjectCollection();
  20.                                                                 bref.Explode(bferEntities);
  21.                                                                 foreach (var brefEntity in bferEntities)
  22.                                                                 {
  23.                                                                         var entity = (Entity)brefEntity;
  24.                                                                         if (entity.Database == null)
  25.                                                                                 entity.SetDatabaseDefaults(db);
  26.                                                                        
  27.                                                                 }
  28.  
  29.                                                                 bref.Visible = false;
  30.                                                         }
  31.                                                 }
  32.                                                 catch (Exception e)
  33.                                                 {
  34.                                                 }
  35.                                         }
  36.                                 }
  37.  
  38.                                 trans.Commit();
  39.                         }
  40.                 }
  41.  

У меня возникает следующий вопрос: когда я делаю
Код - C# [Выбрать]
  1. var bferEntities = new DBObjectCollection();
  2. bref.Explode(bferEntities);
  3.  
то у меня появляется набор объектов из блокреференса. Но эти объекты имеют objectid равным {0}.



Как в таком случае использовать Database.DeepCloneObjects?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Постарался выкинуть все лишнее.
Ты похоже не читаешь то, что тебе пишут. По поводу ForWrite я уже писал. По поводу using тебе писал Дмитрий.
У меня возникает следующий вопрос: когда я делаю
Код - C# [Выбрать]

    var bferEntities = new DBObjectCollection();
    bref.Explode(bferEntities);
     
то у меня появляется набор объектов из блокреференса. Но эти объекты имеют objectid равным {0}.

Как в таком случае использовать Database.DeepCloneObjects?
1. Кто-то из нас советовал делать Explode?
2. Никак ты не сможешь использовать Database.DeepCloneObjects для этих объектов.

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

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
1. Для BlockReference ты должен найти его BlockTableRecord и определиться внешняя ссылка ли это или нет. Если не внешняя ссылка пропускаешь.
2. Для BlockTableRecord находишь ее базу: BlockTableRecord.GetXrefDatabase
3. Создаёшь ObjectIdCollection, проходишь по ModelSpace этой базы и отбираешь все (или нужные тебе объекты)
4. При помощи WblockCloneObjects копируешь выбранные в ObjectIdCollection объекты в ModelSpace текущего чертежа.
5. Возможно (если BlockReference.BlockTransform возвращает не единичную матрицу) придётся еще выполнить трансформацию всех скопированных объектов.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 19
  • Карма: 0
Хорошо, спасибо. Выполню  и отпишусь.

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Подозреваю, что часть ссылок SoftPointer и соответственно не будут копироваться при помощи WblockCloneObjects в другой чертеж. Как, например, не копируются группы.
Только сейчас понял, что Вы, скорее всего, имели в виду группы объектов AutoCAD. Я подумал (в контексте обсуждения) что Вы про группы точек, и удивлялся Вашим познаниям Civil 3D :)

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
подумал (в контексте обсуждения) что Вы про группы точек, и удивлялся Вашим познаниям Civil 3D :)
:D
Речь конечно шла о группах (Group) AutoCAD: https://forums.autodesk.com/t5/net/wblockcloneobjects-and-groups/td-p/4712099
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 19
  • Карма: 0
Поменял код следующим образом
Код - C# [Выбрать]
  1.  public void Action()
  2.                 {
  3.                         var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  4.                         var db = doc.Database;
  5.  
  6.                         using (var trans = db.TransactionManager.StartTransaction())
  7.                         {
  8.                                 var bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
  9.                                 var btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
  10.                                
  11.                                 foreach (var objId in btr)
  12.                                 {
  13.                                         using (var ent = (Entity)trans.GetObject(objId, OpenMode.ForRead))
  14.                                         {
  15.                                                 try
  16.                                                 {
  17.                                                         var bref = ent as BlockReference;
  18.                                                         if (bref != null)
  19.                                                         {
  20.                                                                 //Является ли блок внешней ссылкой?
  21.                                                                 var isExternal = btr.Cast<ObjectId>().All(a => a != bref.BlockTableRecord);
  22.  
  23.                                                                 if (!isExternal)
  24.                                                                         return;
  25.  
  26.                                                                 // Получаем BlockTableRecord внешней ссылки
  27.                                                                 var btrBref = (BlockTableRecord)trans.GetObject(bref.BlockTableRecord, OpenMode.ForRead);
  28.                                                                 var xDB = btrBref.GetXrefDatabase(false);
  29.  
  30.                                                                 // открываем транзакцию внешней был для получения объектов
  31.                                                                 using (var transRef = xDB.TransactionManager.StartTransaction())
  32.                                                                 {
  33.                                                                         // Внешняя база блока
  34.                                                                         var btBref = transRef.GetObject(xDB.BlockTableId, OpenMode.ForRead) as BlockTable;
  35.                                                                         var s = transRef.GetObject( btBref[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
  36.  
  37.                                                                         // Создаем и заполняем коллекцию id'шников
  38.                                                                         var idColl = new ObjectIdCollection();
  39.                                                                         foreach (var objid in s)
  40.                                                                         {
  41.                                                                                 idColl.Add(objid);
  42.                                                                         }
  43.  
  44.                                                                         var iMap = new IdMapping();
  45.                                                                         xDB.WblockCloneObjects(idColl, db.CurrentSpaceId, iMap, DuplicateRecordCloning.Ignore, false);
  46.                                                                 }
  47.  
  48.                                                                 bref.Visible = false;
  49.                                                         }
  50.                                                 }
  51.                                                 catch (Exception e)
  52.                                                 {
  53.                                                 }
  54.                                         }
  55.                                 }
  56.  
  57.                                 trans.Commit();
  58.                         }
  59.                 }
  60.  

В итоге во время попытки выполнить WblockCloneObjects "выкидывается" экспепшн.




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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Это связано с тем, что базы из Xref. Тут есть два варианта решения:
1. После
Код - C# [Выбрать]
  1. var xDB = btrBref.GetXrefDatabase(false);
вставляешь
Код - C# [Выбрать]
  1. xDB.RestoreOriginalXrefSymbols();
и перед
Код - C# [Выбрать]
  1. bref.Visible = false;
вставляешь
Код - C# [Выбрать]
  1. xDB.RestoreForwardingXrefSymbols();
Должно работать, но возможно медленно.
2.  Для btrBref получаешь её PathName
Создаёшь новую Database:
Код - C# [Выбрать]
  1. Database xDb = new Database(false,true);
и в неё читаешь (Database.ReadDwgFile) файл по этому пути.
Дальше работаешь с ней так, как ты работал с xDb в своём коде. Не забудь только выполнить для неё xDb.Dispose();
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 19
  • Карма: 0
Спасибо, пробую.

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

  • ADN OPEN
  • Сообщений: 19
  • Карма: 0
Для первого случая ситуация следующая.
Добавил в код Ваши рекомендации.
Код - C# [Выбрать]
  1. public void Action()
  2.                 {
  3.                         var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  4.                         var db = doc.Database;
  5.  
  6.                         using (var trans = db.TransactionManager.StartTransaction())
  7.                         {
  8.                                 var bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
  9.                                 var btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
  10.                                
  11.                                 foreach (var objId in btr)
  12.                                 {
  13.                                         using (var ent = (Entity)trans.GetObject(objId, OpenMode.ForRead))
  14.                                         {
  15.                                                 try
  16.                                                 {
  17.                                                         var bref = ent as BlockReference;
  18.                                                         if (bref != null)
  19.                                                         {
  20.                                                                
  21.                                                                 // Получаем BlockTableRecord внешней ссылки
  22.                                                                 var btrBref = (BlockTableRecord)trans.GetObject(bref.BlockTableRecord, OpenMode.ForRead);
  23.  
  24.                                                                 if (!btrBref.IsFromExternalReference)
  25.                                                                 {
  26.                                                                         return;
  27.                                                                 }
  28.  
  29.                                                                 var xDB = btrBref.GetXrefDatabase(false);
  30.                                                                 xDB.RestoreOriginalXrefSymbols();
  31.  
  32.                                                                 // открываем транзакцию внешней базы для получения объектов
  33.                                                                 using (var transRef = xDB.TransactionManager.StartTransaction())
  34.                                                                 {
  35.                                                                         // Внешняя база блока
  36.                                                                         var xBT = transRef.GetObject(xDB.BlockTableId, OpenMode.ForRead) as BlockTable;
  37.                                                                         var xBTR = transRef.GetObject(xBT[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
  38.  
  39.                                                                         // Создаем и заполняем коллекцию id'шников
  40.                                                                         var idColl = new ObjectIdCollection();
  41.                                                                         foreach (var objid in xBTR)
  42.                                                                         {
  43.                                                                                 idColl.Add(objid);
  44.                                                                         }
  45.  
  46.                                                                         var iMap = new IdMapping();
  47.                                                                         xDB.WblockCloneObjects(idColl, db.CurrentSpaceId, iMap, DuplicateRecordCloning.Ignore, false);
  48.                                                                 }
  49.  
  50.                                                                 xDB.RestoreForwardingXrefSymbols();
  51.                                                                 bref.Visible = false;
  52.                                                         }
  53.                                                 }
  54.                                                 catch (Exception e)
  55.                                                 {
  56.                                                 }
  57.                                         }
  58.                                 }
  59.  
  60.                                 trans.Commit();
  61.                         }
  62.                 }
  63.  

При запуске код работает без ошибок. Но объекты вообще не копируются.



Во втором случае код выглядит следующим образом.

Код - C# [Выбрать]
  1. public void Action()
  2.                 {
  3.                         var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  4.                         var db = doc.Database;
  5.  
  6.                         using (var trans = db.TransactionManager.StartTransaction())
  7.                         {
  8.                                 var bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForWrite);
  9.                                 var btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
  10.                                
  11.                                 foreach (var objId in btr)
  12.                                 {
  13.                                         using (var ent = (Entity)trans.GetObject(objId, OpenMode.ForWrite))
  14.                                         {
  15.                                                 try
  16.                                                 {
  17.                                                         var bref = ent as BlockReference;
  18.                                                         if (bref != null)
  19.                                                         {
  20.                                                                
  21.                                                                 // Получаем BlockTableRecord внешней ссылки
  22.                                                                 var btrBref = (BlockTableRecord)trans.GetObject(bref.BlockTableRecord, OpenMode.ForWrite);
  23.  
  24.                                                                 if (!btrBref.IsFromExternalReference)
  25.                                                                 {
  26.                                                                         return;
  27.                                                                 }
  28.  
  29.                                                                 using (var xDB = new Database(false, true))
  30.                                                                 {
  31.                                                                         xDB.ReadDwgFile(btrBref.PathName, FileShare.ReadWrite, false, null);
  32.  
  33.                                                                         // открываем транзакцию внешней базы для получения объектов
  34.                                                                         using (var transRef = xDB.TransactionManager.StartTransaction())
  35.                                                                         {
  36.                                                                                 // Внешняя база блока
  37.                                                                                 var xBT = transRef.GetObject(xDB.BlockTableId, OpenMode.ForRead) as BlockTable;
  38.                                                                                 var xBTR = transRef.GetObject(xBT[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
  39.  
  40.                                                                                 // Создаем и заполняем коллекцию id'шников
  41.                                                                                 var idColl = new ObjectIdCollection();
  42.                                                                                 foreach (var objid in xBTR)
  43.                                                                                 {
  44.                                                                                         idColl.Add(objid);
  45.                                                                                 }
  46.  
  47.                                                                                 var iMap = new IdMapping();
  48.                                                                                 xDB.WblockCloneObjects(idColl, db.CurrentSpaceId, iMap, DuplicateRecordCloning.Ignore, false);
  49.                                                                         }
  50.                                                                 }
  51.  
  52.                                                                 bref.Visible = false;
  53.                                                         }
  54.                                                 }
  55.                                                 catch (Exception e)
  56.                                                 {
  57.                                                 }
  58.                                         }
  59.                                 }
  60.  
  61.                                 trans.Commit();
  62.                         }
  63.                 }
  64.  
Пришлось открыть объекты на запись, так как вылетал эксепшн прир сокрытии блока.
Копирование объектов происходит, но без COGOPOINT'ов. Думаю, что может создание нового COGOPOINT на основе старого.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Ты в обоих случаях не выполнил условие, что WblockCloneObjects должно вызваться вне транзакции. И кроме того во внутренних транзакциях я не увидел вызова Commit(). Впрочем, наверное Дмитрий Загорулькин был прав, говоря что так копировать нельзя и что нужно создавать объекты средствами Civil 3D.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение