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        








« Retro computing with the Raspberry Pi | Main | Animating transient AutoCAD graphics using .NET »

October 05, 2012

Querying for XCLIP information inside AutoCAD using .NET

This question came in recently by email:

I have reached a snag when trying to find the boundaries of external references that have been "xclipped" by the user. Or, to be more precise, I can't even really find the data telling me whether or not the external reference has been "xclipped" at all. I'm wondering if you have any idea how or where I could find this data.

While I found this previous post showing how to perform an XCLIP, I couldn’t find anything showing how to query for XCLIP information.

Here’s some C# code that does just that for a selected block or external reference:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.DatabaseServices.Filters;

using System.Collections.Generic;

 

namespace SpatialFiltering

{

  public class Commands

  {

    const string filterDictName = "ACAD_FILTER";

    const string spatialName = "SPATIAL";

 

    [CommandMethod("DXC")]

    static public void DetectXClip()

    {

      var doc = Application.DocumentManager.MdiActiveDocument;

      var ed = doc.Editor;

 

      // Ask for an xclipped xref to be selected

 

      var peo =

        new PromptEntityOptions(

          "\nSelect xclipped block or xref"

        );

      peo.SetRejectMessage("Must be a block or xref.");

      peo.AddAllowedClass(typeof(BlockReference), false);

 

      var per = ed.GetEntity(peo);

 

      if (per.Status != PromptStatus.OK)

        return;

 

      var tr = doc.TransactionManager.StartTransaction();

      using (tr)

      {

        // Open the selected BlockReference

 

        var br =

          tr.GetObject(per.ObjectId, OpenMode.ForRead)

          as BlockReference;

 

        // To save multiple codepaths with the same message

        // ("No clipping information found"), we'll use a flag to

        // see whether we've found anything

 

        bool found = false;

 

        // It should always be a block reference, but it might

        // not have an extension dictionary

 

        if (

          br != null && br.ExtensionDictionary != ObjectId.Null)

        {

          // The extension dictionary needs to contain a nested

          // dictionary called ACAD_FILTER

 

          var extdict =

            tr.GetObject(br.ExtensionDictionary, OpenMode.ForRead)

            as DBDictionary;

          if (extdict != null && extdict.Contains(filterDictName))

          {

            var fildict =

              tr.GetObject(

                extdict.GetAt(filterDictName), OpenMode.ForRead

              ) as DBDictionary;

            if (fildict != null)

            {

              // The nested dictionary should contain a

              // SpatialFilter object called SPATIAL

 

              if (fildict.Contains(spatialName))

              {

                var fil =

                  tr.GetObject(

                    fildict.GetAt(spatialName), OpenMode.ForRead

                  ) as SpatialFilter;

                if (fil != null)

                {

                  // We have a SpatialFilter: print its bounds

 

                  var ext = fil.GetQueryBounds();

                  ed.WriteMessage(

                    "\nFound clip from {0} to {1}.",

                    ext.MinPoint, ext.MaxPoint

                  );

                  var pts = fil.Definition.GetPoints();

                  foreach (var pt in pts)

                  {

                    ed.WriteMessage(

                      "\nBoundary point at {0}", pt

                    );

                  }

                  found = true;

                }

              }

            }

          }

        }

        if (!found)

        {

          ed.WriteMessage("\nNo clipping information found.");

        }

        tr.Commit();

      }

    }

  }

}

When we run the DXC command and selected an XCLIPped block or external reference, we see its clipping information printed to the command-line:

Command: DXC

Select xclipped block or xref:

Found clip from (4.05811894970383,5.24702344885421,-10000000000) to (6.37251127340078,8.93717310957857,10000000000).

Boundary point at (4.39197755714056,8.93717310957849)

Boundary point at (4.05811894970388,7.08011285053157)

Boundary point at (4.71314514170174,5.24702344885429)

Boundary point at (5.97105160306316,6.93165698166899)

Boundary point at (6.13163547119819,7.89430470599807)

Boundary point at (6.37251127340073,8.34888837222314)

blog comments powered by Disqus

Feed/Share

10 Random Posts