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

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

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

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

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

  • ADN OPEN
  • Сообщений: 11
  • Карма: 0
  • cad-pro.ru
    • Полезные приемы работы в AutoCAD
При копировании объектов из одного dwg файла в другой размеры не копируются. Почему? Насколько я понимаю они тоже объекты.
Текст кода ниже.
Заранее спасибо за ответ.

Код - Visual Basic [Выбрать]
  1. Dim sourceDb As Database = New Database(False, True)
  2.         Dim acObjIdCollsource As ObjectIdCollection = New ObjectIdCollection()
  3.         Try
  4.             Using tr As Transaction = sourceDb.TransactionManager.StartTransaction()
  5.                 sourceDb.ReadDwgFile(Me.ListBox1.SelectedItem, FileOpenMode.OpenForReadAndReadShare, True, "")
  6.                 sourceDb.CloseInput(True)
  7.                 Dim acBlkTblSourceDoc As BlockTable
  8.                 acBlkTblSourceDoc = tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, False, False)
  9.                 '' Open the Block table record Model space for read
  10.                Dim acBlkTblRecSourceDoc As BlockTableRecord
  11.                 acBlkTblRecSourceDoc = tr.GetObject(acBlkTblSourceDoc(BlockTableRecord.ModelSpace), OpenMode.ForRead, False, True)
  12.                 For Each ObjId As ObjectId In acBlkTblRecSourceDoc
  13.                     acObjIdCollsource.Add(ObjId)
  14.                 Next
  15.                 tr.Commit()
  16.  
  17.             End Using
  18.  
  19.             Dim Doc As Document = Application.DocumentManager.MdiActiveDocument
  20.             Dim currentDb As Database = Doc.Database
  21.             Dim ed As Editor = Doc.Editor
  22.             Using acLckDocCur As DocumentLock = Doc.LockDocument()
  23.                 Using tr = Doc.TransactionManager.StartTransaction()
  24.                     '' Open the Block table for read
  25.                    Dim acBlkTblCurrentDoc As BlockTable
  26.                     acBlkTblCurrentDoc = tr.GetObject(currentDb.BlockTableId, OpenMode.ForWrite, False, False)
  27.                     '' Open the Block table record Model space for read
  28.                    Dim acBlkTblRecCurrentDoc As BlockTableRecord
  29.                     acBlkTblRecCurrentDoc = tr.GetObject(acBlkTblCurrentDoc(BlockTableRecord.ModelSpace), OpenMode.ForWrite, False, True)
  30.                     '' Clone the objects to the new database
  31.                    Dim bobject As Entity = Nothing
  32.                     For Each ObjId As ObjectId In acBlkTblRecCurrentDoc
  33.                         bobject = tr.GetObject(ObjId, OpenMode.ForWrite, False, True)
  34.                         bobject.Erase(True)
  35.                     Next
  36.                     Dim acIdMap As IdMapping = New IdMapping()
  37.                     sourceDb.WblockCloneObjects(acObjIdCollsource, acBlkTblRecCurrentDoc.ObjectId, acIdMap, DuplicateRecordCloning.Replace, False)
  38.                     currentDb.UpdateExt(True)
  39.                     '' Save the copied objects to the database
  40.                    tr.Commit()
  41.                 End Using
  42.                 acObjIdCollsource.Dispose()
  43.                 '' Unlock the document
  44.            End Using
  45.  
« Последнее редактирование: 22-01-2017, 12:42:17 от Александр Ривилис »

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Копирование нужно делать методом sourceDb.WblockCloneObjects. Вот пример.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
dmitry15,
Приветствую на форуме!
Прочитай у меня в подписи как следует форматировать код на форуме и следуй в дальнейшем этому правилу.
При копировании объектов из одного dwg файла в другой размеры не копируются. Почему?
В действительности они копируются. Но для них (после копирования) нужно выполнить метод Dimension.RecomputeDimensionBlock
Ну и в добавок currentDb.BlockTableId и acBlkTblCurrentDoc(BlockTableRecord.ModelSpace) не нужно открывать ForWrite, а вполне достаточно ForRead, так как ни то ни другое не модифицируется.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

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

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

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

По рекомендациям Александра Ривилиса
- если несложно можно поподробней про Dimension.RecomputeDimensionBlock т.к. в инете скудная информация, попробовал использовать в коде под AutoCad 2010 вариант RecomputeDimensionBlock у Dimension отсутствует. Если что не судите строго так как только начинаю программировать под AutoCad.
- currentDb.BlockTableId и acBlkTblCurrentDoc(BlockTableRecord.ModelSpace) открыты для записи, так как в файле в который копирую объекты перед этим те объекты, что там находятся я удаляю.
-  попробовал вынести за транзакцию sourceDb.WblockCloneObjects(...) компилятор ругается, что переменная  acBlkTblRecCurrentDoc не объявлена, может что то не то делаю.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
попробовал использовать в коде под AutoCad 2010 вариант RecomputeDimensionBlock у Dimension отсутствует
Плохо искал. Проверил в AutoCAD 2010 - есть такой метод:
Код - C# [Выбрать]
  1. // Autodesk.AutoCAD.DatabaseServices.Dimension
  2. public void RecomputeDimensionBlock([MarshalAs(UnmanagedType.U1)] bool forceUpdate);

- currentDb.BlockTableId и acBlkTblCurrentDoc(BlockTableRecord.ModelSpace) открыты для записи, так как в файле в который копирую объекты перед этим те объекты, что там находятся я удаляю.
Ну и что? Ты видимо не понимаешь. Факт удаления объекта никак не связан ни с BlockTable, ни с BlockTableRecord. Открывать их на запись нужно только тогда, когда непосредственно они модифицируются.
-  попробовал вынести за транзакцию sourceDb.WblockCloneObjects(...) компилятор ругается, что переменная  acBlkTblRecCurrentDoc не объявлена, может что то не то делаю.
Конечно не определена. Но она и не нужна. Нужен её ObjectId, который нужно было получить в транзакции, а использовать вне транзакции.
« Последнее редактирование: 22-01-2017, 18:23:32 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Копирование нужно делать методом sourceDb.WblockCloneObjects. Вот пример.
Хоть убейте, но я уверен, что когда писал этот ответ, то в вопросе в коде не было WblockCloneObjects! Поэтому и написал. Может старею уже?  :o ;D

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Хоть убейте, но я уверен, что когда писал этот ответ, то в вопросе в коде не было WblockCloneObjects! Поэтому и написал. Может старею уже?  :o ;D
Скорее это всё из-за форматирования (точнее его отсутствия). Ну и из-за "языка гоблинов" (VB.NET), как любит писать Андрей Бушман:)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 11
  • Карма: 0
  • cad-pro.ru
    • Полезные приемы работы в AutoCAD
Реализовал все рекомендации Александра Ривилиса (во всяком случае я так считаю), но результат нулевой, ничего не изменилось, размеров как не было так и нет.
Ниже фрагмент кода, который изменил.

Код - vb.net [Выбрать]
  1.     Dim Doc As Document = Application.DocumentManager.MdiActiveDocument
  2.             Dim currentDb As Database = Doc.Database
  3.             Dim ed As Editor = Doc.Editor
  4.            
  5.             Using acLckDocCur As DocumentLock = Doc.LockDocument()
  6.  
  7.                 Dim acBlkTblCurrentDoc As BlockTable
  8.                 Dim acBlkTblRecCurrentDoc As BlockTableRecord
  9.                 Dim bobject As Entity = Nothing
  10.  
  11.                 Using tr = Doc.TransactionManager.StartTransaction()
  12.                     '' Open the Block table for write
  13.                     acBlkTblCurrentDoc = tr.GetObject(currentDb.BlockTableId, OpenMode.ForWrite, False, False)
  14.                     '' Open the Block table record Model space for write
  15.                     acBlkTblRecCurrentDoc = tr.GetObject(acBlkTblCurrentDoc(BlockTableRecord.ModelSpace), OpenMode.ForWrite, False, True)
  16.                     '' Clone the objects to the new database
  17.                     For Each ObjId As ObjectId In acBlkTblRecCurrentDoc
  18.                         bobject = tr.GetObject(ObjId, OpenMode.ForWrite, False, True)
  19.                         bobject.Erase(True)
  20.                     Next
  21.                     tr.Commit()
  22.                 End Using
  23.  
  24.                 Dim acIdMap As IdMapping = New IdMapping()
  25.                 sourceDb.WblockCloneObjects(acObjIdCollsource, acBlkTblRecCurrentDoc.ObjectId, acIdMap, DuplicateRecordCloning.Replace, False)
  26.  
  27.                 Using tr = Doc.TransactionManager.StartTransaction()
  28.                     '' Open the Block table for read
  29.                     acBlkTblCurrentDoc = tr.GetObject(currentDb.BlockTableId, OpenMode.ForRead, False, False)
  30.                     '' Open the Block table record Model space for read
  31.                     acBlkTblRecCurrentDoc = tr.GetObject(acBlkTblCurrentDoc(BlockTableRecord.ModelSpace), OpenMode.ForRead, False, True)
  32.  
  33.                     For Each ObjId As ObjectId In acBlkTblRecCurrentDoc
  34.                         bobject = tr.GetObject(ObjId, OpenMode.ForRead, False, True)
  35.                         If TypeOf bobject Is Dimension Then
  36.                             Dim dimen As Dimension = bobject
  37.                             dimen.RecomputeDimensionBlock(True)
  38.                             dimen.RecordGraphicsModified(True)
  39.                         End If
  40.                     Next
  41.                     '' Save the copied objects to the database
  42.                     tr.Commit()
  43.                 End Using
  44.  End Using

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
'' Clone the objects to the new database
                    For Each ObjId As ObjectId In acBlkTblRecCurrentDoc
                        bobject = tr.GetObject(ObjId, OpenMode.ForWrite, False, True)
                        bobject.Erase(True)
                    Next
Ну а где копирование???

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

  • ADN OPEN
  • Сообщений: 11
  • Карма: 0
  • cad-pro.ru
    • Полезные приемы работы в AutoCAD
Извиняюсь забыл удалить этот комментарий из кода.
Копирование ниже по коду.

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Копирование ниже по коду.
Я к тому, что Вы в своем коде не "наполняете" коллекцию acObjIdCollsource. В первой транзакции Вы только удаляете объекты

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

  • ADN OPEN
  • Сообщений: 11
  • Карма: 0
  • cad-pro.ru
    • Полезные приемы работы в AutoCAD
Наполнение коллекции можно посмотреть в коде который привел в начале этой темы.
Сейчас я выложил только фрагмент, который менял по рекомендациям.

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Поменял это:
sourceDb.WblockCloneObjects(acObjIdCollsource, acBlkTblRecCurrentDoc.ObjectId, acIdMap, DuplicateRecordCloning.Replace, False)
на это:
Код - vb.net [Выбрать]
  1. sourceDb.WblockCloneObjects(acObjIdCollsource, currentDb.CurrentSpaceId, acIdMap, DuplicateRecordCloning.Replace, false);
Копирует и даже RecomputeDimensionBlock не нужно

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

  • ADN OPEN
  • Сообщений: 11
  • Карма: 0
  • cad-pro.ru
    • Полезные приемы работы в AutoCAD
Проверил у себя, не помогло, никаких изменений.
А разве currentDb.CurrentSpaceId и acBlkTblRecCurrentDoc.ObjectId не одно и то же? Просто интересно для собственного развития.