乐筑天下

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

DGN Purge for 2012

[复制链接]

3

主题

81

帖子

4

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
93
发表于 2013-7-30 17:10:06 | 显示全部楼层 |阅读模式
Kean has posted this fix for purging DGN linetypes here, but it works for acad 2013 and above.
We are having serious problems with massive amounts of linetypes from DGN drawings, but are on acad 2012.
(see my comment in the link posted)
He suggests you can build the code (found here) to work for 2012, but I have no idea or experience with this.
Can any of you help?
Thanks in advance.
回复

使用道具 举报

24

主题

1265

帖子

1028

银币

后起之秀

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

铜币
362
发表于 2013-7-30 17:34:06 | 显示全部楼层
AFAIK, you have to have the dev tools to compile the code for the desired ACAD version.
I bet someone here at the swamp can do it   
See also, the comments in this thread: http://through-the-interface.typepad.com/through_the_interface/2012/12/purging-unwanted-dgn-linestyle-data-from-an-autocad-drawing-using-net.html
回复

使用道具 举报

44

主题

3166

帖子

2803

银币

中流砥柱

Rank: 25

铜币
557
发表于 2013-7-30 17:38:07 | 显示全部楼层
Here's an Autoloader .bundle compiled to .NET 3.5 for 2012 products... Tested here using Civil 3D 2012 just fine... Just download, unblock, unzip to:
[ol]%AppData%\Autodesk\ApplicationPlugins\
[/ol]
... And restart your session. Lemon squeezy.
Cheers
回复

使用道具 举报

44

主题

3166

帖子

2803

银币

中流砥柱

Rank: 25

铜币
557
发表于 2013-7-30 17:42:14 | 显示全部楼层
Also... For those who'd rather compile themselves, here's the source code (C#)....
Commands.cs
** Note the change from using Autodesk.AutoCAD.ApplicationServices.Core to using Autodesk.AutoCAD.ApplicationServices, and from acdb19.dll to acdb18.dll for the DllImport call.
[ol]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
            {
                // 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();
                }
            }
        }
    }
}
[/ol]
回复

使用道具 举报

44

主题

3166

帖子

2803

银币

中流砥柱

Rank: 25

铜币
557
发表于 2013-7-30 17:42:30 | 显示全部楼层
... And dependent ReferenceFiler.cs
[ol]using System;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace DgnPurger
{
    public class ReferenceFiler : DwgFiler
    {
        public ObjectIdCollection HardPointerIds;
        public ObjectIdCollection SoftPointerIds;
        public ObjectIdCollection HardOwnershipIds;
        public ObjectIdCollection SoftOwnershipIds;

        public ReferenceFiler()
        {
            HardPointerIds = new ObjectIdCollection();
            SoftPointerIds = new ObjectIdCollection();
            HardOwnershipIds = new ObjectIdCollection();
            SoftOwnershipIds = new ObjectIdCollection();
        }

        public override ErrorStatus FilerStatus
        {
            get { return ErrorStatus.OK; }

            set { }
        }

        public override FilerType FilerType
        {
            get { return FilerType.IdFiler; }
        }

        public override long Position
        {
            get { return 0; }
        }

        public override IntPtr ReadAddress() { return new IntPtr(); }
        public override byte[] ReadBinaryChunk() { return null; }
        public override bool ReadBoolean() { return true; }
        public override byte ReadByte() { return new byte(); }
        public override void ReadBytes(byte[] value) { }
        public override double ReadDouble() { return 0.0; }
        public override Handle ReadHandle() { return new Handle(); }
        public override ObjectId ReadHardOwnershipId()
        {
            return ObjectId.Null;
        }
        public override ObjectId ReadHardPointerId()
        {
            return ObjectId.Null;
        }
        public override short ReadInt16() { return 0; }
        public override int ReadInt32() { return 0; }
        public override long ReadInt64() { return 0; }
        public override Point2d ReadPoint2d() { return new Point2d(); }
        public override Point3d ReadPoint3d() { return new Point3d(); }
        public override Scale3d ReadScale3d() { return new Scale3d(); }
        public override ObjectId ReadSoftOwnershipId()
        {
            return ObjectId.Null;
        }
        public override ObjectId ReadSoftPointerId()
        {
            return ObjectId.Null;
        }
        public override string ReadString() { return null; }
        public override ushort ReadUInt16() { return 0; }
        public override uint ReadUInt32() { return 0; }
        public override ulong ReadUInt64() { return 0; }
        public override Vector2d ReadVector2d()
        {
            return new Vector2d();
        }
        public override Vector3d ReadVector3d()
        {
            return new Vector3d();
        }

        public override void ResetFilerStatus() { }
        public override void Seek(long offset, int method) { }

        public override void WriteAddress(IntPtr value) { }
        public override void WriteBinaryChunk(byte[] chunk) { }
        public override void WriteBoolean(bool value) { }
        public override void WriteByte(byte value) { }
        public override void WriteBytes(byte[] value) { }
        public override void WriteDouble(double value) { }
        public override void WriteHandle(Handle handle) { }
        public override void WriteInt16(short value) { }
        public override void WriteInt32(int value) { }
        public override void WriteInt64(long value) { }
        public override void WritePoint2d(Point2d value) { }
        public override void WritePoint3d(Point3d value) { }
        public override void WriteScale3d(Scale3d value) { }
        public override void WriteString(string value) { }
        public override void WriteUInt16(ushort value) { }
        public override void WriteUInt32(uint value) { }
        public override void WriteUInt64(ulong value) { }
        public override void WriteVector2d(Vector2d value) { }
        public override void WriteVector3d(Vector3d value) { }

        public override void WriteHardOwnershipId(ObjectId value)
        {
            HardOwnershipIds.Add(value);
        }

        public override void WriteHardPointerId(ObjectId value)
        {
            HardPointerIds.Add(value);
        }

        public override void WriteSoftOwnershipId(ObjectId value)
        {
            SoftOwnershipIds.Add(value);
        }

        public override void WriteSoftPointerId(ObjectId value)
        {
            SoftPointerIds.Add(value);
        }

        public void reset()
        {
            HardPointerIds.Clear();
            SoftPointerIds.Clear();
            HardOwnershipIds.Clear();
            SoftOwnershipIds.Clear();
        }
    }
}
[/ol]
回复

使用道具 举报

3

主题

81

帖子

4

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
93
发表于 2013-7-30 18:00:25 | 显示全部楼层
DENIM!!!  
about 10,000 linetypes gone from one problem file!  (ok, I may be exaggerating a little.  But probably over a thousand)
easy peasy.
Thanks BB.
When it comes to .net:
回复

使用道具 举报

44

主题

3166

帖子

2803

银币

中流砥柱

Rank: 25

铜币
557
发表于 2013-7-30 18:14:54 | 显示全部楼层
DENIM!!!  
about 10,000 linetypes gone from one problem file!  (ok, I may be exaggerating a little.  But probably over a thousand)
easy peasy.
Thanks BB.
When it comes to .net:

You're welcome; Kean (and others) did the all the work, I just put it together in a saweet looking package.
回复

使用道具 举报

24

主题

1265

帖子

1028

银币

后起之秀

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

铜币
362
发表于 2013-7-30 18:19:54 | 显示全部楼层
I knew someone blackbox would come through quickly!
回复

使用道具 举报

44

主题

3166

帖子

2803

银币

中流砥柱

Rank: 25

铜币
557
发表于 2013-7-30 18:56:54 | 显示全部楼层

That is kind of you to say, R.K. :beer:
回复

使用道具 举报

0

主题

1

帖子

1

银币

初来乍到

Rank: 1

铜币
1
发表于 2013-8-2 03:27:35 | 显示全部楼层
Hi BlackBox
I downloaded "Autodesk DGN Purge.bundle.zip" file and it works perfectly. I finally managed to remove the thousands of linetypes.
Thank you for your help.
Regards
Jan
回复

使用道具 举报

发表回复

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

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

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

GMT+8, 2025-2-5 07:54 , Processed in 0.187033 second(s), 72 queries .

© 2020-2025 乐筑天下

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