Purge в nanoCAD 23+
Понадобилось мне тут поиграться с очисткой файла в нанике. Нуачо, стандартная достаточно вещь, думал я...
Для начала попробовал код от Андрея Бушмана. Только NC так почистил файл, что тупо развалился.
Да и черт с ним, пишу через настолько не любимый мною COM:
1 2 3 4 5 6 | Document doc = Application.DocumentManager.MdiActiveDocument; nanoCAD.Document comDoc = doc.AcadDocument as nanoCAD.Document; for (int i = 0; i < 3; i++) { comDoc.PurgeAll(); } |
Ура? Фигушки! Этот подход не уничтожает пустые тексты и геометрию нулевой длины! Кстати, лисповой vla-purgeall тоже не убирает эту дрянь. Значит, надо проходить по всем описаниям блоков, исключая внешние ссылки, и смотреть что там внутри. На всякий случай: Trans - текущая транзакция, DBase - база текущего чертежа:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | BlockTable blockTable = Trans.GetObject(DBase.BlockTableId, OpenMode.ForRead) as BlockTable; foreach (ObjectId blockDefId in blockTable) { BlockTableRecord blockDef = Trans.GetObject(blockDefId, OpenMode.ForRead) as BlockTableRecord; if (!blockDef.IsFromExternalReference) { foreach (ObjectId entId in blockDef) { Entity ent = Trans.GetObject(entId, OpenMode.ForRead, false, true) as Entity; if (ent != null) { if (ent is Curve curve) { if (curve.GetDistanceAtParameter(curve.EndParam) < Tolerance.Global.EqualPoint) { EraseEntity(curve); } } else if (ent is DBText dbText) { if (string.IsNullOrWhiteSpace(dbText.TextString)) { EraseEntity(dbText); } } else if (ent is MText mText) { if (string.IsNullOrWhiteSpace(mText.Text)) { EraseEntity(mText); } } } } } } |
Я почти выкатил код, но хвала богам, вовремя остановился. А что будет, если в чертеже вдруг окажется, к примеру, таблица nanoCAD? Правильно - ошибка. Потому как MultiCAD-объекты могут быть запросто скастованы в Curve, но при этом массы параметров и методов там не будет от слова совсем. В принципе, есть два варианта. Первый - получать ObjectName для обрабатываемого примитива и фильтровать. Второй - оборачивать все в try-catch.
Я провел несколько экспериментов, вроде бы (именно что вроде бы!) имена пользовательских объектов MultiCAD всегда начинаются с mcs. Но что будет дальше - не знает никто, даже, наверное, сами нанодевы. Так что, несмотря на гарантированные тормоза, я решил обернуть обработку в try-catch:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | private void PurgeCurrentDocument(Database DBase, Transaction Trans) { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; BlockTable blockTable = Trans.GetObject(DBase.BlockTableId, OpenMode.ForRead) as BlockTable; foreach (ObjectId blockDefId in blockTable) { BlockTableRecord blockDef = Trans.GetObject(blockDefId, OpenMode.ForRead) as BlockTableRecord; if (!blockDef.IsFromExternalReference) { foreach (ObjectId entId in blockDef) { Entity ent = Trans.GetObject(entId, OpenMode.ForRead, false, true) as Entity; if (ent != null) { try { if (ent is Curve curve) { if (curve.GetDistanceAtParameter(curve.EndParam) < Tolerance.Global.EqualPoint) { EraseEntity(curve); } else if (ent is DBText dbText) { if (string.IsNullOrWhiteSpace(dbText.TextString)) { EraseEntity(dbText); } } else if (ent is MText mText) { if (string.IsNullOrWhiteSpace(mText.Text .Replace("\\P", " ") .Replace('\r', ' ') .Replace('\n', ' '))) { EraseEntity(mText); } } } } catch (Exception ex) { #if DEBUG ed.WriteMessage( $"Handle "{ent.Handle.ToString()}" can't convert to curve : {ex.Message}"); #endif } } nanoCAD.Document comDoc = doc.AcadDocument as nanoCAD.Document; for (int i = 0; i < 3; i++) { comDoc.PurgeAll(); } } } } } private void EraseEntity(Entity entity) { entity.UpgradeOpen(); entity.Erase(); entity.DowngradeOpen(); } |
P.S. Для работы с ActiveX надо подключать как минимум OdaX.dll (ну или как она там называется), болтается в каталоге установки NC, если я не ошибаюсь.