AfraLISP - Learn AutoLISP for AutoCAD productivity

Selection Sets

by Kenny Ramage

When you work with AutoCAD, you very seldom work with only one entity or, for that matter, one type of entity. To be able to work efficiently with a group, or selection set, of entities, you need to be able to place them in one place and work on them as a group. You might also want to filter the entities so that only a certain type is within the group.
The AutoLisp function that enables you to do this is the (ssget) function.

	(setq sel1 (ssget))

This function allows you to select as many entities as you like using any selection method, such as Window, Crossing, Fence, etc.
You can also include a selection set filter within the function.

	(setq sel1 (ssget "x"))

The "x" following the (ssget) is the most basic of filters. This filter selects ALL. This is quite sufficient in some circumstances but you can filter the entities further by following the "x" with a list of associative codes. For example :

	(setq sel1 (ssget "x" '((8 . "STEEL"))))

This expression would create a selection set containing only entities that are on the STEEL layer. (Associative code 8 refers to the Layer.)
You can use more than one associative code if you desire :

	(setq sel1 (ssget "x" '((0 . "CIRCLE")(8 . "STEEL"))))

The above example would create a selection set of all CIRCLES on the Layer STEEL.

If you don't want to search the entire drawing for a selection set, but would rather use a select by Window or Crossing, then just omit the "x" option.

	(setq sel1 (ssget '((0 . "CIRCLE")(8 . "STEEL"))))

This example permits the user to select entities using any selection method he prefers but, will only create a selection set of CIRCLES on Layer STEEL.

Try this next :

	(setq sel1 (ssget "w" "\nSelect Objects by Window: "))

Doesn't work, does it?
You cannot use prompts within the (ssget) function. But, you can use other AutoCad functions to feed the required information to the (ssget) function.

	(prompt "\nSelect Objects by Window")
	(setq p1 (getpoint "\nFirst Corner: "))
	(setq p2 (getpoint p1 "\nSecond Corner: "))
	(setq sel1 (ssget "w" p1 p2))

You can also use other selection options with (ssget)

	(setq sel1 (ssget "P"))

This will create a selection set of all "Previous" entities.
Other options available are "L" for "Last" and "I" for "Implied".

You can also use logical filters when creating selection sets.
Have a look at a previous example :

	(setq sel1 (ssget '((0 . "CIRCLE")(8 . "STEEL"))))

What we are saying here is :

"Create a selection set of all the CIRCLES from the entities selected AND they must be on Layer "STEEL".

AND is the default logical filter when you string associative codes together.

You can also use the OR logical filter, but to do this you must inform AutoLisp first. To do this you use a special type of associative code, the -4.

(setq sel1 (ssget '((-4 . "<OR")(8 . "STEEL")(8 . "PIPE")(-4 . "OR>"))))

This would create a selection set of all entities on Layer STEEL "OR" on Layer PIPE.

As well as logical filters, you can also have relation filters :

	(setq sel1 (ssget '(0 . "CIRCLE")(-4 . ">=")(40 . 2.0)))

This would create a selection set of all CIRCLES with a RADIUS (group 40) of greater or equal to 2.0.

All of these different types of filters can be nested.

You can also Add and Delete entities from selection sets. Three guesses what these function names are? You were right first time, (ssadd) and (ssdel).

	(setq sel1 (ssget))
	;create the first selection set
	(setq ent (car (entsel))
	;select an entity and use (car (ensel))
	; to retrieve the entity name
	(setq sel1 (ssadd ent sel1))
	;add the entity to the selection set

To delete an entity is exactly the same except for the last line :

	(setq sel1 (ssdel ent sel1))

But what would you do if you wanted to add two selection sets together? The following explains how to create a "Union" between 2 selection sets :

	(setq ct 0)
	;set counter to zero
	(repeat (sslength sel2)
	;get the number of items in selection set 2
	;and loop that number of times
	(ssadd (ssname sel2 ct) sel1)
	;get the name of the entity from selection set 2
	;by using the counter index number and add it to
	;selection set 1
	(setq ct (1+ ct))
	;increment the counter by 1
	);end repeat

Here's an example of a simple routine that will count the number of blocks contained within a drawing :

(defun c:bcount ( / p1 b a n)
	(setq p1 (getstring "\Name of Block : "))
	;get the name of the block
	(setq b (cons 2 p1))
	;construct a dotted pair - code 2 is for blocks
	(setq a (ssget "x" (list b)))
	;filter for the block name
	(if (/= a nil)
	;check if there are any blocks of that name
	   ;if there is…
		(setq n (sslength a))
		;count the number of blocks
		(alert (strcat "\nThere are " (itoa n) " in the DataBase"))
		;display the result
	   ;if there are no blocks
		(alert "\nThere are none in the DataBase")
		;inform the user

Well that's about it with selection sets. Just remember that you can save yourself an awful lot of work by using selection sets with filters. Filter at the source rather than programmatically trying to filter out the undesirable entities at a later stage. Ta Ta for now…