26/09/2014
Расчленение вложенных блоков с помощью .NET
Некоторое время назад я написал статью о том, как использовать метод Entity.Explode() чтобы получить те же результаты, что и в команде РАСЧЛЕНИ (_EXPLODE). В комментариях я получил замечание, что с этим лучше справляется метод BlockReference.ExplodeToOwnerSpace.Мне захотелось использовать этот же метод для расчленения вложенных блоков, но так как BlockReference.ExplodeToOwnerSpace() не возвращает список созданных объектов, мне пришлось приспособить событие Database.ObjectAppended для этого и для рекурсивного вызова моей функции ExplodeBlock() со всеми вновь созданными блоками. Мы можем так же удалить оригинальный примитив (или примитивы если функция вызвана рекурсивно).
Вот код на C#:
Код - C#: [Выделить]
- using Autodesk.AutoCAD.ApplicationServices;
- using Autodesk.AutoCAD.DatabaseServices;
- using Autodesk.AutoCAD.EditorInput;
- using Autodesk.AutoCAD.Runtime;
- namespace Explosions
- {
- public class Commands
- {
- [CommandMethod("EB")]
- public void ExplodeBock()
- {
- var doc = Application.DocumentManager.MdiActiveDocument;
- if (doc == null)
- return;
- var ed = doc.Editor;
- var db = doc.Database;
- // Просим пользователя выбрать блок
- var peo = new PromptEntityOptions("\nВыберите блок для расчленения: ");
- peo.SetRejectMessage("Это должен быть блок.");
- peo.AddAllowedClass(typeof(BlockReference), false);
- var per = ed.GetEntity(peo);
- if (per.Status != PromptStatus.OK)
- return;
- using (var tr = db.TransactionManager.StartTransaction())
- {
- // Вызываем рекурсивно функцию расчленения
- // с блоком верхнего уровня
- // (можно передать false в качестве 4-го параметра
- // если не хотите удалять исходные примитивы)
- ExplodeBlock(tr, db, per.ObjectId);
- tr.Commit();
- }
- }
- private void ExplodeBlock(
- Transaction tr, Database db, ObjectId id, bool erase = true
- )
- {
- // Открываем вставку блока – для расчленения достаточно возможности
- // открыть «для чтения»т.к. эта операция не меняет исходный примитив
- var br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
- // Будем собирать созданные BlockReferences
- var toExplode = new ObjectIdCollection();
- // Создаем обработчик для получения вложенных вставок блока
- ObjectEventHandler handler =
- (s, e) =>
- {
- if (e.DBObject is BlockReference)
- {
- toExplode.Add(e.DBObject.ObjectId);
- }
- };
- // Добавляем обработчик перед вызовом расчленения
- // удаляем сразу после этого
- db.ObjectAppended += handler;
- br.ExplodeToOwnerSpace();
- db.ObjectAppended -= handler;
- // Проходимся по всем полученным вставкам блока и рекурсивно
- // расчленяем их
- foreach (ObjectId bid in toExplode)
- {
- ExplodeBlock(tr, db, bid, erase);
- }
- // Нужно теперь очистить список расчлененных вставок блоков
- toExplode.Clear();
- // Чтобы повторить поведение команды РАСЧЛЕНИ
- // необходимо удалить исходный примитив
- if (erase)
- {
- br.UpgradeOpen();
- br.Erase();
- br.DowngradeOpen();
- }
- }
- }
- }
Обсуждение: http://adn-cis.org/forum/index.php?topic=982
Опубликовано 26.09.2014Отредактировано 26.09.2014 в 12:12:50