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)

4 responses to “Querying for XCLIP information inside AutoCAD using .NET”

  1. This was helpful, Thanks!

    Just one additional question, how would you go about determining if the spatial filter was inverted?

    The SpatialFilter class doesn't appear to have easy access to this data and I've been unable to figure out how to retrieve it.

  2. My pleasure!

    I don't think I've ever created an inverted Spatial Filter. If you can tell me some steps to do so, I'll see how you can query the fact that it's inverted.

    Kean

  3. In AutoCAD when you select a block reference with a clip boundary you should see an arrow on the boundary, simply click it and it will invert the clipping.

    When looking at the DXF of such a drawing it appears that the spatial filter has an extension dictionary which contains an Xrecord, but when I attempt to get the extension dictionary from the spatial filter in code it comes back as null. I'm using RealDWG 2013 in C++, but I expect the concepts should be the same.

  4. Thanks, Mike - that helped a lot.

    Much to my surprise, it turns out this has been exposed by neither ObjectARX nor .NET.

    I'd suggest posting via ADN or to the AutoCAD .NET Discussion Group to request that this be addressed.

    Kean

Leave a Reply to Kean Walmsley Cancel reply

Your email address will not be published. Required fields are marked *