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>
- <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.

Subscribe
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
Posted by: Narayanan | July 02, 2008 at 10:15 AM
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
Posted by: Kean | July 07, 2008 at 12:25 PM
The "DxfCode.Operator" dose not exist in AutoCAD2006 .Net API. Any good advise?
Posted by: GanQuan | September 21, 2008 at 08:29 PM
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
Posted by: Kean | September 22, 2008 at 08:09 PM
Hi Kean,
How to prevent selecting objects of a layer
Posted by: sham | May 30, 2009 at 09:34 AM
Try using the "<not" / "not>" operator.
Kean
Posted by: Kean Walmsley | May 30, 2009 at 01:30 PM