При копировании объектов из одного dwg файла в другой размеры не копируются

Автор Тема: При копировании объектов из одного dwg файла в другой размеры не копируются  (Прочитано 18721 раз)

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

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Реализовал все рекомендации Александра Ривилиса (во всяком случае я так считаю)
Это тебе только кажется.
1. Ты используешь acBlkTblRecCurrentDoc.ObjectId в том месте, где первая транзакция завершена и acBlkTblRecCurrentDoc уже закрыт. Так что использовать acBlkTblRecCurrentDoc.ObjectId нельзя.
2. Во второй транзакции не нужно (открывать) ни acBlkTblCurrentDoc ни acBlkTblRecCurrentDoc. Всё что тебе нужно есть в acIdMap.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Петренко ДмитрийАвтор темы

  • ADN OPEN
  • Сообщений: 11
  • Карма: 0
  • cad-pro.ru
    • Полезные приемы работы в AutoCAD
Чем дальше в лес тем толще партизаны. :)
Может я чего то не понимаю (скорее всего), но если "acBlkTblRecCurrentDoc уже закрыт" почему в текущий активный чертеж копируются из коллекции все объекты кроме размеров?
Как я уже писал после замены acBlkTblRecCurrentDoc.objectid на currentDb.CurrentSpaceId абсолютно ничего не изменилось.
По поводу acIdMap мне разбираться еще день или два поэтому пока что есть то есть.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Как я уже писал после замены acBlkTblRecCurrentDoc.objectid на currentDb.CurrentSpaceId абсолютно ничего не изменилось.
Тебе очень повезло. Мог словить в лучшем случае Exception, в худшем Fatal Error. Нельзя использовать объекты/примитивы открытые в транзакции вне этой транзакции.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Код - C# [Выбрать]
  1. using System.IO;
  2. using System.Windows.Forms;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.EditorInput;
  6. using Autodesk.AutoCAD.Runtime;
  7.  
  8. namespace CopyDimensions
  9. {
  10.     public class Class1
  11.     {
  12.         [CommandMethod("test")]
  13.         public void Test()
  14.         {
  15.             try
  16.             {
  17.                 Document Doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  18.                 Database currentDb = Doc.Database;
  19.                 Editor ed = Doc.Editor;
  20.                 Database sourceDb = new Database(false, true);
  21.                 var acObjIdCollsource = new ObjectIdCollection();
  22.                 var opf = new Autodesk.AutoCAD.Windows.OpenFileDialog("title", "", "dwg", "name",
  23.                     Autodesk.AutoCAD.Windows.OpenFileDialog.OpenFileDialogFlags.AllowAnyExtension);
  24.                 if (opf.ShowDialog() == DialogResult.OK)
  25.                 {
  26.                     sourceDb.ReadDwgFile(opf.Filename, FileShare.Read, true, "");
  27.                 }
  28.  
  29.                 using (var tr = sourceDb.TransactionManager.StartTransaction())
  30.                 {
  31.                     var acBlkTblCurrentDoc = tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false, false) as BlockTable;
  32.                     var acBlkTblRecCurrentDoc = tr.GetObject(acBlkTblCurrentDoc[BlockTableRecord.ModelSpace], OpenMode.ForRead, false, true) as BlockTableRecord;
  33.                     foreach (ObjectId ObjId in acBlkTblRecCurrentDoc)
  34.                     {
  35.                         acObjIdCollsource.Add(ObjId);
  36.                     }
  37.                     tr.Commit();
  38.                 }
  39.                 using (var tr = currentDb.TransactionManager.StartTransaction())
  40.                 {
  41.                     var bt = tr.GetObject(currentDb.BlockTableId, OpenMode.ForRead) as BlockTable;
  42.                     var btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
  43.                     IdMapping acIdMap = new IdMapping();
  44.                     sourceDb.WblockCloneObjects(
  45.                         acObjIdCollsource,
  46.                         btr.ObjectId,
  47.                         acIdMap, DuplicateRecordCloning.Replace, false);
  48.                     tr.Commit();
  49.                 }
  50.             }
  51.             catch (Exception exception)
  52.             {
  53.                 Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(exception.Message + exception.StackTrace);
  54.             }
  55.         }
  56.     }
  57. }

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Еще могу порекомендовать вынести sourceDb.WblockCloneObjects(...) за рамки транзакции.
Как оказалось - плохой совет ))

Отмечено как Решение Александр Ривилис 23-01-2017, 02:46:06

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Еще могу порекомендовать вынести sourceDb.WblockCloneObjects(...) за рамки транзакции.
Как оказалось - плохой совет ))
Если ты думаешь, что пример из справки - это истина в последней инстанции, то ты ошибаешься. И на этом форуме неоднократно наталкивались на ошибки в примерах и проблемы с WblockCloneObjects внутри транзакций.

Не люблю VB.NET, но решил проверить. AutoCAD 2010 у меня нет, поэтому проверял в AutoCAD 2012.

Код - vb.net [Выбрать]
  1. Imports System
  2. Imports Autodesk.AutoCAD.Runtime
  3. Imports Autodesk.AutoCAD.ApplicationServices
  4. Imports Autodesk.AutoCAD.DatabaseServices
  5. Imports Autodesk.AutoCAD.Geometry
  6. Imports Autodesk.AutoCAD.EditorInput
  7.  
  8. <Assembly: CommandClass(GetType(Rivilis.MyCommands))>
  9.  
  10. Namespace Rivilis
  11.   Public Class MyCommands
  12.  
  13.     <CommandMethod("WBTEST", CommandFlags.Modal)>
  14.     Public Sub WbTest()
  15.       Using sourceDb As Database = New Database(False, False)
  16.         Dim acObjIdCollsource As ObjectIdCollection = New ObjectIdCollection()
  17.         Using tr As Transaction = sourceDb.TransactionManager.StartTransaction()
  18.           sourceDb.ReadDwgFile("C:\TEMP\test.dwg", FileOpenMode.OpenForReadAndReadShare, True, "")
  19.           sourceDb.CloseInput(True)
  20.           Dim acBlkTblSourceDoc As BlockTable
  21.           acBlkTblSourceDoc = tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead)
  22.           Dim acBlkTblRecSourceDoc As BlockTableRecord
  23.           acBlkTblRecSourceDoc = tr.GetObject(acBlkTblSourceDoc(BlockTableRecord.ModelSpace), OpenMode.ForRead)
  24.           For Each ObjId As ObjectId In acBlkTblRecSourceDoc
  25.             acObjIdCollsource.Add(ObjId)
  26.           Next
  27.           tr.Commit()
  28.         End Using
  29.         Dim Doc As Document = Application.DocumentManager.MdiActiveDocument
  30.         Dim currentDb As Database = Doc.Database
  31.         Dim ed As Editor = Doc.Editor
  32.  
  33.         Using acLckDocCur As DocumentLock = Doc.LockDocument()
  34.  
  35.           Dim bobject As Entity = Nothing
  36.           Dim idModel As ObjectId = ObjectId.Null
  37.           Using tr = Doc.TransactionManager.StartTransaction()
  38.             Dim acBlkTblCurrentDoc As BlockTable =
  39.               tr.GetObject(currentDb.BlockTableId, OpenMode.ForRead)
  40.             idModel = acBlkTblCurrentDoc(BlockTableRecord.ModelSpace)
  41.             Dim acBlkTblRecCurrentDoc As BlockTableRecord =
  42.               tr.GetObject(idModel, OpenMode.ForRead)
  43.             For Each ObjId As ObjectId In acBlkTblRecCurrentDoc
  44.               bobject = tr.GetObject(ObjId, OpenMode.ForWrite)
  45.               bobject.Erase(True)
  46.             Next
  47.             tr.Commit()
  48.           End Using
  49.  
  50.           Dim acIdMap As IdMapping = New IdMapping()
  51.  
  52.           sourceDb.WblockCloneObjects(acObjIdCollsource, idModel, acIdMap, DuplicateRecordCloning.Replace, False)
  53.  
  54.           Using tr = Doc.TransactionManager.StartTransaction()
  55.             For Each pair As IdPair In acIdMap
  56.               Dim id As ObjectId = pair.Value
  57.               If (id.ObjectClass.IsDerivedFrom(RXClass.GetClass(GetType(Dimension)))) Then
  58.                 Dim d As Dimension = tr.GetObject(id, OpenMode.ForWrite)
  59.                 d.RecomputeDimensionBlock(True)
  60.               End If
  61.             Next
  62.             tr.Commit()
  63.           End Using
  64.         End Using
  65.       End Using
  66.     End Sub
  67.   End Class
  68.  
  69. End Namespace

Копирует всё, в том числе и размеры и что наиболее важно - размеры внутри блоков. Размеры в пространстве модели должно было копировать и так, без RecomputeDimensionBlock. Во всяком случае как раз недавно такая проблема всплыла в ObjectARX: https://forums.autodesk.com/t5/objectarx/why-the-dimensions-not-show/td-p/6777534
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

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

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Если ты думаешь, что пример из справки - это истина в последней инстанции, то ты ошибаешься. И на этом форуме неоднократно наталкивались на ошибки в примерах и проблемы с WblockCloneObjects внутри транзакций.
Я немного про другое имел ввиду. Чтобы получить acBlkTblRecCurrentDoc.ObjectId все равно нужно открывать транзакцию - вот я про что. Просто я не учел, что при этом WblockCloneObjects можно вынести за транзакцию. У меня где-то на подкороче осталось "Что произошло в транзакции - должно остаться в транзакции"  :D

Оффлайн Петренко ДмитрийАвтор темы

  • ADN OPEN
  • Сообщений: 11
  • Карма: 0
  • cad-pro.ru
    • Полезные приемы работы в AutoCAD
Ура, я это сделал, конечно не без помощи Александра Ривилиса, а именно пока не заменил свою транзакцию, в которой находится RecomputeDimensionBlock(True) на ту, которая приведена в примере Александра Ривилиса ничего не менялось, независимо от того где находится WblockCloneObjects в транзакции или вне ее.
И еще относительно последнего кода приведенного Александра Ривилиса при к его просмотре засомневался в строчке Using sourceDb As Database = New Database(False, False), но решил тупо проверить акад выдал сообщение NoInputFiler.
Заменил ее на Using sourceDb As Database = New Database(False, True) все заработало.

Оффлайн Петренко ДмитрийАвтор темы

  • ADN OPEN
  • Сообщений: 11
  • Карма: 0
  • cad-pro.ru
    • Полезные приемы работы в AutoCAD
Раз уж зашел разговор, еще вопрос.
При копировании некоторых чертежей выдается сообщение eNotAllowedForThisProxy и ничего не копируется, насколько я понимаю не получается копировать объекты AutocadMechanical т.е. блоки с атрибутами так как именно оно там присутствуют в отличие от других чертежей. Возможно ли их скопировать? Какой для этого есть метод? 

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Раз уж зашел разговор, еще вопрос.
При копировании некоторых чертежей выдается сообщение eNotAllowedForThisProxy и ничего не копируется, насколько я понимаю не получается копировать объекты AutocadMechanical т.е. блоки с атрибутами так как именно оно там присутствуют в отличие от других чертежей. Возможно ли их скопировать? Какой для этого есть метод? 
Если не загружены модули AutoCAD Mechanical, то его объекты/примитивы будут прокси и соответственно они не будут копироваться. Поэтому попробуй перед копированием загрузить соответствующие arx/dbx-файлы (какие именно - ищи сам).
И еще относительно последнего кода приведенного Александра Ривилиса при к его просмотре засомневался в строчке Using sourceDb As Database = New Database(False, False), но решил тупо проверить акад выдал сообщение NoInputFiler.
Заменил ее на Using sourceDb As Database = New Database(False, True) все заработало.
Это видимо баг AutoCAD 2010 (или Mechanical - если у тебя не чистый AutoCAD).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн exilerus

  • ADN OPEN
  • Сообщений: 46
  • Карма: 2
Нашел информацию о проблеме тут. Спасибо!

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

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

Оффлайн exilerus

  • ADN OPEN
  • Сообщений: 46
  • Карма: 2
Да вот как раз об этой. Не производился пересчет размеров при копировании объектов с другого чертежа.