Как скопировать несколько блоков

Автор Тема: Как скопировать несколько блоков  (Прочитано 5705 раз)

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

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

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

  • ADN OPEN
  • Сообщений: 41
  • Карма: 0
Подскажите пожалуйста, как скопировать и потом вставить несколько блоков на одном и том же рисунке.

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Как скопировать несколько блоков
« Ответ #1 : 15-10-2019, 18:47:06 »
Да, собственно, так же, как и любой другой объект чертежа: https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2016/ENU/AutoCAD-NET/files/GUID-7EF7D821-473B-4F05-A98C-AEEC9F86A871-htm.html

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как скопировать несколько блоков
« Ответ #2 : 15-10-2019, 19:41:04 »
Пожалуй лучше при помощи Database.DeepCloneObjects  (если в пределах одного чертежа) или Database.WblockCloneObjects (если между разными чертежами).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Как скопировать несколько блоков
« Ответ #3 : 15-10-2019, 19:53:55 »
Ещё интересный вариант нашёл, но это для специфической ситуации: https://adndevblog.typepad.com/autocad/2012/04/clone-the-dynamic-block-in-the-same-drawing-file.html
В принципе, как ответ под такую формулировку вопроса попадает   :)

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

  • ADN OPEN
  • Сообщений: 41
  • Карма: 0
Re: Как скопировать несколько блоков
« Ответ #4 : 15-10-2019, 20:18:24 »
Спасибо! Дмитрий, мне ваш первый вариант больше подходит кажется, странно, что он у меня не находился почему то. Александр , не знаю что это такое Database.DeepCloneObjects, а можно какую небудь ссылочку с использовнием этой штуки.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как скопировать несколько блоков
« Ответ #5 : 15-10-2019, 21:21:35 »
Александр , не знаю что это такое Database.DeepCloneObjects, а можно какую небудь ссылочку с использовнием этой штуки.
Не пользуешься ты поиском, а жаль. Вот пример ссылки: https://adn-cis.org/forum/index.php?topic=3086.0
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как скопировать несколько блоков
« Ответ #6 : 15-10-2019, 21:24:48 »
Ещё интересный вариант нашёл, но это для специфической ситуации: https://adndevblog.typepad.com/autocad/2012/04/clone-the-dynamic-block-in-the-same-drawing-file.html
В принципе, как ответ под такую формулировку вопроса попадает   :)
Это будет копирование с созданием новых блоков (с новыми именами). Здесь в постановке задачи об этом не говорится. Я так понял, что просто нужно размножить вставки блока, т.е. все они должны ссылаться на одну и ту же BlockTableRecord.
« Последнее редактирование: 15-10-2019, 21:55:57 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 41
  • Карма: 0
Re: Как скопировать несколько блоков
« Ответ #7 : 18-10-2019, 18:04:48 »
Ребят , подскажите что не так, ошибок нет, но копию блока не делает
Код - C# [Выбрать]
  1.  using (Transaction acTrans = acActiveDoc.TransactionManager.StartTransaction())
  2.                     {
  3.                         foreach (ObjectId blkId in idArray)
  4.                         {
  5.                             BlockTable acBlkTbl = (BlockTable)acTrans.GetObject(db.BlockTableId, OpenMode.ForWrite);
  6.                             BlockTableRecord btr = (BlockTableRecord)acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
  7.                             BlockReference br = (BlockReference)acTrans.GetObject(blkId, OpenMode.ForWrite);
  8.                             BlockReference newBr = (BlockReference)br.Clone();
  9.                             newBr.Position = new Point3d(10, 10, 10);
  10.                             btr.AppendEntity(newBr);
  11.                             acTrans.AddNewlyCreatedDBObject(newBr, true);
  12.                         }
  13.                         acTrans.Commit();
  14.                     }

Отмечено как Решение serhiy79 21-10-2019, 15:53:54

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Как скопировать несколько блоков
« Ответ #8 : 18-10-2019, 18:28:50 »
На первый взгляд, прямо фатальных ошибок нет. Но!
1. Открытие блока, таблицы блоков и модели надо вынести из цикла. Или открытие-закрытие транзакции поместить в цикл.
2. Из этого всего на запись (ForWrite) надо открывать только модель.
3. Для получения ObjectId модели не надо открывать таблицу блоков, есть специальный метод для этого: SymbolUtilityServices.GetBlockModelSpaceId.
Я проверил, возможно ли вообще копировать блоки таким способом. У меня получилось.
Код:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Geometry;
  5. using Autodesk.AutoCAD.Runtime;
  6.  
  7. namespace AcadTest2020
  8. {
  9.     public class CopyBlockTest
  10.     {
  11.         [CommandMethod("CopyBlockTestRun")]
  12.         public void Run()
  13.         {
  14.             Document doc = Application.DocumentManager.MdiActiveDocument;
  15.             Database db = doc.Database;
  16.             Editor ed = doc.Editor;
  17.  
  18.             PromptEntityResult res = ed.GetEntity("\nSelect block reference: ");
  19.             if (res.Status != PromptStatus.OK) return;
  20.             ObjectId blkId = res.ObjectId;
  21.  
  22.             PromptPointResult insPtRes = ed.GetPoint("\nSelect location: ");
  23.             if (insPtRes.Status != PromptStatus.OK) return;
  24.             Point3d pos = insPtRes.Value.TransformBy(ed.CurrentUserCoordinateSystem);
  25.  
  26.             ObjectId mSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(db);
  27.  
  28.             using (Transaction acTrans = db.TransactionManager.StartTransaction())
  29.             {
  30.                 BlockReference br = (BlockReference)acTrans.GetObject(blkId, OpenMode.ForRead);
  31.                 BlockReference newBr = (BlockReference)br.Clone();
  32.                 newBr.Position = pos;
  33.  
  34.                 BlockTableRecord btr = (BlockTableRecord)acTrans.GetObject(mSpaceId, OpenMode.ForWrite);
  35.                 btr.AppendEntity(newBr);
  36.                 acTrans.AddNewlyCreatedDBObject(newBr, true);
  37.                 acTrans.Commit();
  38.             }
  39.         }
  40.     }
  41. }
  42.  
Видео:

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

  • ADN OPEN
  • Сообщений: 41
  • Карма: 0
Re: Как скопировать несколько блоков
« Ответ #9 : 18-10-2019, 19:45:21 »
Спасибо большое Дмитрий!

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 405
  • Карма: 77
  • Skype: vildar82
Re: Как скопировать несколько блоков
« Ответ #10 : 03-02-2020, 18:48:05 »
А как сделать копию определения блока в чертеже?

1. DeepCloneObject нельзя использовать? Ошибка - InvalidOwnerObject  :-[
Код - C# [Выбрать]
  1.    var ids = new ObjectIdCollection(new[] { idBTR });
  2.    db.DeepCloneObjects(ids, idBlockTableOwner, map, false);
Передаю database.BlockTableId - как owner контейнер для копируемого блока.
Как он имя блока при этом разрулит. Непонятно.

2. WblockCloneObjects - нельзя использовать для копирования объектов в одном чертеже.

3. Через Wblock остается попробовать:
Код - C# [Выбрать]
  1. copyId = db.Insert("DynamicBlockCopy", temDB, true);
Это работает! Нужно понаблюдать  ;D

4. Ну и по примитивам копировать - худший вариант - там всякая динамика полезет  :P

5. Clone? Клонировать определение блока, поменять имя, добавить в чертеж. Подвох, скорее всего, обеспечен - типа словарь блока потеряется, еще что-нибудь  >:(

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Как скопировать несколько блоков
« Ответ #11 : 03-02-2020, 19:09:51 »
3. Через Wblock остается попробовать:
Я так понимаю, что это отсюда? : https://adndevblog.typepad.com/autocad/2012/04/clone-the-dynamic-block-in-the-same-drawing-file.html
Это работает! Нужно понаблюдать 
Так вроде нормальный способ! Единственное - непонятно что будет, если такое имя блока уже есть в чертеже. Я бы заранее формировал гарантированно уникальное имя. А так, думаю, способ вполне рабочий. Я когда-то так и вручную (не программно) динамические блоки в отдельные файлы переносил с помощью команды WBLOCK. Была идея создать библиотеку блоков, где каждый блок в отдельном чертеже. Забавно было потом открывать такой чертёж - там динамические параметры блока были прямо в модели :). Потом передумал в пользу одного файла со всеми блоками.
5. Clone? Клонировать определение блока, поменять имя, добавить в чертеж. Подвох, скорее всего, обеспечен - типа словарь блока потеряется, еще что-нибудь 
А у BlockTableRecord не должно быть такого метода. Это только для Entity. Наврал. У любого RXObject. Ну попробуй :)

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как скопировать несколько блоков
« Ответ #12 : 03-02-2020, 19:57:11 »
4. Ну и по примитивам копировать - худший вариант - там всякая динамика полезет 
Создаёшь новую пустую BlockTableRecord и в неё при помощи db.DeepCloneObjects копируешь содержимое исходного блока.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 41
  • Карма: 0
Re: Как скопировать несколько блоков
« Ответ #13 : 03-02-2020, 21:52:32 »
Моя финальная версия для копирования и вставки блока
Код - C# [Выбрать]
  1.  public static  void CopyMove(ObjectId[] objectIds, Vector3d disp)
  2.         {
  3.             Document doc = AcApSrvApp.DocumentManager.MdiActiveDocument;
  4.             Database db = doc.Database;
  5.          
  6.             using (Transaction tr = db.TransactionManager.StartTransaction())
  7.             {
  8.                 foreach (ObjectId Id in objectIds)
  9.                 {
  10.                     Entity ent = (Entity)tr.GetObject(Id, OpenMode.ForRead);
  11.                     //ObjectId ownerId = ent.OwnerId;
  12.                     IdMapping IdMap = new IdMapping();
  13.                     ObjectIdCollection idsColl = new ObjectIdCollection(new ObjectId[] { Id });
  14.                     //db.DeepCloneObjects(idsColl, ownerId, IdMap, false);
  15.                     db.DeepCloneObjects(idsColl, db.CurrentSpaceId, IdMap, false);
  16.  
  17.                     foreach (IdPair pair in IdMap)
  18.                     {
  19.                         if (pair.IsPrimary)
  20.                         {
  21.                             Entity en = tr.GetObject(pair.Value, OpenMode.ForWrite, false, true) as Entity;
  22.  
  23.                             //Get current layer
  24.                             LayerTable LayerTbl = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
  25.                             LayerTableRecord LayerTblRec = tr.GetObject(LayerTbl[en.Layer], OpenMode.ForWrite) as LayerTableRecord;
  26.  
  27.                             //If block on locked layer, don't copy it
  28.                             if (!LayerTblRec.IsLocked)
  29.                             {
  30.                                 if (en != null)
  31.                                 {
  32.                                     en.TransformBy(Matrix3d.Displacement(disp));
  33.                                     newobjectIds.Add(en.Id);
  34.                                 }
  35.                             }
  36.                         }
  37.                     }
  38.  
  39.                 }
  40.                 tr.Commit();
  41.             }
  42.         }
  43.  

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 405
  • Карма: 77
  • Skype: vildar82
Re: Как скопировать несколько блоков
« Ответ #14 : 04-02-2020, 08:56:18 »
Моя финальная версия для копирования и вставки блока
А почему бы не клонировать все объекты одним вызовом DeepCloneObjects?