« Getting to know the Project Draw API | Main | A tale of tight turnaround »

July 02, 2008

Conditional selection of AutoCAD entities using .NET

This post was inspired by a comment on this previous post, where we looked at some code to select entities on a specific layer. The question was regarding how best to select entities from multiple layers: the selection filtering mechanism inside AutoCAD makes this very easy, and can cope with composition of conditions related to various entity properties.

The basic concept is to enclose sets of entity properties for which you wish to filter with tags indicating the composition of the conditions: for "or" you enclose the conditions with "<or" and "or>" and for "and" you use "<and" and "and>". Wow: I can safely say that that's probably the only sentence I've ever written that has 6 of the last 10 words being "and". :-)

Let's take a concrete example: let's say we want to select all lines on on layer 0 and all the circles with radii greater than 10.'s how we would compose the conditions, in pseudo-code:

  • <or
    • <and
      • Layer == "0"
      • Entity type == "LINE"
    • and>
    • <and
      • Entity type == "CIRCLE"
      • Radius >= 10.0
    • and>
  • or>

This translates into the following C# code - for clarity I've left the specific properties/values hard-coded, but clearly it would be straightforward to ask the user or pick them out of a database, as needed.

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;


namespace EntitySelection

{

  public class Commands

  {

    [CommandMethod("SEWP")]

    static public void SelectEntitiesWithProperties()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;


      // Build a conditional filter list so that only

      // entities with the specified properties are

      // selected


      TypedValue[] tvs =

        new TypedValue[] {

          new TypedValue(

            (int)DxfCode.Operator,

            "<or"

          ),

          new TypedValue(

            (int)DxfCode.Operator,

            "<and"

          ),

          new TypedValue(

            (int)DxfCode.LayerName,

            "0"

          ),

          new TypedValue(

            (int)DxfCode.Start,

            "LINE"

          ),

          new TypedValue(

            (int)DxfCode.Operator,

            "and>"

          ),

          new TypedValue(

            (int)DxfCode.Operator,

            "<and"

          ),

          new TypedValue(

            (int)DxfCode.Start,

            "CIRCLE"

          ),

          new TypedValue(

            (int)DxfCode.Operator,

            ">="

          ),

          new TypedValue(

            (int)DxfCode.Real, // Circle Radius

            10.0

          ),

          new TypedValue(

            (int)DxfCode.Operator,

            "and>"

          ),

          new TypedValue(

            (int)DxfCode.Operator,

            "or>"

          )

        };


      SelectionFilter sf =

        new SelectionFilter(tvs);

      PromptSelectionResult psr =

        ed.SelectAll(sf);


      ed.WriteMessage(

        "\nFound {0} entit{1}.",

        psr.Value.Count,

        (psr.Value.Count == 1 ? "y" : "ies")

      );

    }

  }

}

By the way - you can also choose to perform an "exclusive or" test by using "<xor" and "xor>".

To try out this code, draw a number of lines in a blank drawing, and run the SEWP command. This simply tells you how many entities met the selection criteria - it doesn't leave them selected for use by further commands. You can then see how drawing circles of varying radii changes the number of entities selected by the command.

On a final note... SelectionFilters can be used either non-interactively (as in this example, via the SelectAll() method) or interactively (via GetSelection(), SelectWindow(), SelectCrossingPolygon(), SelectFence(), etc.). I've shown simple uses of SelectionFilters in previous posts, but it's also possible to use quite complicated groupings of conditions - as we've scratched the surface of in this post.

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83452464869e200e5537991ff8833

Listed below are links to weblogs that reference Conditional selection of AutoCAD entities using .NET:

Comments

Thanks Kean,

This question has a very thin relatationship with the post, but still posting it in a hope that possibly this could even turn out to be a post one day!

Okay, the question is that what should I do if I want to expose properties of my custom entity to AutoCAD's filter mechanism. For example, if I have a custom entity called myCircle, derived from AcDbEntity has a property mRadius. I want the users to use AutoCAD standard mechanism to filter all myCircle entities with values of mRadius is greater than 20.

Thanks,
Narayanan

Hi Narayanan,

Actually this is reasonably closely related, but unfortunately I don't know of a way to customize the FILTER dialog: there would need to be a way to connect descriptions of properties with their underlying DXF group-code (and the datatype they contain).

That said, the FILTER command only really uses the internal mechanism described in this post, so you could implement your own tailored feature that works with your objects.

I hope this helps,

Kean

The "DxfCode.Operator" dose not exist in AutoCAD2006 .Net API. Any good advise?

I don't know whether this means the API wasn't present then, which is quite possible.

You could try replacing DxfCode.Operator with -4 (its value), in case that helps.

Kean

Hi Kean,
How to prevent selecting objects of a layer

Try using the "<not" / "not>" operator.

Kean

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been posted. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment

RSS Feed

Search