LISP for measuring angles between xlines

LISP for measuring angles between xlines

Shanky1999
Enthusiast Enthusiast
1,393 Views
20 Replies
Message 1 of 21

LISP for measuring angles between xlines

Shanky1999
Enthusiast
Enthusiast

Hi, I wanted to know if we can create an autocad lisp which can measure angle between two xlines.

I know xlines and rays dont have any vertex, but can we create a lisp which can create a line from the intersection of these two xlines and measure them ?

0 Likes
Accepted solutions (1)
1,394 Views
20 Replies
Replies (20)
Message 2 of 21

_gile
Consultant
Consultant

Hi,

Here's a way which works whatever the plane the xlines lies on. It checks if the two xline intersects (i.e., they lies on the same plane and aren't parallel).

 

;; angleXline
;; Returns the angle in radians between two Xlines
;; or nil if Xlines are parallel or not coplanar.
;;
;; Arguments
;; xline1: first xline (ENAME)
;; xline2: second xline (ENAME)
(defun angleXlines (xline1 xline2 / v1 v2 norm)
  (if
    (inters
	(getpropertyvalue xline1 "BasePoint")
	(getpropertyvalue xline1 "SecondPoint")
	(getpropertyvalue xline2 "BasePoint")
	(getpropertyvalue xline2 "SecondPoint")
	nil
      )
     (progn
       (setq v1	  (getpropertyvalue xline1 "UnitDir")
	     v2	  (getpropertyvalue xline2 "UnitDir")
	     norm (list
		    (- (* (cadr v1) (caddr v2)) (* (caddr v1) (cadr v2)))
		    (- (* (caddr v1) (car v2)) (* (car v1) (caddr v2)))
		    (- (* (car v1) (cadr v2)) (* (cadr v1) (car v2)))
		  )
       )
       (- (angle '(0. 0. 0.) (trans v2 0 norm))
	  (angle '(0. 0. 0.) (trans v1 0 norm))
       )
     )
  )
)

 

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 21

-didier-
Advisor
Advisor

Bonjour @Shanky1999 

 

What do you need ?

  1. The value of the angle on the command line as an information ?
  2. The value of the angle on the drawing as an entity "angular dimension”?

 

Amicalement

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

DA

EESignature

0 Likes
Message 4 of 21

Kent1Cooper
Consultant
Consultant

@Shanky1999 wrote:

....

I know xlines and rays dont have any vertex, but can we create a lisp which can create a line from the intersection of these two xlines and measure them ?


They do have defined points, like Lines (DXF codes 10 & 11).  The 11 value is a unit vector relative to the origin 10 value [Osnappable as the ENDpoint of a Ray, or the MIDpoint of an Xline].

There's no need to create a Line.  This will report, in your current settings for angular mode and precision, the two angles [projected onto the current drawing plane if they are in different Coordinate Systems] between two selected objects of either or both kinds:

 

(defun C:XLRA ; = XLine/Ray Angle
  (/ e1 e2 e1data e2data e1ang e2ang)
  (setq
    e1 (car (entsel "\nOne XLINE or RAY: "))
    e2 (car (entsel "\nOther XLINE or RAY: "))
    e1data (entget e1)
    e2data (entget e2)
    e1ang (rem (angle '(0 0 0) (cdr (assoc 11 e1data))) pi)
    e2ang (rem (angle '(0 0 0) (cdr (assoc 11 e2data))) pi)
    angbetween (abs (- e1ang e2ang))
  ); setq
  (prompt
    (strcat
      "\nAngles between those two XLINES/RAYS are "
      (angtos angbetween) " and " (angtos (- pi angbetween)) "."
    ); strcat
  ); alert
  (prin1)
)

 

It will say the angles are 0° and 180° if they're parallel.

It leaves the 'angbetween' variable [in radians] available for you to use in any way you need.

It could be made to do things like verify you selected the right kind(s) of thing(s), that you didn't select the same thing twice, etc.....

Kent Cooper, AIA
0 Likes
Message 5 of 21

MunteanStefan
Contributor
Contributor

The dot product of the Xlines' directions gives you the cosine of the angle, assuming that the directions are always unit vectors.

Then you can  extract the angle.

 

(defun Xangle (e1 e2 / v1 v2 v)
  (setq v1 (cdr (assoc 11 (entget e1)))
        v2 (cdr (assoc 11 (entget e2)))
        v  (apply '+ (mapcar '* v1 v2))
  )
  (if
    (equal v 0.0 1e-8)
    (/ pi 2.0)
    (atan (/ (sqrt (- 1 (* v v))) v))
  )
)

 

 

Edit: alternative, to return the acute angle.

(defun Xangle (e1 e2 / v1 v2 v a)
  (setq v1 (cdr (assoc 11 (entget e1)))
        v2 (cdr (assoc 11 (entget e2)))
        v  (apply '+ (mapcar '* v1 v2))
        a  (atan (sqrt (- 1 (* v v))) v)
  )
  (if (> a (/ pi 2)) (- pi a) a)
)
Message 6 of 21

komondormrex
Mentor
Mentor

hey,

yet another one

(defun c:x_ray_angle (/ dir_1 dir_2 xy_diff)
  (setq dir_1 (vlax-get (vlax-ename->vla-object (car (entsel "\nPick 1st ray or xline: "))) 'directionvector)
	dir_2 (vlax-get (vlax-ename->vla-object (car (entsel "\nPick 2nd ray or xline: "))) 'directionvector)
	xy_diff (mapcar '- dir_1 dir_2)
  )
  (princ "\nBetween angle: ")
  (cond
    ((or (< (abs (car xy_diff)) 1e-12) (< (abs (cadr xy_diff)) 1e-12)) pi)
    (t (* 2 (atan (/ (setq a (sqrt (apply '+ (mapcar '* xy_diff xy_diff)))) (sqrt (- 4 (* a a)))))))
  )
)
0 Likes
Message 7 of 21

-didier-
Advisor
Advisor

Bonjour

 

All these programs are fine, but I would like to present my version because they do not return the angles of the selected entities. I wanted to do a different treatment.

I explain, whatever the entities selected, the programs return a single angle value, and it is not always the one that corresponds to the selection.

Mine is more "simple", I do not use the vectors, but the selection points to calculate the angle that really corresponds to the selection.

I have somewhat arranged the presentation by testing the angular units of the system as well as the local language.

Here is my code :

 

(defun language ()
    (vl-registry-read
        (strcat "HKEY_LOCAL_MACHINE\\" (vlax-product-key))
        "Language")
    )
(defun rad2dms (a)
    (setq deg (/ (* a 180) pi))
    (setq minu (* (- deg (fix deg))60))
    (setq sec ( * (- minu (fix minu)) 60))
    (strcat (itoa (fix deg)) "° , " (itoa (fix minu)) "' , " (rtos sec 2 2) "''")    
    )

(defun c:da:anglexlines ( / ang int p1 p2 xl1 xl2)
    (setq lang (language))
    (if ( = lang "Français")
        (progn
            (setq xl1 (entsel "\nChoix de la première XLINE...\n"))
            (setq xl2 (entsel "\nChoix de la deuxième XLINE...\n"))
            )
        (progn
            (setq xl1 (entsel "\nPick 1st ray or xline: "))
            (setq xl2 (entsel "\nPick 2nd ray or xline: "))
            )
        )
    (if (and (or (= "RAY" (cdr (assoc 0 (entget (car xl1)))))
                 (= "XLINE" (cdr (assoc 0 (entget (car xl1))))))
             (or (= "RAY" (cdr (assoc 0 (entget (car xl2)))))
                 (= "XLINE" (cdr (assoc 0 (entget (car xl2))))))
             )
        (progn
            (setq p1 (osnap (cadr xl1)"_nea"))
            (setq xl1 (vlax-ename->vla-object (car xl1)))
            (setq p2 (osnap (cadr xl2)"_nea"))
            (setq xl2 (vlax-ename->vla-object (car xl2)))
            (setq int (vla-intersectwith xl1 xl2 0))
            (setq int (vlax-safearray->list (vlax-variant-value int)))
            (setq ang (abs (- (angle int p1) (angle int p2))))
            (if (> ang pi)
                (setq ang (abs (- (* pi 2) ang)))
                )
            (cond
                ((= 0 (getvar "aunits")) (setq ang (rtos (* (/ ang pi) 180)2 )))
                ((= 1 (getvar "aunits")) (setq ang (rad2dms ang)))
                ((= 2 (getvar "aunits")) (setq ang (rtos (* (/ ang pi) 200)2 )))
                ((= 3 (getvar "aunits")) (setq ang (rtos ang 2 )))
                ((= 4 (getvar "aunits"))
                 (if ( = lang "Français")
                     (setq ang "ce système d'unités n'est pas prévu")
                     (setq ang "this unit system is not intended")
                     ))
                )
            
            (if ( = lang "Français")
                (alert (strcat "L'angle en unités utilisateur est de  : " ang))
                (alert (strcat "The angle in user units is  : " ang))
                )
            )
        (if ( = lang "Français")
            (alert "les entités sélectionnées ne sont pas xline ou ray.")
            (alert "the selected entities are not xline or ray.")
            )
        )
    )

 

 

Amicalement

 

 

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

DA

EESignature

0 Likes
Message 8 of 21

CADaSchtroumpf
Advisor
Advisor

An another method

(defun c:xline2alpha ( / x ss1 obj_straight dir_vec deriv alpha)
  (repeat 2
    (princ (strcat "\nSelect " (if x "Second " (setq x "First ")) "ray or xline: "))
    (while (not (setq ss1 (ssget "_+.:E:S" '((0 . "XLINE,RAY"))))))
    (setq
      obj_straight (vlax-ename->vla-object (ssname ss1 0))
      dir_vec (vlax-get-property obj_straight 'DirectionVector)
      deriv (vlax-safearray->list (vlax-variant-value dir_vec))
      alpha (if alpha (- alpha (atan (cadr deriv) (car deriv))) (atan (cadr deriv) (car deriv)))
    )
  )
  (print alpha)
  (angtos alpha (getvar "AUNITS") 4)
)
0 Likes
Message 9 of 21

-didier-
Advisor
Advisor

Bonjour @CADaSchtroumpf 

 

I’m sorry to insist but, your program is concerned, as others are.

 

Snag_2ac68291.png

That is why I have proposed a different approach.

Amicalement

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

DA

EESignature

0 Likes
Message 10 of 21

calderg1000
Mentor
Mentor
Accepted solution

Regards @Shanky1999 

Previously configure "DIMSTYLE" according to the characteristics of your work and the reference to objects, then apply the routine, It also allows you to obtain the external angle...

 

;;;___
(defun c:angXl (/ sn i j p lp ps)
 (princ "\nSelect Two Xline")
  (setq
    sn (vl-remove-if 'listp (mapcar 'cadr (ssnamex (ssget '((0 . "*line"))))))
  )
  (foreach i sn
    (setq
      p (list (cdr (assoc 10 (entget i))) (cdr (assoc 11 (entget i))))
    )
    (setq lp (cons p lp))
  )
  (setq ps (inters (caar lp)(mapcar '+ (caar lp) (cadar lp))(caadr lp)(mapcar '+ (caadr lp) (cadadr lp))nil)
  )
  (command "_dimangular" "" "_non" ps "pause" "pause" "pause")
)

 

 


Carlos Calderon G
EESignature
>Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

Message 11 of 21

CADaSchtroumpf
Advisor
Advisor

@-didier- 

Let's say that my return (in radians) is good; for calculation, for example for a submission to (entmake)
Afterwards, for a correct display in the angular unit used, it is enough to take into account the variables and the management of negative angles.
This version displays the two angles (because there are two after all; the complementary...)

(defun c:xline2alpha ( / x ss1 obj_straight dir_vec deriv alpha)
  (repeat 2
    (princ (strcat "\nSelect " (if x "Second " (setq x "First ")) "ray or xline: "))
    (while (not (setq ss1 (ssget "_+.:E:S" '((0 . "XLINE,RAY"))))))
    (setq
      obj_straight (vlax-ename->vla-object (ssname ss1 0))
      dir_vec (vlax-get-property obj_straight 'DirectionVector)
      deriv (vlax-safearray->list (vlax-variant-value dir_vec))
      alpha (if alpha (- alpha (atan (cadr deriv) (car deriv))) (atan (cadr deriv) (car deriv)))
      alpha (if (< alpha 0) (rem (- (* 2 pi) alpha) pi) (rem alpha pi))
    )
  )
  (alert
    (strcat
      (rtos alpha 2 4)
      "\n"
      (angtos (- pi alpha (getvar "ANGBASE")) (getvar "AUNITS") 4)
      "\n"
      (angtos (- alpha (getvar "ANGBASE")) (getvar "AUNITS") 4)
    )
  )
  (prin1)
)
0 Likes
Message 12 of 21

Shanky1999
Enthusiast
Enthusiast

I would prefer option 2 if possible.

Thank you

0 Likes
Message 13 of 21

Shanky1999
Enthusiast
Enthusiast

Hi,

 

If I would have to increase the angle precision, I would have to do it in dimstyle right?

 

Thank you.

0 Likes
Message 14 of 21

-didier-
Advisor
Advisor

Bonjour @Shanky1999 

 

I would prefer option 2 if possible. I don't understand what is option 2, sorry.

To change the angle precision, I have updated my code in message 7, and now the precision i the value of the environment variable LUPREC.

 

Amicalement

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

DA

EESignature

0 Likes
Message 15 of 21

Kent1Cooper
Consultant
Consultant

@-didier- wrote:

... the precision i the value of the environment variable LUPREC.


[Do you perhaps mean the System Variable AUPREC?   And I suggest the use of (angtos) rather than (rtos) functions in relation to the string conversion of the 'ang' variable.  That will go to text directly in the current angular units, so some of your calculations should not be needed, nor probably the (cond) function that considers the AUNITS System Variable setting.]

Kent Cooper, AIA
0 Likes
Message 16 of 21

calderg1000
Mentor
Mentor

Regards @Shanky1999 

Yes, by editing the dimensioning style, you can configure the output, both the format of the units and the precision.

calderg1000_0-1731512493496.png

 


Carlos Calderon G
EESignature
>Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

0 Likes
Message 17 of 21

-didier-
Advisor
Advisor

Bonjour @Kent1Cooper 

 

  • OK for the variable Sytem is better than environment.
  • I hesitated for angtos, but this function taking into account the settings of the direction of the angles poses problems because I do not know how the machine is set by the person who asks the question.
  • And finally rtos takes LUPREC but ignores AUPREC, the help says this :
    The rtos function returns a string that is the representation of number according to the settings
    of mode, precision, and the AutoCAD UNITMODE, DIMZIN, LUNITS, and LUPREC system variables.



    Amicalement

 

 

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

DA

EESignature

0 Likes
Message 18 of 21

Shanky1999
Enthusiast
Enthusiast

ok thanks,

I just needed the measurement to be shown in the dwg

0 Likes
Message 19 of 21

Shanky1999
Enthusiast
Enthusiast

i wanted option 2 in this case, but thanks I got what I needed

0 Likes
Message 20 of 21

Shanky1999
Enthusiast
Enthusiast

this lisp worked as I intended, although all of your code worked, it would display the angle as an alert, I wanted it to be shown as a dimension on drawing. 

0 Likes