Selection Set

Selection Set

Ranjit_Singh
Advisor Advisor
2,667 Views
16 Replies
Message 1 of 17

Selection Set

Ranjit_Singh
Advisor
Advisor

Hi everyone, I am fairly new to LISP. I tried creating a selection set. Below is my LISP routine

 

(defun c:selal()
(setq vscbp (getpoint "\n Specify base point: "))
(setq ss1 (ssget))
(setq ss2 (ssget "P" '((-4 . "<OR")(0 . "TEXT")(0 . "MTEXT")(0 . "MULTILEADER")(0 . "LEADER")(0 . "DIMENSION")(-4 . "OR>"))))
(command "._SELECT" ss1 "")
(setq ss3 (ssget "P" '((-4 . "<OR")(0 . "HATCH")(0 . "LINE") (0 . "ARC") (0 . "CIRCLE") (0 . "SPLINE") (0 . "POLYLINE") (0 . "2D POLYLINE") (0 . "3D POLYLINE")(-4 . "OR>"))))
)

I am trying to make a selection in the drawing and then filter annotation objects to make ss2. I then need ss3 which is everything from ss1 less the annotation objects. Questions is: After I create ss2, is there a cleaner way to make ss3, which is everything in ss1 less ss2? I am manually typing out everything I can imagine for ss3 and I am sure I missed quite a bit. I want to make sure I get everything from ss1 less the annotation objects. Thanks.

0 Likes
Accepted solutions (1)
2,668 Views
16 Replies
Replies (16)
Message 2 of 17

ВeekeeCZ
Consultant
Consultant
Accepted solution

Oneway may be this..

 

 

(setq ss1 (ssget))
(setq ss3 (ssget "P" '((-4 . "<NOT") (0 . "*TEXT,*LEADER,DIMENSION") (-4 . "NOT>"))))
Message 3 of 17

Ranjit_Singh
Advisor
Advisor

Thanks. One last question. Is there a way to avoid doing a selection again for ss3? I am trying to eliminate

(setq ss1 (ssget))

from

 

(setq ss1 (ssget))
(setq ss3 (ssget "P" '((-4 . "<NOT") (0 . "*TEXT,*LEADER,DIMENSION") (-4 . "NOT>"))))

I am currently doing this by using this

(command "._SELECT" ss1 "")

Is there a possible way to call ss1 by name? Something like

 

(setq ss3 (ssget "ss1" '((-4 . "<NOT") (0 . "*TEXT,*LEADER,DIMENSION") (-4 . "NOT>")))) 

Of corse that gives me an error, but I jus wanted to know if there was a similar alternative that would avoid me adding an extra line to my code. Since I already make a selection at the begining of the code, I should be able to call ss1 later in the code, right?

 

0 Likes
Message 4 of 17

ВeekeeCZ
Consultant
Consultant

Not with regular ssget function... as far as I know. But...

 

Instead of using autocad's command "SELECT" you can use (sssetfirst nil ss1) and then implied selection - which is probably better.

 

(sssetfirst nil ss1)
(setq ss3 (ssget "_I" '((-4 . "<NOT") (0 . "*TEXT,*LEADER,DIMENSION") (-4 . "NOT>"))))
  

 

Or you can use ExpressTools function.

 

(setq ss3 (acet-ss-ssget-filter ss1 '((-4 . "<NOT") (0 . "*TEXT,*LEADER,DIMENSION") (-4 . "NOT>"))))

But I would probably go the first way.

 

0 Likes
Message 5 of 17

Ranjit_Singh
Advisor
Advisor

BeekeeCZ, Thanks! It's interesting you mentioned express tools. I am trying to use the bscale command from express tools. I want it to scale a block vertically and so am using the bscale command. However, AutoCAD prompts for all the bscale parameters after encountering the bscale command? I am trying to pass those values from LISP but it isn't working. Any advise. I am not sure what I am doing wrong. Thanks in advance for all your input.

 

((C:BSCALE) entlast "" "" 0.5 "")
0 Likes
Message 6 of 17

ВeekeeCZ
Consultant
Consultant

Hello in the new year.

 

 

You need to look into c:\Program Files\Autodesk\AutoCAD 2015\Express\bscale.lsp file to find a proper function.

 

(if (not acet-bscale) (load "bscale.lsp"))
(acet-bscale (ssadd (entlast)) 0 0.5 0.5 0.5)

Or... you can use the regular SCALE command

 

(command "_.SCALE" (entlast) "" "_none" (trans (cdr (assoc 10 (entget (entlast)))) 0 1) 0.5)

 

0 Likes
Message 7 of 17

Ranjit_Singh
Advisor
Advisor

Hello and happy new year. Thanks! That worked like magic. The scale command did not help as I just needed to scale in the vertical direction. My next task is to move all the annotation objects to their original points in the new scaled block. I will give it a try and post back any issues I face. Thanks again forall your input.

0 Likes
Message 8 of 17

Ranjit_Singh
Advisor
Advisor

Hi BeeKeeZ, back again with new stumble block. I finished the following LISP.

 

(defun c:vsc()
(setq oldosmode (getvar "osmode"))
(setvar "osmode" 2081)
(setq vscall (ssget))
(setq vscbp (getpoint "\n Specify base point: "))
(setq vscscale (getreal "\nSpecify vertical scaling factor: "))
(setq vscanno (ssget "P" '((-4 . "<OR")(0 . "*TEXT*,*LEADER*,*DIMENSION*")(-4 . "OR>"))))
(sssetfirst nil vscall)
(setq vscnotanno (ssget "_I" '((-4 . "<NOT") (0 . "*TEXT*,*LEADER*,*DIMENSION*,*PROFILE*,*LABEL*") (-4 . "NOT>"))))
(command "._copybase" vscbp vscnotanno "")
(command "._pasteblock" vscbp "")
(if (not acet-bscale) (load "bscale.lsp"))
(acet-bscale (ssadd (entlast)) "" 0 vscscale 0)
(sssetfirst nil vscnotanno)
(command "._erase" "previous" "")
(setvar "osmode" oldosmode)
(princ)
)

 

 Pls help me verify if this is the best way to achieve the results or maybe any suggestions for improvement? Also,  how can I move the annotation and leaders to the new position. I dont want to scale them since all annotation needs to be the same size, but simply move them to their respective original positions. The logic I think whould be calculating the Y distance between the leaders arrowhead and base point and/or, between other annotation and the base point and then simply move all annotation by distance times scale factor. Can't seem to figure out how to get started though. I already have all the annotation objects in a selection set. So basically just should be able to cycle through each one, perform the logic and that's it. Seems simple while writing Smiley Wink Any pointers on getting started will be appreciated. Thanks.

0 Likes
Message 9 of 17

ВeekeeCZ
Consultant
Consultant

@Ranjit_Singh wrote:

Hi BeeKeeZ, back again with new stumble block. I finished the following LISP.

 

...

 Pls help me verify if this is the best way to achieve the results or maybe any suggestions for improvement? Also,  how can I move the annotation and leaders to the new position. I dont want to scale them since all annotation needs to be the same size, but simply move them to their respective original positions. The logic I think whould be calculating the Y distance between the leaders arrowhead and base point and/or, between other annotation and the base point and then simply move all annotation by distance times scale factor. Can't seem to figure out how to get started though. I already have all the annotation objects in a selection set. So basically just should be able to cycle through each one, perform the logic and that's it. Seems simple while writing Smiley Wink Any pointers on getting started will be appreciated. Thanks.


Hi, try this code. I made some improvements... but still very simple to understand.

 

Spoiler
(defun c:VSC ( / *error* adoc oldosmode vscall vscbp vscscale vscanno vscnotanno ent typ i why)

    (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break,end"))
      (princ (strcat "\nError: " errmsg)))
    (setvar "osmode" oldosmode)
    (vla-endundomark adoc)
    (princ))

  
  (setq oldosmode (getvar "osmode"))
  (vla-startundomark (setq adoc (vla-get-activedocument (vlax-get-acad-object))))
  (setvar "osmode" 2081)
  
  (if (setq vscall (ssget))
    (progn
      (initget 1)
      (setq vscbp (getpoint "\nSpecify base point: "))
      (initget 1)
      (setq vscscale (getdist "\nSpecify vertical scaling factor: "))
      (setq vscanno (ssget "_P" '((0 . "*TEXT,*LEADER,*DIMENSION"))))
      (sssetfirst nil vscall)
      (if (setq vscnotanno (ssget "_I" '((-4 . "<NOT") (0 . "*TEXT,*LEADER,DIMENSION") (-4 . "NOT>"))))
	(progn
	  (command "._copybase" "_none" vscbp vscnotanno ""
		   "._pasteblock" "_none" vscbp "")
	  (if (not acet-bscale) (load "bscale.lsp"))
	  (acet-bscale (ssadd (entlast)) "" 0 vscscale 0)
	  (command "._erase" vscnotanno "")))
      (if vscanno
	(repeat (setq i (sslength vscanno))
	  (setq ent (ssname vscanno (setq i (1- i)))
		typ (cdr (assoc 0 (entget ent)))
		why (cond ((or (wcmatch typ "MTEXT,LEADER")
			       (and (wcmatch typ "TEXT")
				    (= 0 (cdr (assoc 72 (entget ent))))
				    (= 0 (cdr (assoc 73 (entget ent))))))
			   (caddr (assoc 10 (entget ent))))
			  ((wcmatch typ "TEXT")
			   (caddr (assoc 11 (entget ent))))
			  ((wcmatch typ "MULTILEADER")
			   (caddr (caddr (vl-remove-if-not '(lambda (x) (vl-position (car x) '(10))) (entget ent)))))
			  ((and (wcmatch typ "DIMENSION")
				(= "AcDbRotatedDimension" (cdr (assoc 100 (reverse (entget ent)))))
				(equal (caddr (assoc 13 (entget ent)))
				       (caddr (assoc 14 (entget ent)))
				       1e-2))
			   (caddr (assoc 13 (entget ent))))))
	  (if why (command "._move" ent "" '(0 0 0) (list 0. (* (- why (cadr vscbp)) (1- vscscale)) 0.)))
       ))))
  (*error* "end")
)

some notes:
- i had to exclude C3D ents.. (profile, *label*) they don't has simple insertion point..
- horizontal dimensions are moved, the others are excluded
- note red "_none" - it turn off the osnap function. Very important, otherwise you'll unpredictable result

 

 

This routine won't be any fast - I used simple _MOVE command... Maybe some come up with something faster...

0 Likes
Message 10 of 17

Ranjit_Singh
Advisor
Advisor

Thanks! works perfect. I am going to spend time to understand this (and come back with any questions, in case I dont understand any code). This one will save me a lot of time. Appreciate all your help.

0 Likes
Message 11 of 17

Ranjit_Singh
Advisor
Advisor

Hi BeekeeCZ, hoping you can provide some feedback. The LISP works perfectly. However, I noticed that some of the annotation Rotated Dimensions are not moved while others are. I looked further into the matter; and basically all the rotated dimensions that had their color set in properties to "Yellow", "Blue" etc. (basically not to "By Layer") did not get selected and moved. That was strange. I thought that the gruop code 0 meant select an entity type and dont even worry about the color. But apparently it is inherently grabbing only objects that have color set "by layer" and ofcorse the type we describe in the filter. Does that mean now I need to make sure that all entities are set to color "by layer" and then apply the LISP? That makes it a little more cumbersome. Kindly advise.

0 Likes
Message 12 of 17

ВeekeeCZ
Consultant
Consultant
Post a sample of dwg file where this occurs.
0 Likes
Message 13 of 17

Ranjit_Singh
Advisor
Advisor

Hi BeekeeCZ, see drawing file attached. I was thinking it is only the ones where color is not set by layer, but I just noticed that a few others which have color set to by layer also do not move or scale. So I am thinking it is something else in the code and not the color property. Thanks.

0 Likes
Message 14 of 17

ВeekeeCZ
Consultant
Consultant

@Ranjit_Singh wrote:

Hi BeekeeCZ, see drawing file attached. I was thinking it is only the ones where color is not set by layer, but I just noticed that a few others which have color set to by layer also do not move or scale. So I am thinking it is something else in the code and not the color property. Thanks.


It has nothing to do with a color. Problem was too big precision - didn't know you working in mm (that's why always post some sample)

 

Spoiler
(defun c:VSC ( / *error* adoc oldosmode vscall vscbp vscscale vscanno vscnotanno ent typ i why)

    (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break,end"))
      (princ (strcat "\nError: " errmsg)))
    (setvar "osmode" oldosmode)
    (vla-endundomark adoc)
    (princ))

  
  (setq oldosmode (getvar "osmode"))
  (vla-startundomark (setq adoc (vla-get-activedocument (vlax-get-acad-object))))
  (setvar "osmode" 2081)
  
  (if (setq vscall (ssget))
    (progn
      (initget 1)
      (setq vscbp (getpoint "\nSpecify base point: "))
      (initget (+ 1 2 4))
      (setq vscscale (getdist "\nSpecify vertical scaling factor: "))
      (setq vscanno (ssget "_P" '((0 . "*TEXT,*LEADER,*DIMENSION"))))
      (sssetfirst nil vscall)
      (if (setq vscnotanno (ssget "_I" '((-4 . "<NOT") (0 . "*TEXT,*LEADER,DIMENSION") (-4 . "NOT>"))))
	(progn
	  (command "._copybase" "_none" vscbp vscnotanno ""
		   "._pasteblock" "_none" vscbp "")
	  (if (not acet-bscale) (load "bscale.lsp"))
	  (acet-bscale (ssadd (entlast)) "" 0 vscscale 0)
	  (command "._erase" vscnotanno "")))
      (if vscanno
	(repeat (setq i (sslength vscanno))
	  (setq ent (ssname vscanno (setq i (1- i)))
		typ (cdr (assoc 0 (entget ent)))
		why (cond ((or (wcmatch typ "MTEXT,LEADER")
			       (and (wcmatch typ "TEXT")
				    (= 0 (cdr (assoc 72 (entget ent))))
				    (= 0 (cdr (assoc 73 (entget ent))))))
			   (caddr (assoc 10 (entget ent))))
			  ((wcmatch typ "TEXT")
			   (caddr (assoc 11 (entget ent))))
			  ((wcmatch typ "MULTILEADER")
			   (caddr (caddr (vl-remove-if-not '(lambda (x) (vl-position (car x) '(10))) (entget ent)))))
			  ((and (wcmatch typ "DIMENSION")
					(= "AcDbRotatedDimension" (cdr (assoc 100 (reverse (entget ent)))))
				(equal (cdr (assoc 50 (entget ent)))
				       0.
				       1e-4))
			   (caddr (assoc 13 (entget ent))))))
	  (if why (command "._move" ent "" '(0 0 0) (list 0. (* (- why (cadr vscbp)) (1- vscscale)) 0.)))
       ))
      ))
  (*error* "end")
)

 

0 Likes
Message 15 of 17

Ranjit_Singh
Advisor
Advisor

BeekeeCZ thanks a million. The new LISP works great but I still see one dimension not being moved. Please see before and after screen shot. Maybe it's an issue at my end with some settings. I notice that the dimension is aligned different than the others (it spans vertically and not horizontally, like the rest which move perfectly). Could this be the new issue? Thanks.

0 Likes
Message 16 of 17

ВeekeeCZ
Consultant
Consultant
I know that - and I told you before (see post #9).
Do you really need it? It can't be just moved, I must be scaled as well. Then the label should be scaled back... complicated.
0 Likes
Message 17 of 17

Ranjit_Singh
Advisor
Advisor

BeekeeCZ, thanks for all your help. I can just move that one little label 🙂

0 Likes