- 积分
- 22862
- 明经币
- 个
- 注册时间
- 2016-5-25
- 在线时间
- 小时
- 威望
-
- 金钱
- 个
- 贡献
-
- 激情
-
|
原贴搬运清理dgn
//http://www.theswamp.org/index.php?topic=45030.msg502441#msg502441
- using System;
- using System.Runtime.InteropServices;
- //using Autodesk.AutoCAD.ApplicationServices.Core;
- using Autodesk.AutoCAD.ApplicationServices;
- using Autodesk.AutoCAD.DatabaseServices;
- using Autodesk.AutoCAD.Runtime;
- using System.Collections.ObjectModel;
-
- namespace DgnPurger
- {
- public class Commands
- {
- const string dgnLsDefName = "DGNLSDEF";
- const string dgnLsDictName = "ACAD_DGNLINESTYLECOMP";
-
- public struct ads_name
- {
- public IntPtr a;
- public IntPtr b;
- };
-
- //[DllImport("acdb19.dll",
- [DllImport("acdb18.dll",
- CharSet = CharSet.Unicode,
- CallingConvention = CallingConvention.Cdecl,
- EntryPoint = "acdbHandEnt")]
- public static extern int acdbHandEnt(string h, ref ads_name n);
-
- [CommandMethod("DGNPURGE")]
- public void PurgeDgnLinetypes()
- {
- var doc =
- Application.DocumentManager.MdiActiveDocument;
- var db = doc.Database;
- var ed = doc.Editor;
-
- using (var tr = doc.TransactionManager.StartTransaction())
- {
- // Start by getting all the "complex" DGN linetypes
- // from the linetype table
-
- var linetypes = CollectComplexLinetypeIds(db, tr);
-
- // Store a count before we start removing the ones
- // that are referenced
-
- var ltcnt = linetypes.Count;
-
- // Remove any from the "to remove" list that need to be
- // kept (as they have references from objects other
- // than anonymous blocks)
-
- var ltsToKeep =
- PurgeLinetypesReferencedNotByAnonBlocks(db, tr, linetypes);
-
- // Now we collect the DGN stroke entries from the NOD
-
- var strokes = CollectStrokeIds(db, tr);
-
- // Store a count before we start removing the ones
- // that are referenced
-
- var strkcnt = strokes.Count;
-
- // Open up each of the "keeper" linetypes, and go through
- // their data, removing any NOD entries from the "to
- // remove" list that are referenced
-
- PurgeStrokesReferencedByLinetypes(tr, ltsToKeep, strokes);
-
- // Erase each of the NOD entries that are safe to remove
-
- int erasedStrokes = 0;
-
- foreach (ObjectId id in strokes)
- {
- try
- {
- var obj = tr.GetObject(id, OpenMode.ForWrite);
- obj.Erase();
- if (
- obj.GetRXClass().Name.Equals("AcDbLSSymbolComponent")
- )
- {
- EraseReferencedAnonBlocks(tr, obj);
- }
- erasedStrokes++;
- }
- catch (System.Exception ex)
- {
- ed.WriteMessage(
- "\nUnable to erase stroke ({0}): {1}",
- id.ObjectClass.Name,
- ex.Message
- );
- }
- }
-
- // And the same for the complex linetypes
-
- int erasedLinetypes = 0;
-
- foreach (ObjectId id in linetypes)
- {
- try
- {
- var obj = tr.GetObject(id, OpenMode.ForWrite);
- obj.Erase();
- erasedLinetypes++;
- }
- catch (System.Exception ex)
- {
- ed.WriteMessage(
- "\nUnable to erase linetype ({0}): {1}",
- id.ObjectClass.Name,
- ex.Message
- );
- }
- }
-
- // Remove the DGN stroke dictionary from the NOD if empty
-
- var nod =
- (DBDictionary)tr.GetObject(
- db.NamedObjectsDictionaryId, OpenMode.ForRead
- );
-
- ed.WriteMessage(
- "\nPurged {0} unreferenced complex linetype records" +
- " (of {1}).",
- erasedLinetypes, ltcnt
- );
-
- ed.WriteMessage(
- "\nPurged {0} unreferenced strokes (of {1}).",
- erasedStrokes, strkcnt
- );
-
- if (nod.Contains(dgnLsDictName))
- {
- var dgnLsDict =
- (DBDictionary)tr.GetObject(
- (ObjectId)nod[dgnLsDictName],
- OpenMode.ForRead
- );
-
- if (dgnLsDict.Count == 0)
- {
- dgnLsDict.UpgradeOpen();
- dgnLsDict.Erase();
-
- ed.WriteMessage(
- "\nRemoved the empty DGN linetype stroke dictionary."
- );
- }
- }
-
- tr.Commit();
- }
- }
-
- // Collect the complex DGN linetypes from the linetype table
-
- private static ObjectIdCollection CollectComplexLinetypeIds(
- Database db, Transaction tr
- )
- {
- var ids = new ObjectIdCollection();
-
- var lt =
- (LinetypeTable)tr.GetObject(
- db.LinetypeTableId, OpenMode.ForRead
- );
- foreach (var ltId in lt)
- {
- // Complex DGN linetypes have an extension dictionary
- // with a certain record inside
-
- var obj = tr.GetObject(ltId, OpenMode.ForRead);
- if (obj.ExtensionDictionary != ObjectId.Null)
- {
- var exd =
- (DBDictionary)tr.GetObject(
- obj.ExtensionDictionary, OpenMode.ForRead
- );
- if (exd.Contains(dgnLsDefName))
- {
- ids.Add(ltId);
- }
- }
- }
- return ids;
- }
-
- // Collect the DGN stroke entries from the NOD
-
- private static ObjectIdCollection CollectStrokeIds(
- Database db, Transaction tr
- )
- {
- var ids = new ObjectIdCollection();
-
- var nod =
- (DBDictionary)tr.GetObject(
- db.NamedObjectsDictionaryId, OpenMode.ForRead
- );
-
- // Strokes are stored in a particular dictionary
-
- if (nod.Contains(dgnLsDictName))
- {
- var dgnDict =
- (DBDictionary)tr.GetObject(
- (ObjectId)nod[dgnLsDictName],
- OpenMode.ForRead
- );
-
- foreach (var item in dgnDict)
- {
- ids.Add(item.Value);
- }
- }
-
- return ids;
- }
-
- // Remove the linetype IDs that have references from objects
- // other than anonymous blocks from the list passed in,
- // returning the ones removed in a separate list
-
- private static ObjectIdCollection
- PurgeLinetypesReferencedNotByAnonBlocks(
- Database db, Transaction tr, ObjectIdCollection ids
- )
- {
- var keepers = new ObjectIdCollection();
-
- // To determine the references from objects in the database,
- // we need to open every object. One reasonably efficient way
- // to do so is to loop through all handles in the possible
- // handle space for this drawing (starting with 1, ending with
- // the value of "HANDSEED") and open each object we can
-
- // Get the last handle in the db
-
- var handseed = db.Handseed;
-
- // Copy the handseed total into an efficient raw datatype
-
- var handseedTotal = handseed.Value;
-
- // Loop from 1 to the last handle (could be a big loop)
-
- var ename = new ads_name();
-
- for (long i = 1; i < handseedTotal; i++)
- {
- // Get a handle from the counter
-
- var handle = Convert.ToString(i, 16);
-
- // Get the entity name using acdbHandEnt()
-
- var res = acdbHandEnt(handle, ref ename);
-
- if (res != 5100) // RTNORM
- continue;
-
- // Convert the entity name to an ObjectId
-
- var id = new ObjectId(ename.a);
-
- // Open the object and check its linetype
-
- var obj = tr.GetObject(id, OpenMode.ForRead, true);
- var ent = obj as Entity;
- if (ent != null && !ent.IsErased)
- {
- if (ids.Contains(ent.LinetypeId))
- {
- // If the owner does not belong to an anonymous
- // block, then we take it seriously as a reference
-
- var owner =
- (BlockTableRecord)tr.GetObject(
- ent.OwnerId, OpenMode.ForRead
- );
- if (
- !owner.Name.StartsWith("*") ||
- owner.Name.ToUpper() == BlockTableRecord.ModelSpace ||
- owner.Name.ToUpper().StartsWith(
- BlockTableRecord.PaperSpace
- )
- )
- {
- // Move the linetype ID from the "to remove" list
- // to the "to keep" list
-
- ids.Remove(ent.LinetypeId);
- keepers.Add(ent.LinetypeId);
- }
- }
- }
- }
- return keepers;
- }
-
- // Remove the stroke objects that have references from
- // complex linetypes (or from other stroke objects, as we
- // recurse) from the list passed in
-
- private static void PurgeStrokesReferencedByLinetypes(
- Transaction tr,
- ObjectIdCollection tokeep,
- ObjectIdCollection nodtoremove
- )
- {
- foreach (ObjectId id in tokeep)
- {
- PurgeStrokesReferencedByObject(tr, nodtoremove, id);
- }
- }
-
- // Remove the stroke objects that have references from this
- // particular complex linetype or stroke object from the list
- // passed in
-
- private static void PurgeStrokesReferencedByObject(
- Transaction tr, ObjectIdCollection nodIds, ObjectId id
- )
- {
- var obj = tr.GetObject(id, OpenMode.ForRead);
- if (obj.ExtensionDictionary != ObjectId.Null)
- {
- // Get the extension dictionary
-
- var exd =
- (DBDictionary)tr.GetObject(
- obj.ExtensionDictionary, OpenMode.ForRead
- );
-
- // And the "DGN Linestyle Definition" object
-
- if (exd.Contains(dgnLsDefName))
- {
- var lsdef =
- tr.GetObject(
- exd.GetAt(dgnLsDefName), OpenMode.ForRead
- );
-
- // Use a DWG filer to extract the references
-
- var refFiler = new ReferenceFiler();
- lsdef.DwgOut(refFiler);
-
- // Loop through the references and remove any from the
- // list passed in
-
- foreach (ObjectId refid in refFiler.HardPointerIds)
- {
- if (nodIds.Contains(refid))
- {
- nodIds.Remove(refid);
- }
-
- // We need to recurse, as linetype strokes can reference
- // other linetype strokes
-
- PurgeStrokesReferencedByObject(tr, nodIds, refid);
- }
- }
- }
- else if (
- obj.GetRXClass().Name.Equals("AcDbLSCompoundComponent") ||
- obj.GetRXClass().Name.Equals("AcDbLSPointComponent")
- )
- {
- // We also need to consider compound components, which
- // don't use objects in their extension dictionaries to
- // manage references to strokes...
-
- // Use a DWG filer to extract the references from the
- // object itself
-
- var refFiler = new ReferenceFiler();
- obj.DwgOut(refFiler);
-
- // Loop through the references and remove any from the
- // list passed in
-
- foreach (ObjectId refid in refFiler.HardPointerIds)
- {
- if (nodIds.Contains(refid))
- {
- nodIds.Remove(refid);
- }
-
- // We need to recurse, as linetype strokes can reference
- // other linetype strokes
-
- PurgeStrokesReferencedByObject(tr, nodIds, refid);
- }
- }
- }
-
- // Erase the anonymous blocks referenced by an object
-
- private static void EraseReferencedAnonBlocks(
- Transaction tr, DBObject obj
- )
- {
- var refFiler = new ReferenceFiler();
- obj.DwgOut(refFiler);
-
- // Loop through the references and erase any
- // anonymous block definitions
- //
- foreach (ObjectId refid in refFiler.HardPointerIds)
- {
- BlockTableRecord btr =
- tr.GetObject(refid, OpenMode.ForRead) as BlockTableRecord;
- if (btr != null && btr.IsAnonymous)
- {
- btr.UpgradeOpen();
- btr.Erase();
- }
- }
- }
- }
- }
-
|
|