明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 948|回复: 2

[符号表] 清理dgn

[复制链接]
发表于 2020-2-25 12:48 | 显示全部楼层 |阅读模式
原贴搬运清理dgn
//http://www.theswamp.org/index.php?topic=45030.msg502441#msg502441

  1. using System;
  2. using System.Runtime.InteropServices;
  3. //using Autodesk.AutoCAD.ApplicationServices.Core;
  4. using Autodesk.AutoCAD.ApplicationServices;
  5. using Autodesk.AutoCAD.DatabaseServices;
  6. using Autodesk.AutoCAD.Runtime;
  7. using System.Collections.ObjectModel;

  8. namespace DgnPurger
  9. {
  10.     public class Commands
  11.     {
  12.         const string dgnLsDefName = "DGNLSDEF";
  13.         const string dgnLsDictName = "ACAD_DGNLINESTYLECOMP";

  14.         public struct ads_name
  15.         {
  16.             public IntPtr a;
  17.             public IntPtr b;
  18.         };

  19.         //[DllImport("acdb19.dll",
  20.         [DllImport("acdb18.dll",
  21.           CharSet = CharSet.Unicode,
  22.           CallingConvention = CallingConvention.Cdecl,
  23.           EntryPoint = "acdbHandEnt")]
  24.         public static extern int acdbHandEnt(string h, ref ads_name n);

  25.         [CommandMethod("DGNPURGE")]
  26.         public void PurgeDgnLinetypes()
  27.         {
  28.             var doc =
  29.               Application.DocumentManager.MdiActiveDocument;
  30.             var db = doc.Database;
  31.             var ed = doc.Editor;

  32.             using (var tr = doc.TransactionManager.StartTransaction())
  33.             {
  34.                 // Start by getting all the "complex" DGN linetypes
  35.                 // from the linetype table

  36.                 var linetypes = CollectComplexLinetypeIds(db, tr);

  37.                 // Store a count before we start removing the ones
  38.                 // that are referenced

  39.                 var ltcnt = linetypes.Count;

  40.                 // Remove any from the "to remove" list that need to be
  41.                 // kept (as they have references from objects other
  42.                 // than anonymous blocks)

  43.                 var ltsToKeep =
  44.                   PurgeLinetypesReferencedNotByAnonBlocks(db, tr, linetypes);

  45.                 // Now we collect the DGN stroke entries from the NOD

  46.                 var strokes = CollectStrokeIds(db, tr);

  47.                 // Store a count before we start removing the ones
  48.                 // that are referenced

  49.                 var strkcnt = strokes.Count;

  50.                 // Open up each of the "keeper" linetypes, and go through
  51.                 // their data, removing any NOD entries from the "to
  52.                 // remove" list that are referenced

  53.                 PurgeStrokesReferencedByLinetypes(tr, ltsToKeep, strokes);

  54.                 // Erase each of the NOD entries that are safe to remove

  55.                 int erasedStrokes = 0;

  56.                 foreach (ObjectId id in strokes)
  57.                 {
  58.                     try
  59.                     {
  60.                         var obj = tr.GetObject(id, OpenMode.ForWrite);
  61.                         obj.Erase();
  62.                         if (
  63.                           obj.GetRXClass().Name.Equals("AcDbLSSymbolComponent")
  64.                         )
  65.                         {
  66.                             EraseReferencedAnonBlocks(tr, obj);
  67.                         }
  68.                         erasedStrokes++;
  69.                     }
  70.                     catch (System.Exception ex)
  71.                     {
  72.                         ed.WriteMessage(
  73.                           "\nUnable to erase stroke ({0}): {1}",
  74.                           id.ObjectClass.Name,
  75.                           ex.Message
  76.                         );
  77.                     }
  78.                 }

  79.                 // And the same for the complex linetypes

  80.                 int erasedLinetypes = 0;

  81.                 foreach (ObjectId id in linetypes)
  82.                 {
  83.                     try
  84.                     {
  85.                         var obj = tr.GetObject(id, OpenMode.ForWrite);
  86.                         obj.Erase();
  87.                         erasedLinetypes++;
  88.                     }
  89.                     catch (System.Exception ex)
  90.                     {
  91.                         ed.WriteMessage(
  92.                           "\nUnable to erase linetype ({0}): {1}",
  93.                           id.ObjectClass.Name,
  94.                           ex.Message
  95.                         );
  96.                     }
  97.                 }

  98.                 // Remove the DGN stroke dictionary from the NOD if empty

  99.                 var nod =
  100.                   (DBDictionary)tr.GetObject(
  101.                     db.NamedObjectsDictionaryId, OpenMode.ForRead
  102.                   );

  103.                 ed.WriteMessage(
  104.                   "\nPurged {0} unreferenced complex linetype records" +
  105.                   " (of {1}).",
  106.                   erasedLinetypes, ltcnt
  107.                 );

  108.                 ed.WriteMessage(
  109.                   "\nPurged {0} unreferenced strokes (of {1}).",
  110.                   erasedStrokes, strkcnt
  111.                 );

  112.                 if (nod.Contains(dgnLsDictName))
  113.                 {
  114.                     var dgnLsDict =
  115.                       (DBDictionary)tr.GetObject(
  116.                         (ObjectId)nod[dgnLsDictName],
  117.                         OpenMode.ForRead
  118.                       );

  119.                     if (dgnLsDict.Count == 0)
  120.                     {
  121.                         dgnLsDict.UpgradeOpen();
  122.                         dgnLsDict.Erase();

  123.                         ed.WriteMessage(
  124.                           "\nRemoved the empty DGN linetype stroke dictionary."
  125.                         );
  126.                     }
  127.                 }

  128.                 tr.Commit();
  129.             }
  130.         }

  131.         // Collect the complex DGN linetypes from the linetype table

  132.         private static ObjectIdCollection CollectComplexLinetypeIds(
  133.           Database db, Transaction tr
  134.         )
  135.         {
  136.             var ids = new ObjectIdCollection();

  137.             var lt =
  138.               (LinetypeTable)tr.GetObject(
  139.                 db.LinetypeTableId, OpenMode.ForRead
  140.               );
  141.             foreach (var ltId in lt)
  142.             {
  143.                 // Complex DGN linetypes have an extension dictionary
  144.                 // with a certain record inside

  145.                 var obj = tr.GetObject(ltId, OpenMode.ForRead);
  146.                 if (obj.ExtensionDictionary != ObjectId.Null)
  147.                 {
  148.                     var exd =
  149.                       (DBDictionary)tr.GetObject(
  150.                         obj.ExtensionDictionary, OpenMode.ForRead
  151.                       );
  152.                     if (exd.Contains(dgnLsDefName))
  153.                     {
  154.                         ids.Add(ltId);
  155.                     }
  156.                 }
  157.             }
  158.             return ids;
  159.         }

  160.         // Collect the DGN stroke entries from the NOD

  161.         private static ObjectIdCollection CollectStrokeIds(
  162.           Database db, Transaction tr
  163.         )
  164.         {
  165.             var ids = new ObjectIdCollection();

  166.             var nod =
  167.               (DBDictionary)tr.GetObject(
  168.                 db.NamedObjectsDictionaryId, OpenMode.ForRead
  169.               );

  170.             // Strokes are stored in a particular dictionary

  171.             if (nod.Contains(dgnLsDictName))
  172.             {
  173.                 var dgnDict =
  174.                   (DBDictionary)tr.GetObject(
  175.                     (ObjectId)nod[dgnLsDictName],
  176.                     OpenMode.ForRead
  177.                   );

  178.                 foreach (var item in dgnDict)
  179.                 {
  180.                     ids.Add(item.Value);
  181.                 }
  182.             }

  183.             return ids;
  184.         }

  185.         // Remove the linetype IDs that have references from objects
  186.         // other than anonymous blocks from the list passed in,
  187.         // returning the ones removed in a separate list

  188.         private static ObjectIdCollection
  189.           PurgeLinetypesReferencedNotByAnonBlocks(
  190.             Database db, Transaction tr, ObjectIdCollection ids
  191.           )
  192.         {
  193.             var keepers = new ObjectIdCollection();

  194.             // To determine the references from objects in the database,
  195.             // we need to open every object. One reasonably efficient way
  196.             // to do so is to loop through all handles in the possible
  197.             // handle space for this drawing (starting with 1, ending with
  198.             // the value of "HANDSEED") and open each object we can

  199.             // Get the last handle in the db

  200.             var handseed = db.Handseed;

  201.             // Copy the handseed total into an efficient raw datatype

  202.             var handseedTotal = handseed.Value;

  203.             // Loop from 1 to the last handle (could be a big loop)

  204.             var ename = new ads_name();

  205.             for (long i = 1; i < handseedTotal; i++)
  206.             {
  207.                 // Get a handle from the counter

  208.                 var handle = Convert.ToString(i, 16);

  209.                 // Get the entity name using acdbHandEnt()

  210.                 var res = acdbHandEnt(handle, ref ename);

  211.                 if (res != 5100) // RTNORM
  212.                     continue;

  213.                 // Convert the entity name to an ObjectId

  214.                 var id = new ObjectId(ename.a);

  215.                 // Open the object and check its linetype

  216.                 var obj = tr.GetObject(id, OpenMode.ForRead, true);
  217.                 var ent = obj as Entity;
  218.                 if (ent != null && !ent.IsErased)
  219.                 {
  220.                     if (ids.Contains(ent.LinetypeId))
  221.                     {
  222.                         // If the owner does not belong to an anonymous
  223.                         // block, then we take it seriously as a reference

  224.                         var owner =
  225.                           (BlockTableRecord)tr.GetObject(
  226.                             ent.OwnerId, OpenMode.ForRead
  227.                           );
  228.                         if (
  229.                           !owner.Name.StartsWith("*") ||
  230.                           owner.Name.ToUpper() == BlockTableRecord.ModelSpace ||
  231.                           owner.Name.ToUpper().StartsWith(
  232.                             BlockTableRecord.PaperSpace
  233.                           )
  234.                         )
  235.                         {
  236.                             // Move the linetype ID from the "to remove" list
  237.                             // to the "to keep" list

  238.                             ids.Remove(ent.LinetypeId);
  239.                             keepers.Add(ent.LinetypeId);
  240.                         }
  241.                     }
  242.                 }
  243.             }
  244.             return keepers;
  245.         }

  246.         // Remove the stroke objects that have references from
  247.         // complex linetypes (or from other stroke objects, as we
  248.         // recurse) from the list passed in

  249.         private static void PurgeStrokesReferencedByLinetypes(
  250.           Transaction tr,
  251.           ObjectIdCollection tokeep,
  252.           ObjectIdCollection nodtoremove
  253.         )
  254.         {
  255.             foreach (ObjectId id in tokeep)
  256.             {
  257.                 PurgeStrokesReferencedByObject(tr, nodtoremove, id);
  258.             }
  259.         }

  260.         // Remove the stroke objects that have references from this
  261.         // particular complex linetype or stroke object from the list
  262.         // passed in

  263.         private static void PurgeStrokesReferencedByObject(
  264.           Transaction tr, ObjectIdCollection nodIds, ObjectId id
  265.         )
  266.         {
  267.             var obj = tr.GetObject(id, OpenMode.ForRead);
  268.             if (obj.ExtensionDictionary != ObjectId.Null)
  269.             {
  270.                 // Get the extension dictionary

  271.                 var exd =
  272.                   (DBDictionary)tr.GetObject(
  273.                     obj.ExtensionDictionary, OpenMode.ForRead
  274.                   );

  275.                 // And the "DGN Linestyle Definition" object

  276.                 if (exd.Contains(dgnLsDefName))
  277.                 {
  278.                     var lsdef =
  279.                       tr.GetObject(
  280.                         exd.GetAt(dgnLsDefName), OpenMode.ForRead
  281.                       );

  282.                     // Use a DWG filer to extract the references

  283.                     var refFiler = new ReferenceFiler();
  284.                     lsdef.DwgOut(refFiler);

  285.                     // Loop through the references and remove any from the
  286.                     // list passed in

  287.                     foreach (ObjectId refid in refFiler.HardPointerIds)
  288.                     {
  289.                         if (nodIds.Contains(refid))
  290.                         {
  291.                             nodIds.Remove(refid);
  292.                         }

  293.                         // We need to recurse, as linetype strokes can reference
  294.                         // other linetype strokes

  295.                         PurgeStrokesReferencedByObject(tr, nodIds, refid);
  296.                     }
  297.                 }
  298.             }
  299.             else if (
  300.               obj.GetRXClass().Name.Equals("AcDbLSCompoundComponent") ||
  301.               obj.GetRXClass().Name.Equals("AcDbLSPointComponent")
  302.             )
  303.             {
  304.                 // We also need to consider compound components, which
  305.                 // don't use objects in their extension dictionaries to
  306.                 // manage references to strokes...

  307.                 // Use a DWG filer to extract the references from the
  308.                 // object itself

  309.                 var refFiler = new ReferenceFiler();
  310.                 obj.DwgOut(refFiler);

  311.                 // Loop through the references and remove any from the
  312.                 // list passed in

  313.                 foreach (ObjectId refid in refFiler.HardPointerIds)
  314.                 {
  315.                     if (nodIds.Contains(refid))
  316.                     {
  317.                         nodIds.Remove(refid);
  318.                     }

  319.                     // We need to recurse, as linetype strokes can reference
  320.                     // other linetype strokes

  321.                     PurgeStrokesReferencedByObject(tr, nodIds, refid);
  322.                 }
  323.             }
  324.         }

  325.         // Erase the anonymous blocks referenced by an object

  326.         private static void EraseReferencedAnonBlocks(
  327.           Transaction tr, DBObject obj
  328.         )
  329.         {
  330.             var refFiler = new ReferenceFiler();
  331.             obj.DwgOut(refFiler);

  332.             // Loop through the references and erase any
  333.             // anonymous block definitions
  334.             //
  335.             foreach (ObjectId refid in refFiler.HardPointerIds)
  336.             {
  337.                 BlockTableRecord btr =
  338.                   tr.GetObject(refid, OpenMode.ForRead) as BlockTableRecord;
  339.                 if (btr != null && btr.IsAnonymous)
  340.                 {
  341.                     btr.UpgradeOpen();
  342.                     btr.Erase();
  343.                 }
  344.             }
  345.         }
  346.     }
  347. }
发表于 2020-2-26 15:02 | 显示全部楼层
这个是干嘛用的啊?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-5-2 06:41 , Processed in 0.190834 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表