Selection set by rotation angle

Selection set by rotation angle

dlbsurveysuk
Collaborator Collaborator
1,195 Views
19 Replies
Message 1 of 20

Selection set by rotation angle

dlbsurveysuk
Collaborator
Collaborator

I need to select a single text object to obtain it's rotation angle, then make a selection set of all text on a layer, that is at that same rotation angle, together with all blocks on another layer that are at that same rotation angle. Then rotate all the selected blocks/text to zero.

 

I think this gets all text on layer LTEXT -

 

 

(setq LTXTLST (ssget '((8 . "LTEXT") (0 . "text"))))

 

 

and this gets all blocks on layer LX -

 

 

(setq LXLST (ssget (list (cons 0  "INSERT")
             (cons 8 "LX")
             )))

 

 

at this point I'm stuck about how to extract the initial rotation angle and how to isolate a selection from the above with that rotation angle. I'm assuming it'll be using some VLA / VLAX commands (that I know very little about) within a loop that will check each object and add it to a list if it matches?

I've already got a routine that'll rotate all the objects/text about their insertion points, I just need to make the initial selection....

Thanks.

 

0 Likes
Accepted solutions (2)
1,196 Views
19 Replies
Replies (19)
Message 2 of 20

-didier-
Advisor
Advisor

Bonjour @dlbsurveysuk 

 

It is possible to click the text whose angle of rotation we want to know,

then to make a selection set of the other texts, then to make a loop on the first selection set by comparing the rotations,

if it is equal to the example, we can add it to the second selection set.

The selection ss2 contains all texts entities who have the same rotation angle than the example text entity.

(setq text_example (car (entsel "\nSelect the text example\n")))
(prompt "\nSelection of other texts\n")
(setq ss1 (ssget '((0 . "text"))))
(setq ss2 (ssadd))
(setq rotexample (cdr (assoc 50 (entget text_example))))
(repeat (setq x (sslength ss1))
  (if (= rotexample (cdr (assoc 50 (entget (ssname ss1 (setq x (1- x)))))))
    (ssadd (ssname ss1 x) ss2)
    )  
  )
(sssetfirst nil ss2)  

Amicalement

Éternel débutant.. my site for learning : Programmer dans AutoCAD

DA

EESignature

Message 3 of 20

paullimapa
Mentor
Mentor

TRot.lsp should do the trick for you

; trot function
; rotates selected Texts & Blocks matching selected Text rotation to zero
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/selection-set-by-rotation-angle/m-p/11697042#M442315
(princ"\nLoading Function...")(princ)
(defun c:trot (/ ed rot ss txt) 
 (princ"\nSelect Text Object To Get Rotation...")
 (while (not txt)
  (setq txt (ssget "_+.:E:S"'((0 . "TEXT"))))
  (if(not txt)
   (progn
    (princ"\nObject Selected is Not Text...")(princ)
   )
   (progn
    (setq ed(entget(ssname txt 0))) ; get entity data
    (setq rot(cdr(assoc 50 ed))) ; get rotation angle in degrees
    (princ(strcat"\nOnly Texts & Blocks With Matching [" (rtos (* 180.0 (/ rot pi)) 2 4) "] Degree Rotation Will Be Selected..."))(princ)
    (setq ss 
     (ssget
      (list
        '(-4 . "<OR")
            '(-4 . "<AND") '(0 . "TEXT")  (cons 50 rot) '(-4 . "AND>")
            '(-4 . "<AND") '(0 . "INSERT") (cons 50 rot) '(-4 . "AND>")
        '(-4 . "OR>")
      ) ; list
     ) ; ssget
    ) ; setq
    (if ss
      (progn
       (foreach ent (setq entlst(mapcar 'cadr (ssnamex ss))) ; loop through all entties from ss converted to list 
        (if (= 'ename (type ent)) ; confirm is entity
         (progn
          (setq ed (entget ent)) ; get entity data
          (entmod (subst (cons 50 0.0)(assoc 50 ed) ed)) ; substitute 0 degree rotation
          (entupd ent) ; update entitity
         )
        ) ; if entity 
       ) ; foreach loop
       (alert"Operation Completed.")
      ) ; progn
      (alert"No Matching Texts & Blocks Selected.")     
    ) ; if
   ) ; progn
  ) ; if
 ) ; while
 (princ)
) ; defun
(princ"\n...Loaded Successfully...Enter Command [TRot] to Execute.")(princ)

Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 4 of 20

Sea-Haven
Mentor
Mentor
Accepted solution

My $0.05 added current space check also.

 

 

(defun c:tang ( / ang ss1 x ent)
(setq ang (cdr (assoc 50 (entget (car (entsel "\nPick a text for angle "))))))
(setq ss1 (ssget "X" '((8 . "LTEXT") (0 . "TEXT")(cons 50 ang)(cons 410 (getvar 'ctab)))))
(if (= ss1 nil)
(alert "No text found")
(repeat (setq x (sslength ss1))
 (setq ent  (entget (ssname ss1 (setq x (1- x)))))
 (entmod (subst (cons 50 ang) (assoc 50 ent) ent))
)
)
(princ)
)

 

 Can change entsel to a ssget to force a pick text, no error checks can be added also, same with match text select layer.

Message 5 of 20

Kent1Cooper
Consultant
Consultant

This is the kind of thing that can [depending on how the angle was determined] come out with tiny differences in value [perhaps ten or twelve decimal places down] that may foil the (=) function that looks for exact equality, or similarly inclusion of the (50 . SourceObjectRotation) entry in an (ssget) filter.  I would suggest testing in a matter such as this, with a fuzz factor:

  (if (equal SourceObjectRotation TestObjectRotation 1e-4)

    ... put it in the restricted selection set, or whatever ...

  )

Kent Cooper, AIA
Message 6 of 20

dlbsurveysuk
Collaborator
Collaborator

Thanks but this is giving me "No Matching Texts & Blocks Selected." (test drawing attached)

0 Likes
Message 7 of 20

dlbsurveysuk
Collaborator
Collaborator

Thanks but this is giving me "error: bad SSGET list" (test drawing attached)

0 Likes
Message 8 of 20

paullimapa
Mentor
Mentor

works perfectly for me...see attached dwg with rotated text & blocks

also here is a screen capture of the command sequence and the rotated texts & blocks afterwards

paulli_apa_0-1674472695800.png

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 9 of 20

dlbsurveysuk
Collaborator
Collaborator

OK. Thanks for the command sequence. Working now.

0 Likes
Message 10 of 20

paullimapa
Mentor
Mentor

glad to have helped....cheers!!!


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 11 of 20

dlbsurveysuk
Collaborator
Collaborator

Hi again,

 

Do you know where I would insert -

 

(trans ......... 0 1 )

 

in the code to make it work in any UCS?

 

Thanks.

0 Likes
Message 12 of 20

paullimapa
Mentor
Mentor
Accepted solution

I modified trot.lsp to allow you to rotate to 0 based on current UCS:

; trot function
; rotates selected Texts & Blocks matching selected Text rotation to zero
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/selection-set-by-rotation-angle/m-p/11697042#M442315
(princ"\nLoading Function...")(princ)
(defun c:trot (/ ed rot ss txt UCSang) 
 (princ"\nSelect Text Object To Get Rotation...")
 (while (not txt)
  (setq txt (ssget "_+.:E:S"'((0 . "TEXT"))))
  (if(not txt)
   (progn
    (princ"\nObject Selected is Not Text...")(princ)
   )
   (progn
    (setq ed(entget(ssname txt 0))) ; get entity data
    (setq rot(cdr(assoc 50 ed))) ; get rotation angle in degrees
    (princ(strcat"\nOnly Texts & Blocks With Matching [" (rtos (* 180.0 (/ rot pi)) 2 4) "] Degree Rotation Will Be Selected..."))(princ)
    (setq ss 
     (ssget
      (list
        '(-4 . "<OR")
            '(-4 . "<AND") '(0 . "TEXT")  (cons 50 rot) '(-4 . "AND>")
            '(-4 . "<AND") '(0 . "INSERT") (cons 50 rot) '(-4 . "AND>")
        '(-4 . "OR>")
      ) ; list
     ) ; ssget
    ) ; setq
    (if ss
      (progn
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/trans-function-to-find-rotation-of-ucs/td-p/1454208
      (setq UCSang (angle (trans '(0.0 0.0 0.0) 1 0)(trans '(1.0 0.0 0.0) 1 0))) ; get current UCS angle = 0
       (foreach ent (setq entlst(mapcar 'cadr (ssnamex ss))) ; loop through all entties from ss converted to list 
        (if (= 'ename (type ent)) ; confirm is entity
         (progn
          (setq ed (entget ent)) ; get entity data
          (entmod (subst (cons 50 UCSang)(assoc 50 ed) ed)) ; substitute 0 degree rotation
          (entupd ent) ; update entitity
         )
        ) ; if entity 
       ) ; foreach loop
       (alert"Operation Completed.")
      ) ; progn
      (alert"No Matching Texts & Blocks Selected.")     
    ) ; if
   ) ; progn
  ) ; if
 ) ; while
 (princ)
) ; defun
(princ"\n...Loaded Successfully...Enter Command [TRot] to Execute.")(princ)

Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 13 of 20

dlbsurveysuk
Collaborator
Collaborator

Perfect! That's just what I need. Thanks again for all your help.

0 Likes
Message 14 of 20

paullimapa
Mentor
Mentor

Once again glad to have helped... cheers!!!


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 15 of 20

john.uhden
Mentor
Mentor

@dlbsurveysuk:

Please note that @Sea-Haven and @Kent1Cooper are the only responders who recognized that you should probably include a fuzz factor for the angle in radians.  Isn't 2.786213457 close enough to 2.78621346 to being the same?  I am mentioning this for only labels, not for geometry.

Kent (et al):  I'm not sure if I have ever tried to include a fuzz factor in a selection set filter with a 'REAL variable.  Can you show us how (if it can be done)?

John F. Uhden

0 Likes
Message 16 of 20

Sea-Haven
Mentor
Mentor

I checked again on your dwg and could only find 1 thing take a bit of care picking 1st text angle. 

SeaHaven_0-1674527384950.png

 

SeaHaven_1-1674527407401.png

 

0 Likes
Message 17 of 20

Kent1Cooper
Consultant
Consultant

@john.uhden wrote:

....

Kent (et al):  I'm not sure if I have ever tried to include a fuzz factor in a selection set filter with a 'REAL variable.  Can you show us how (if it can be done)?


You can use >relational testing< in a selection set filter.  This will find/select/grip/highlight all objects that have a rotation in a DXF-50 entry that is within less than 1° of 180°:

 

(sssetfirst nil

  (ssget "_X"

    (list

      '(-4 . ">") (cons 50 (- pi (/ pi 180)))

      '(-4 . "<") (cons 50 (+ pi (/ pi 180)))

    )

  )

)

 

The (/ pi 180) is 1° in radians.  It's filtering for everything with a rotation that is more than 179° but less than 181°.

Replace pi with your targe rotation angle [in radians, but that's what you'll get if you pull it from a selected object], and (/ pi 180) with your fuzz factor.  Add other entries to the filter list for object type, Layer if you want, eliminate the "_X" if you want only from among a User selection, probably skip the (sssetfirst) for your purposes, etc.

Kent Cooper, AIA
0 Likes
Message 18 of 20

Kent1Cooper
Consultant
Consultant

 

     (ssget
      (list
        '(-4 . "<OR")
            '(-4 . "<AND") '(0 . "TEXT")  (cons 50 rot) '(-4 . "AND>")
            '(-4 . "<AND") '(0 . "INSERT") (cons 50 rot) '(-4 . "AND>")
        '(-4 . "OR>")
      ) ; list
     ) ; ssget

 

That much doesn't need to have two separate logical groupings of entity type with rotation, given that the rotation is the same for both.  You can get more than one entity type in (wcmatch)-style string format with comma-separated types.  It could be just:

 

     (ssget (list '(0 . "TEXT,INSERT") (cons 50 rot)))

 

If that misses some and you need a fuzz factor, here assuming 0.01 radians [about 0.57°] is an appropriate value:

 

(ssget
  (list
    '(0 . "TEXT,INSERT")
    '(-4 . ">") (cons 50 (- rot 0.01))
    '(-4 . "<") (cons 50 (+ rot 0.01))
  )
)

 

Tighten that 0.01 down to something smaller for a closer-to-exact rotational match.

Kent Cooper, AIA
0 Likes
Message 19 of 20

paullimapa
Mentor
Mentor

very nice..I like that fuzz factor addition.

Also perhaps replacing the entget & assoc functions with getproperties would be more efficient?

;    (setq ed(entget(ssname txt 0))) ; get entity data
;    (setq rot(cdr(assoc 50 ed))) ; get rotation angle in degrees
     (setq rot (getpropertyvalue (ssname txt 0) "Rotation"))

and the same with entmod & subst functions with setproperties:

;          (setq ed (entget ent)) ; get entity data
;          (entmod (subst (cons 50 UCSang)(assoc 50 ed) ed)) ; substitute 0 degree rotation
;          (entupd ent) ; update entitity
           (setpropertyvalue  ent "Rotation" UCSang)

Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 20 of 20

john.uhden
Mentor
Mentor

@Kent1Cooper & @Sea-Haven ,

Ya know, converting the two angles to strings at a desired precision (angtos ang 0 4) would work also for a fuzz factor, but that would require processing the entire selection set.

John F. Uhden

0 Likes