September 2014

Sun Mon Tue Wed Thu Fri Sat
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        








« Adding speech recognition to AutoCAD via Kinect | Main | Coming soon: Kinect for your PC »

November 21, 2011

Generating preview images for all blocks in an AutoCAD drawing using .NET

This was a nice little solution I saw provided recently by Viru Aithal from DevTech India. It’s a simple command to open a drawing and generate preview icons for each of the blocks it contains. It forces an icon to be generated – when it doesn’t already exist – via Viru’s old trick of using InvokeMember() to call IAcadDocument::SendCommand() via COM (which is synchronous, where Document.SendStringToExecute() is asynchronous and only executes once the command has completed).

Viru’s trick allows him to call SendCommand() without creating a dependency on the AutoCAD Type Library (something developers often prefer to avoid, as it simplifies supporting multiple AutoCAD product versions). A similar effect can presumably be achieved using Type Embedding, but I like Viru’s approach for just the odd function call.

Here’s the C# code:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.Runtime;

using System.IO;

 

namespace BlockPreviews

{

  publicclassCommands

  {

    [CommandMethod("GBP", CommandFlags.Session)]

    staticpublicvoid GenerateBlockPreviews()

    {

      Editor ed =

        Application.DocumentManager.MdiActiveDocument.Editor;

 

      PromptFileNameResult res =

        ed.GetFileNameForOpen(

          "Select file for which to generate previews"

        );

      if (res.Status != PromptStatus.OK)

        return;

 

      Document doc = null;

 

      try

      {

        doc =

          Application.DocumentManager.Open(res.StringResult, false);

      }

      catch

      {

        ed.WriteMessage("\nUnable to read drawing.");

        return;

      }

 

      Database db = doc.Database;

 

      string path = Path.GetDirectoryName(res.StringResult),

             name = Path.GetFileName(res.StringResult),

             iconPath = path + "\\" + name + " icons";

 

      int numIcons = 0;

 

      Transaction tr =

        doc.TransactionManager.StartTransaction();

      using (tr)

      {

        BlockTable table =

          (BlockTable)tr.GetObject(

            db.BlockTableId, OpenMode.ForRead

          );

 

        foreach (ObjectId blkId in table)

        {

          BlockTableRecord blk =

            (BlockTableRecord)tr.GetObject(

              blkId, OpenMode.ForRead

            );

 

          // Ignore layouts and anonymous blocks

 

          if (blk.IsLayout || blk.IsAnonymous)

            continue;

 

          // Attempt to generate an icon, where one doesn't exist

 

          if (blk.PreviewIcon == null)

          {

            object ActiveDocument = doc.AcadDocument;

            object[] data = { "_.BLOCKICON " + blk.Name + "\n" };

            ActiveDocument.GetType().InvokeMember(

              "SendCommand",

              System.Reflection.BindingFlags.InvokeMethod,

              null, ActiveDocument, data

            );

          }

 

          // Hopefully we now have an icon

 

          if (blk.PreviewIcon != null)

          {

            // Create the output directory, if it isn't yet there

 

            if (!Directory.Exists(iconPath))

              Directory.CreateDirectory(iconPath);

 

            // Save the icon to our out directory

 

            blk.PreviewIcon.Save(

               iconPath + "\\" + blk.Name + ".bmp"

            );

 

            // Increment our icon counter

 

            numIcons++;

          }

        }

        tr.Commit();

      }

      doc.CloseAndDiscard();

 

      ed.WriteMessage(

        "\n{0} block icons saved to \"{1}\".", numIcons, iconPath

      );

    }

  }

}

When we run the GBP command use it to select a number of AutoCAD’s sample files containing blocks, we see it generates a number of icons for each:

Command: GBP

13 block icons saved to "C:\Program Files\Autodesk\AutoCAD 2012 -

English\Sample\Dynamic Blocks\Annotation - Imperial.dwg icons".

Command: GBP

10 block icons saved to "C:\Program Files\Autodesk\AutoCAD 2012 -

English\Sample\Dynamic Blocks\Architectural - Imperial.dwg icons".

Command: GBP

6 block icons saved to "C:\Program Files\Autodesk\AutoCAD 2012 -

English\Sample\Dynamic Blocks\Electrical - Imperial.dwg icons".

Command: GBP

11 block icons saved to "C:\Program Files\Autodesk\AutoCAD 2012 -

English\Sample\Dynamic Blocks\Civil - Imperial.dwg icons".

While the code executes, you’ll see the BLOCKICON command displaying a dialog for each block it processes, but once completed the drawing is closed (without being saved to disk).

Here’s what we see in Windows Explorer:

Block preview images saved to disk

 

 

Update:

See this post for an improved technique for achieving this.

blog comments powered by Disqus

Feed/Share

10 Random Posts