04/02/2015
Управляемая альтернатива ExplodeAllProxy
Андрей Бушман у себя на сайте опубликовал код, решающий те же задачи, что и знаменитый ExplodeAllProxy от Александра Ривилиса. Пользуясь выцыганенным у Андрея разрешением, публикую мои изменения его кода.Прежде всего, хочу предупредить о следующем:
- Я не автор кода. Я не знаю и не понимаю, как он работает. Я не в силах его повторить. Все, что я могу сказать - это "обращайтесь на сайт Андрея"
- Ниже показан исправленный мною код. Я поменял код так, чтобы хоть что-то в нем понять (Андрей, прости!)
- После этого указаны ссылки со скомпилированными .NET-сборками для AutoCAD 2009-2015. Компилировалось в условиях 64-разрядной ОС. На 32-битных Windows / ACAD работу библиотек не проверял. Загрузка и работа проверены на ACAD2009, 2013, 2015
Если читать все лень, то: библиотека прописывает в AutoCAD
Команда
Код - Auto/Visual LISP: [Выделить]
|
Выводит в командную строку сообщение об обнаруженных прокси-объектах |
Лисп-функция
Код - Auto/Visual LISP: [Выделить]
|
То же |
Команда
Код - Auto/Visual LISP: [Выделить]
|
Разбивает все графические прокси-объекты |
Лисп-функция
Код - Auto/Visual LISP: [Выделить]
|
То же |
Команда
Код - Auto/Visual LISP: [Выделить]
|
Удаляет неразбитые и неграфические прокси-объекты |
Лисп-функция
Код - Auto/Visual LISP: [Выделить]
|
То же |
Команда
Код - Auto/Visual LISP: [Выделить]
|
Совмещает разбиение и очистку прокси-объектов |
Лисп-функция
Код - Auto/Visual LISP: [Выделить]
|
То же |
ACAD 2009 | ACAD 2010 | ACAD 2011 |
ACAD 2012 | ACAD 2013 | ACAD 2014 |
ACAD 2015 | ||
Все версии |
Код - C#: [Выделить]
ZIP-архив с кодом ProxyFunctionality можно скачать здесь- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Diagnostics;
- using System.IO;
- using cad = Autodesk.AutoCAD.ApplicationServices.Application;
- using Ap = Autodesk.AutoCAD.ApplicationServices;
- using Db = Autodesk.AutoCAD.DatabaseServices;
- using Ed = Autodesk.AutoCAD.EditorInput;
- using Rt = Autodesk.AutoCAD.Runtime;
- using Gm = Autodesk.AutoCAD.Geometry;
- namespace gunipcProxy
- {
- public delegate void WriteMessage(String format, params Object[] args);
- public static class ExtensionMethods
- {
- static Rt.RXClass proxyObjectRXType = Rt.RXClass.GetClass(typeof(
- Db.ProxyObject));
- static Rt.RXClass proxyEntityRXType = Rt.RXClass.GetClass(typeof(
- Db.ProxyEntity));
- public static Db.ObjectId[] GetDBObjectIds(this Db.Database db)
- {
- Db.ObjectId[] ids = GetDBObjectIds(db, (n => true));
- return ids;
- }
- public static Db.ObjectId[] GetDBObjectIds(this Db.Database db, Func filter)
- {
- // Check arguments
- if (null == db)
- throw new ArgumentNullException("null == db");
- if (null == filter)
- throw new ArgumentNullException("null == filter");
- if (db.IsDisposed)
- throw new ArgumentException("true == db.IsDisposed");
- // -------------------
- Int32 approxNum = db.ApproxNumObjects;
- List ids = new List();
- for (Int64 i = db.BlockTableId.Handle.Value; i < db.Handseed.Value
- && approxNum > 0; ++i)
- {
- Db.Handle h = new Db.Handle(i);
- Db.ObjectId id = Db.ObjectId.Null;
- Boolean parseResult = db.TryGetObjectId(h, out id);
- if (parseResult)
- {
- --approxNum;
- if (filter(id))
- {
- ids.Add(id);
- }
- }
- }
- return ids.ToArray();
- }
- public static Db.ObjectId[] GetEntityIds(this Db.Database db)
- {
- Db.ObjectId[] ids = GetEntityIds(db, (n => true));
- return ids;
- }
- public static Db.ObjectId[] GetEntityIds(this Db.Database db, Func filter)
- {
- // Check arguments
- if (null == db)
- throw new ArgumentNullException("null == db");
- if (null == filter)
- throw new ArgumentNullException("null == filter");
- if (db.IsDisposed)
- throw new ArgumentException("true == db.IsDisposed");
- // -------------------
- List ids = new List();
- // Entity items can be located in the BlockTableRecord instances
- // only.
- using (Db.Transaction tr = db.TransactionManager.StartTransaction()
- )
- {
- Db.BlockTable bt = tr.GetObject(db.BlockTableId,
- Db.OpenMode.ForRead) as Db.BlockTable;
- // Skip erased BlockTableRecord instances.
- IEnumerable btrIds = bt.Cast()
- .Where(n => !n.IsErased);
- foreach (Db.ObjectId btrId in btrIds)
- {
- Db.BlockTableRecord btr = tr.GetObject(btrId,
- Db.OpenMode.ForRead) as Db.BlockTableRecord;
- foreach (Db.ObjectId id in btr)
- {
- if (filter(id))
- {
- ids.Add(id);
- }
- }
- }
- tr.Commit();
- }
- return ids.ToArray();
- }
- public static Db.ObjectId[] ExplodeProxyEntity(Db.ObjectId proxyEntityId, out Boolean handOverTo_called, out Int64 explodedCount, WriteMessage writeErrorMessage)
- {
- // Check arguments
- if (null == proxyEntityId)
- throw new ArgumentException("null == proxyEntityId");
- if (proxyEntityId.IsErased)
- throw new ArgumentException("true == proxyEntityId.IsErased");
- if (null == proxyEntityId.Database)
- throw new ArgumentException("null == proxyEntityId.Database");
- if (proxyEntityId.Database.IsDisposed)
- throw new ArgumentException(
- "true == proxyEntityId.Database.IsDisposed");
- if (!proxyEntityId.ObjectClass.IsDerivedFrom(proxyEntityRXType))
- throw new ArgumentException("false == proxyEntityId." +
- "ObjectClass.IsDerivedFrom(proxyEntityRXType)");
- explodedCount = 0;
- // -------------------
- using (Db.DBObjectCollection newDBObjects =
- new Db.DBObjectCollection())
- {
- Db.Database db = proxyEntityId.Database;
- List result = new List();
- using (Db.Transaction tr = db.TransactionManager
- .StartOpenCloseTransaction())
- {
- Db.ProxyEntity proxyEntity = tr.GetObject(
- proxyEntityId, Db.OpenMode.ForWrite, false, true)
- as Db.ProxyEntity;
- if (proxyEntity.GraphicsMetafileType ==
- Db.GraphicsMetafileType.FullGraphics)
- {
- try
- {
- proxyEntity.Explode(newDBObjects);
- ++explodedCount;
- }
- catch (Exception ex)
- {
- #if !DEBUG
- writeErrorMessage( "ObjectId: {0}. Error message: {1}\n", proxyEntity.ObjectId, ex.Message);
- #endif
- }
- }
- else if (proxyEntity.GraphicsMetafileType == Db.GraphicsMetafileType.BoundingBox)
- {
- Db.Extents3d ext = proxyEntity.GeometricExtents;
- Gm.Point3dCollection arr = new Gm.Point3dCollection();
- arr.Add(ext.MinPoint);
- arr.Add(new Gm.Point3d(ext.MinPoint.X, ext.MaxPoint.Y, ext.MinPoint.Z));
- arr.Add(new Gm.Point3d(ext.MaxPoint.X, ext.MaxPoint.Y, ext.MinPoint.Z));
- arr.Add(new Gm.Point3d(ext.MaxPoint.X, ext.MinPoint.Y, ext.MinPoint.Z));
- Db.Polyline3d pline = new Db.Polyline3d(
- Db.Poly3dType.SimplePoly, arr, true);
- pline.LayerId = proxyEntity.LayerId;
- pline.LinetypeId = proxyEntity.LinetypeId;
- pline.Color = proxyEntity.Color;
- newDBObjects.Add(pline);
- }
- Db.BlockTableRecord btr = tr.GetObject(
- proxyEntity.BlockId, Db.OpenMode.ForWrite, false)
- as Db.BlockTableRecord;
- // ----------------
- Boolean canBeErased = (proxyEntity.ProxyFlags & 0x1) != 0;
- if (canBeErased)
- {
- proxyEntity.Erase();
- handOverTo_called = false;
- }
- else
- {
- using (Db.Line tmp = new Db.Line())
- {
- proxyEntity.HandOverTo(tmp, false, false);
- tmp.Erase();
- proxyEntity.Dispose();
- handOverTo_called = true;
- }
- }
- if (newDBObjects.Count > 0)
- {
- foreach (Db.DBObject item in newDBObjects)
- {
- if (item is Db.Entity)
- {
- Db.Entity _ent = item as Db.Entity;
- btr.AppendEntity(_ent);
- tr.AddNewlyCreatedDBObject(item, true);
- result.Add(item.ObjectId);
- }
- }
- }
- Db.ObjectIdCollection idsRef =
- btr.GetBlockReferenceIds(true, true);
- foreach (Db.ObjectId id in idsRef)
- {
- Db.BlockReference br = tr.GetObject(id,
- Db.OpenMode.ForWrite, false)
- as Db.BlockReference;
- br.RecordGraphicsModified(true);
- }
- tr.Commit();
- }
- return result.ToArray();
- }
- }
- public static void RemoveDBObject(Db.ObjectId id, out Boolean handOverTo_called)
- {
- // Check arguments
- if (null == id)
- throw new ArgumentException("null == id");
- if (id.IsErased)
- throw new ArgumentException("true == id.IsErased");
- if (null == id.Database)
- throw new ArgumentException("null == id.Database");
- if (id.Database.IsDisposed)
- throw new ArgumentException("true == id.Database.IsDisposed");
- // -------------------
- Db.Database db = id.Database;
- using (Db.Transaction tr = db.TransactionManager
- .StartOpenCloseTransaction())
- {
- Db.DBObject obj = tr.GetObject(id, Db.OpenMode.ForWrite, false,
- true);
- EraseDBObject(obj, out handOverTo_called);
- tr.Commit();
- }
- }
- private static void EraseDBObject(Db.DBObject obj, out Boolean handOverTo_called)
- {
- // Check argument
- if (null == obj)
- throw new ArgumentNullException("null == obj");
- if (obj.IsErased)
- throw new ArgumentException("true == obj.IsErased");
- if (obj.IsDisposed)
- throw new ArgumentException("true == obj.IsDisposed");
- if (null == obj.Database)
- throw new ArgumentException("null == obj.Database");
- if (obj.Database.IsDisposed)
- throw new ArgumentException("true == obj.Database.IsDisposed");
- // ----------------
- Boolean canBeErased = true;
- // AcDbProxyEntity::kEraseAllowed = 0x1
- if (obj is Db.ProxyObject)
- {
- Db.ProxyObject proxy = obj as Db.ProxyObject;
- canBeErased = (proxy.ProxyFlags & 0x1) != 0;
- }
- else if (obj is Db.ProxyEntity)
- {
- Db.ProxyEntity proxy = obj as Db.ProxyEntity;
- canBeErased = (proxy.ProxyFlags & 0x1) != 0;
- }
- if (canBeErased)
- {
- obj.Erase(true);
- handOverTo_called = false;
- }
- else
- {
- using (Db.DBObject tmp = obj is Db.Entity ?
- (Db.DBObject)new Db.Line() : new Db.DBDictionary())
- {
- obj.HandOverTo(tmp, false, false);
- tmp.Erase(true);
- obj.Dispose();
- handOverTo_called = true;
- }
- }
- }
- public static Db.ObjectId[] GetFreeAnnotativeScaleIds(this Db.Database db)
- {
- // Check argument
- if (null == db)
- throw new ArgumentNullException("null == db");
- if (db.IsDisposed)
- throw new ArgumentException("true == db.IsDisposed");
- // ----------------
- using (Db.ObjectIdCollection ids = new Db.ObjectIdCollection())
- {
- Db.ObjectContextManager ocMng = db.ObjectContextManager;
- if (null != ocMng)
- {
- Db.ObjectContextCollection ocItems =
- ocMng.GetContextCollection("ACDB_ANNOTATIONSCALES");
- if (null != ocItems)
- {
- foreach (Db.ObjectContext item in ocItems)
- {
- // This check is necessary for BricsCAD older
- // than v15.1.02:
- if (item is Db.AnnotationScale && String.Compare(
- item.Name, db.Cannoscale.Name) != 0)
- {
- ids.Add(new Db.ObjectId(item.UniqueIdentifier)
- );
- }
- }
- db.Purge(ids);
- }
- }
- return ids.Cast().Where(n => !n.IsErased
- && !n.IsEffectivelyErased).ToArray();
- }
- }
- public static void RemoveFreeAnnotativeScales(this Db.Database db)
- {
- // Check argument
- if (null == db)
- throw new ArgumentNullException("null == db");
- if (db.IsDisposed)
- throw new ArgumentException("true == db.IsDisposed");
- // -----------------
- Db.ObjectId[] ids = db.GetFreeAnnotativeScaleIds();
- using (Db.Transaction tr = db.TransactionManager.StartTransaction()
- )
- {
- foreach (Db.ObjectId id in ids)
- {
- try
- {
- Db.DBObject obj = tr.GetObject(id, Db.OpenMode
- .ForWrite, false);
- obj.Erase();
- }
- catch { }
- }
- tr.Commit();
- }
- }
- }
- public static class ProxyFunctionality
- {
- public static void Proxy_ShowInfo()
- {
- Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
- if (null == doc)
- return;
- Ed.Editor ed = doc.Editor;
- Db.Database db = doc.Database;
- using (doc.LockDocument())
- {
- // Proxy types
- Rt.RXClass proxyObjectRXType = Rt.RXClass.GetClass(typeof(Db.ProxyObject));
- Rt.RXClass proxyEntityRXType = Rt.RXClass.GetClass(typeof(Db.ProxyEntity));
- // Filters
- Func proxyEntityFilter = n => !n.IsErased && !n.IsEffectivelyErased && n.ObjectClass.IsDerivedFrom(proxyEntityRXType);
- Func proxyObjectFilter = n => !n.IsErased && !n.IsEffectivelyErased && n.ObjectClass.IsDerivedFrom(proxyObjectRXType);
- // Filtered ids
- Db.ObjectId[] proxyEntityIds = db.GetEntityIds(proxyEntityFilter);
- Db.ObjectId[] proxyObjectIds = db.GetDBObjectIds(proxyObjectFilter);
- ed.WriteMessage("{0} ProxyEntity and {1} ProxyObject items found.\n", proxyEntityIds.Length.ToString(), proxyObjectIds.Length.ToString());
- }
- }
- public static void Proxy_ExplodeAllProxyEntities(Boolean ShowReport)
- {
- Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
- if (null == doc)
- return;
- Ed.Editor ed = doc.Editor;
- Db.Database db = doc.Database;
- using (doc.LockDocument())
- {
- Rt.RXClass proxyEntityRXType = Rt.RXClass.GetClass(typeof(Db.ProxyEntity));
- Func proxyEntityFilter = n => !n.IsErased && !n.IsEffectivelyErased && n.ObjectClass.IsDerivedFrom(proxyEntityRXType);
- Db.ObjectId[] proxyEntityIds = db.GetEntityIds(proxyEntityFilter);
- Int64 newEntityCount = 0;
- Int64 handOverTo_entity_count = 0;
- Int64 explodedCount = 0;
- foreach (Db.ObjectId id in proxyEntityIds)
- {
- Boolean handOverTo_called = false;
- Int64 tmp_explodedCount = 0;
- Db.ObjectId[] newEntityIds = gunipcProxy.ExtensionMethods.ExplodeProxyEntity(id, out handOverTo_called, out tmp_explodedCount, ed.WriteMessage);
- newEntityCount += newEntityIds.Length;
- explodedCount += tmp_explodedCount;
- if (handOverTo_called)
- ++handOverTo_entity_count;
- }
- try
- {
- /* Remove erased objects from memory.
- * An exception occurs if erasedIds contain ids which was
- * removed from memory already. There is no method to check
- * it in advance. */
- Db.ObjectId[] erasedIds = db.GetDBObjectIds(n => n.IsErased
- );
- /* This checking is neccessary, bacause if erasedIds
- * .Length == 0 we get an exception in the
- * ObjectIdCollection initialization. */
- if (erasedIds.Length > 0)
- {
- using (Db.ObjectIdCollection ids =
- new Db.ObjectIdCollection(erasedIds))
- {
- db.ReclaimMemoryFromErasedObjects(ids);
- }
- }
- }
- catch {/* nothing here */ }
- if (ShowReport)
- {
- ed.WriteMessage("{0} ProxyEntity items found.\n", proxyEntityIds.Length.ToString());
- ed.WriteMessage("{0} ProxyEntity items exloded.\n", explodedCount);
- ed.WriteMessage("{0} new DBObjects created.\n", newEntityCount.ToString());
- ed.WriteMessage("Count of 'HandOverTo' operations: {0}.\n", handOverTo_entity_count.ToString());
- ed.WriteMessage("Run the _AUDIT command with the _Y option, " + "please.\n");
- }
- }
- }
- public static void Proxy_RemoveAllProxyObjests(Boolean ShowReport)
- {
- Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
- if (null == doc)
- return;
- Ed.Editor ed = doc.Editor;
- Db.Database db = doc.Database;
- using (doc.LockDocument())
- {
- Rt.RXClass proxyObjectRXType = Rt.RXClass.GetClass(typeof(
- Db.ProxyObject));
- Rt.RXClass proxyEntityRXType = Rt.RXClass.GetClass(typeof(
- Db.ProxyEntity));
- Func proxyObjectFilter = n => !n.IsErased && !n.IsEffectivelyErased && n.ObjectClass.IsDerivedFrom(proxyObjectRXType);
- Func proxyEntityFilter = n => !n.IsErased && !n.IsEffectivelyErased && n.ObjectClass.IsDerivedFrom(proxyEntityRXType);
- Db.ObjectId[] proxyObjectIds = db.GetDBObjectIds(proxyObjectFilter);
- Db.ObjectId[] proxyEntityIds = db.GetEntityIds(proxyEntityFilter);
- Int64 handOverTo_object_count = 0;
- Int64 handOverTo_entity_count = 0;
- foreach (Db.ObjectId id in proxyObjectIds)
- {
- Boolean handOverTo_called = false;
- gunipcProxy.ExtensionMethods.RemoveDBObject(id, out handOverTo_called);
- if (handOverTo_called)
- ++handOverTo_object_count;
- }
- if (ShowReport)
- {
- ed.WriteMessage("{0} ProxyObject items found and removed.\n", proxyObjectIds.Length.ToString());
- ed.WriteMessage("Count of 'HandOverTo' operations: {0}.\n\n", handOverTo_object_count.ToString());
- }
- foreach (Db.ObjectId id in proxyEntityIds)
- {
- Boolean handOverTo_called = false;
- gunipcProxy.ExtensionMethods.RemoveDBObject(id, out handOverTo_called);
- if (handOverTo_called)
- ++handOverTo_entity_count;
- }
- try
- {
- /* Remove erased objects from memory.
- * An exception occurs if erasedIds contain ids which was
- * removed from memory already. There is no method to check
- * it in advance. */
- Db.ObjectId[] erasedIds = db.GetDBObjectIds(n => n.IsErased
- );
- /* This checking is neccessary, bacause if erasedIds
- * .Length == 0 we get an exception in the
- * ObjectIdCollection initialization. */
- if (erasedIds.Length > 0)
- {
- using (Db.ObjectIdCollection ids = new Db.ObjectIdCollection(erasedIds))
- {
- db.ReclaimMemoryFromErasedObjects(ids);
- }
- }
- }
- catch {/* nothing here */ }
- if (ShowReport)
- {
- ed.WriteMessage("{0} ProxyEntity items found and removed.\n", proxyEntityIds.Length.ToString());
- ed.WriteMessage("Count of 'HandOverTo' operations: {0}.\n\n", handOverTo_entity_count.ToString());
- ed.WriteMessage("Run the _AUDIT command with the _Y option, " + "please.\n");
- }
- }
- }
- }
- }
Ну и обертки: команды и лисп-функции
Код - C#: [Выделить]
Опять же, ZIP-архив с исходником здесь- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using Autodesk.AutoCAD.ApplicationServices;
- using Autodesk.AutoCAD.DatabaseServices;
- using Autodesk.AutoCAD.EditorInput;
- using Autodesk.AutoCAD.Runtime;
- using Autodesk.AutoCAD.Geometry;
- // [assembly: Rt.CommandClass(typeof(gunipcProxy.ProxyCommands))]
- namespace gunipcProxy
- {
- public class ProxyCommands
- {
- [CommandMethod("gu_ProxyInfo", CommandFlags.Modal)]
- public static void cmd_ProxyShow()
- { gunipcProxy.ProxyFunctionality.Proxy_ShowInfo(); }
- [LispFunction("gunipc_ProxyInfo")]
- public static ResultBuffer lisp_ProxyShow()
- { gunipcProxy.ProxyFunctionality.Proxy_ShowInfo(); return null; }
- [CommandMethod("gu_ProxyExplode", CommandFlags.Modal)]
- public static void cmd_ProxyExplode()
- { gunipcProxy.ProxyFunctionality.Proxy_ExplodeAllProxyEntities(true); }
- [LispFunction("gunipc_ProxyExplode")]
- public static ResultBuffer lisp_ProxyExplode()
- { gunipcProxy.ProxyFunctionality.Proxy_ExplodeAllProxyEntities(true); return null; }
- [CommandMethod("gu_ProxyRemove", CommandFlags.Modal)]
- public static void cmd_ProxyRemove()
- { gunipcProxy.ProxyFunctionality.Proxy_RemoveAllProxyObjests(true); }
- [LispFunction("gunipc_ProxyRemove")]
- public static ResultBuffer lisp_ProxyRemove()
- { gunipcProxy.ProxyFunctionality.Proxy_RemoveAllProxyObjests(true); return null; }
- [CommandMethod("gu_ProxyClear", CommandFlags.Modal)]
- public static void cmd_ProxyClear()
- {
- gunipcProxy.ProxyFunctionality.Proxy_ExplodeAllProxyEntities(false);
- gunipcProxy.ProxyFunctionality.Proxy_RemoveAllProxyObjests(true);
- }
- [LispFunction("gunipc_ProxyClear")]
- public static ResultBuffer lisp_ProxyClear(ResultBuffer buffer)
- {
- gunipcProxy.ProxyFunctionality.Proxy_ExplodeAllProxyEntities(false);
- gunipcProxy.ProxyFunctionality.Proxy_RemoveAllProxyObjests(false); return null;
- }
- }
- }
Автор: Алексей Кулик. На основе материалов сайта Андрея Бушмана и статьи на autolisp.ru.
Обсуждение: http://adn-cis.org/forum/index.php?topic=1830
Опубликовано 04.02.2015Отредактировано 04.02.2015 в 09:48:18