ADN Open CIS
Сообщество программистов Autodesk в СНГ

26/09/2014

Расчленение вложенных блоков с помощью .NET

Некоторое время назад я написал статью о том, как использовать метод Entity.Explode() чтобы получить те же результаты, что и в команде РАСЧЛЕНИ (_EXPLODE). В комментариях я получил замечание, что с этим лучше справляется метод BlockReference.ExplodeToOwnerSpace.

Мне захотелось использовать этот же метод для расчленения вложенных блоков, но так как BlockReference.ExplodeToOwnerSpace() не возвращает список созданных объектов, мне пришлось приспособить событие Database.ObjectAppended для этого и для рекурсивного вызова моей функции ExplodeBlock() со всеми вновь созданными блоками. Мы можем так же удалить оригинальный примитив (или примитивы если функция вызвана рекурсивно).

Вот код на C#:

Код - C#: [Выделить]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;
  5.  
  6. namespace Explosions
  7. {
  8.   public class Commands
  9.   {
  10.     [CommandMethod("EB")]
  11.     public void ExplodeBock()
  12.     {
  13.       var doc = Application.DocumentManager.MdiActiveDocument;
  14.       if (doc == null)
  15.         return;
  16.       var ed = doc.Editor;
  17.       var db = doc.Database;
  18.  
  19.       // Просим пользователя выбрать блок
  20.  
  21.       var peo = new PromptEntityOptions("\nВыберите блок для расчленения: ");
  22.       peo.SetRejectMessage("Это должен быть блок.");
  23.       peo.AddAllowedClass(typeof(BlockReference), false);
  24.  
  25.       var per = ed.GetEntity(peo);
  26.  
  27.       if (per.Status != PromptStatus.OK)
  28.         return;
  29.  
  30.       using (var tr = db.TransactionManager.StartTransaction())
  31.       {
  32.         // Вызываем рекурсивно функцию расчленения
  33.         // с блоком верхнего уровня
  34.         // (можно передать false в качестве 4-го параметра
  35.         // если не хотите удалять исходные примитивы)
  36.  
  37.         ExplodeBlock(tr, db, per.ObjectId);
  38.  
  39.         tr.Commit();
  40.       }
  41.     }
  42.  
  43.     private void ExplodeBlock(
  44.       Transaction tr, Database db, ObjectId id, bool erase = true
  45.     )
  46.     {
  47.       // Открываем вставку блока – для расчленения достаточно возможности
  48.       // открыть «для чтения»т.к. эта операция не меняет исходный примитив
  49.  
  50.       var br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
  51.  
  52.       // Будем собирать созданные BlockReferences
  53.  
  54.       var toExplode = new ObjectIdCollection();
  55.  
  56.       // Создаем обработчик для получения вложенных вставок блока
  57.  
  58.       ObjectEventHandler handler =
  59.         (s, e) =>
  60.         {
  61.           if (e.DBObject is BlockReference)
  62.           {
  63.             toExplode.Add(e.DBObject.ObjectId);
  64.           }
  65.         };
  66.  
  67.       // Добавляем обработчик перед вызовом расчленения
  68.       //  удаляем сразу после этого
  69.  
  70.       db.ObjectAppended += handler;
  71.       br.ExplodeToOwnerSpace();
  72.       db.ObjectAppended -= handler;
  73.  
  74.       // Проходимся по всем полученным вставкам блока и рекурсивно
  75.       // расчленяем их
  76.  
  77.       foreach (ObjectId bid in toExplode)
  78.       {
  79.         ExplodeBlock(tr, db, bid, erase);
  80.       }
  81.  
  82.       // Нужно теперь очистить список расчлененных вставок блоков
  83.  
  84.       toExplode.Clear();
  85.  
  86.       // Чтобы повторить поведение команды РАСЧЛЕНИ
  87.       // необходимо удалить исходный примитив
  88.  
  89.       if (erase)
  90.       {
  91.         br.UpgradeOpen();
  92.         br.Erase();
  93.         br.DowngradeOpen();
  94.       }
  95.     }
  96.   }
  97. }

 

Источник: http://through-the-interface.typepad.com/through_the_interface/2014/09/exploding-nested-autocad-blocks-using-net.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=982

Опубликовано 26.09.2014
Отредактировано 26.09.2014 в 12:12:50