乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 40|回复: 2

清理dgn

[复制链接]

20

主题

121

帖子

11

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
201
发表于 2020-2-25 12:48:00 | 显示全部楼层 |阅读模式
原贴搬运清理dgn
//http://www.theswamp.org/index.php?topic=45030.msg502441#msg502441
  1. using System;
  2. using System.Runtime.InteropServices;
  3. //using Autodesk..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. }
回复

使用道具 举报

17

主题

69

帖子

2

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
137
发表于 2020-2-26 15:02:00 | 显示全部楼层
这个是干嘛用的啊?
回复

使用道具 举报

0

主题

1

帖子

2

银币

初来乍到

Rank: 1

铜币
1
发表于 2020-3-14 19:05:00 | 显示全部楼层
好东西
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

QQ|关于我们|小黑屋|乐筑天下 繁体中文

GMT+8, 2024-11-22 01:37 , Processed in 0.414267 second(s), 58 queries .

© 2020-2024 乐筑天下

联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表