Draw 2 lines and get the angle through Autolisp COMMANDS

Draw 2 lines and get the angle through Autolisp COMMANDS

theresa_kewley
Explorer Explorer
2,216 Views
15 Replies
Message 1 of 16

Draw 2 lines and get the angle through Autolisp COMMANDS

theresa_kewley
Explorer
Explorer

Hello!  I am new to figuring out Autolisp programming.  I believe my biggest holdback is understanding what COMMANDS can return or how to access that information using the AUTOLISP.  I am attempting to fully automate majority of a program I’m working on.  I am stuck getting an angle of two lines drawn.

 

  1. Set the points
  2. Draw line 1
  3. Draw line 2
  4. Get the angle of line 1 and line2
;Get the angle of rotation
(setq point1Tension (list (car mountPoint1) (cadr mountPoint1) (+ (caddr mountPoint1) tension)))
(setq point1Compression (list (car mountPoint1) (cadr mountPoint1) (- (caddr mountPoint1) compression)))
(setq point2Compression (list (car mountPoint2) (cadr mountPoint2) (- (caddr mountPoint1) compression)))

(setq angle1Line1 (COMMAND "line" point1Tension point2Compression ""));Draw and get Line1 (CAN YOU SET LINE COLOR HERE?)
(setq angle1Line2 (COMMAND "line" point1Compression point2Compression ""));Draw and get Line2
(setq angle1 (COMMAND "MEASUREGEOM" "Angle" angle1Line1 angle1Line2 ""));get Angle 1
0 Likes
2,217 Views
15 Replies
Replies (15)
Message 2 of 16

pendean
Community Legend
Community Legend
CAL command an option? In HELP in AutoCAD, look up the topic
"Obtain an Angle (CAL Command)"
0 Likes
Message 3 of 16

ronjonp
Mentor
Mentor

Lisp has an ANGLE function which returns an angle in radians.

 

Then use the function below to return the angle in degrees:

(defun r2d (r) (* (/ r pi) 180.0))

 

0 Likes
Message 4 of 16

ВeekeeCZ
Consultant
Consultant

No no no, I would stop you here. Don't use commands. I do not say EVER but definitely not as your first choice. IF you are serious about programming.

 

(setq point1Tension (list (car mountPoint1) (cadr mountPoint1) (+ (caddr mountPoint1) tension)))
(setq point1Compression (list (car mountPoint1) (cadr mountPoint1) (- (caddr mountPoint1) compression)))
(setq point2Compression (list (car mountPoint2) (cadr mountPoint2) (- (caddr mountPoint1) compression)))


(setq Line1 (entmakex (list (cons 0 "LINE") (cons 10 point1Tension) (cons 11 point2Compression))))
(setq Line1ang (angle point1Tension point2Compression))
(setq Line2 (entmakex (list (cons 0 "LINE") (cons 10 point1Compression) (cons 11 point2Compression))))
(setq Line2ang (angle point1Compression point2Compression))

(setq ang (- Line1ang Line2ang)) ;; radians

 

0 Likes
Message 5 of 16

theresa_kewley
Explorer
Explorer

@ВeekeeCZ Ok.  Good to know!  I'll try to use commands less. Might make sense why I can't find much for them when searching, ha, ha.

I'm having troubles understanding how the angle is calculated for angle.  Below is in image describing the angle I am trying to get.  I currently am getting angles to be 90 degrees.  I am assuming that I will need to change the UCS in order to get the correct angles from the points?  I am trying to understand how the angle is calculated to the x-axis.

AutoCad Question.png

0 Likes
Message 6 of 16

Moshe-A
Mentor
Mentor

@theresa_kewley ,

 

check this CANG command.

 

moshe

 

; calculate an angle
(defun c:cang (/ p1 p2 p3 a1 a2 a3)
 (if (and
       (setq p1 (getpoint "\nPoint1 Tension: "))
       (setq p2 (getpoint "\nPoint2 Compression: "))
       (setq p3 (getpoint "\nPoint1 Compression: "))
     )
  (progn
   ; calc angles 
   (setq a1 (angle p2 p1))
   (setq a2 (angle p2 p3))

   (if (> a1 a2)
    (setq a3 (- a1 a2))
    (setq a3 (- a2 a1))
   )

   ; make sure sharp angle
   (if (> a3 pi)
    (setq a3 (- (* pi 2) a3))
   )

   
   (princ (strcat "\nAngle = " (angtos a3 1 4)))
  ); progn
 ); if  

 (princ) 
); c:cang

 

Message 7 of 16

devitg
Advisor
Advisor

@theresa_kewley Please upload your sample DWG . 

Sad to know ,  ACAD , can not handle .png  neither image. 

 

0 Likes
Message 8 of 16

theresa_kewley
Explorer
Explorer

@Moshe-A 
This is what happened when running the CANG lisp.  I believe it has to do with the UCS that it's getting 0.

theresa_kewley_0-1670955827803.png

@devitg Attached the file.

0 Likes
Message 9 of 16

Kent1Cooper
Consultant
Consultant

@theresa_kewley wrote:

....

....
(setq angle1Line1 (COMMAND "line" point1Tension point2Compression ""));Draw and get Line1 (CAN YOU SET LINE COLOR HERE?)
(setq angle1Line2 (COMMAND "line" point1Compression point2Compression ""));Draw and get Line2
....

Read about the (command) function in the AutoLisp Reference, and you will find that it always returns nil.  So you can't do the syntax above and get anything stored into your angle1Line1/2 variables.  You can do it this way [whether you use (command) or (entmake{x})]:

 

....
(COMMAND "line" point1Tension point2Compression ""); Draw ...
(setq angle1Line1 (entlast)); ... and get Line1
....

 

And no, you can't do the color of the Line within the command, but you could either set the CECOLOR System Variable before you draw it [but then you need to set it back afterwards], or change its color after it's drawn, by several methods including a CHPROP command, imposing a color override in entity data, applying it as a VLA property, or maybe the simplest:

(setpropertyvalue (entlast) "Color" YourDesiredColor)

Kent Cooper, AIA
0 Likes
Message 10 of 16

CADaSchtroumpf
Advisor
Advisor

This ? For obtain angle IN plane XY or WITH plane XY

(defun C:ID-Angle ( / pt_o pt_f dxf_11 ang ang_z)
  (initget 8)
  (setq pt_o (getpoint "\nSpecify the first point: "))
  (if (null pt_o) (setq pt_o (getvar "lastpoint")))
  (cond
    (pt_o
      (initget 41)
      (setq pt_f (getpoint pt_o "\nSpecify the second point: "))
      (cond
        (pt_f
          (setq dxf_11
            (trans
              (mapcar
                '(lambda (x / ) (/ x (distance (trans pt_o 1 0) (trans pt_f 1 0))))
                (mapcar '- (trans pt_f 1 0) (trans pt_o 1 0))
              )
              0 1 T
            )
          )
          (if (zerop (car dxf_11))
            (setq ang "infinite")
            (setq ang (angtos (atan (/ (cadr dxf_11) (car dxf_11)))))
          )
          (if (= (caddr dxf_11) 1.0)
            (setq ang_z "infinite")
            (if (zerop (caddr dxf_11))
              (setq ang_z (angtos 0.0))
              (setq ang_z (angtos (atan (sqrt (/ 1.0 (- (/ 1.0 (* (caddr dxf_11) (caddr dxf_11))) 1.0))))))
            )
          )
          (prompt (strcat "\nAngle in the plane XY = " ang " - Angle with the plane XY = " ang_z))
          (alert (strcat "Angle in the plane XY = " ang " - Angle with the plane XY = " ang_z))
        )
      )
    )
  )
  (prin1)
)
0 Likes
Message 11 of 16

Kent1Cooper
Consultant
Consultant

@theresa_kewley wrote:....

 

....
(setq angle1 (COMMAND "MEASUREGEOM" "Angle" angle1Line1 angle1Line2 ""));get Angle 1

The MEASUREGEOM Angle option won't accept entity names, but requires picking a point on something, maybe because the returned value could be different depending on where you pick on it.  But the angle can be measured this way [without even drawing the Lines]:

(command "MEASUREGEOM" "Angle" "" point2Compression point1Tension point2Compression "_exit")

And it shows you the result in degrees -- no need to convert radians.  However, I'm not sure how to put that into a variable, since (command) returns nil.  There's a LASTANGLE System Variable, but this result does not go into that.

 

A complication here is that you want an angle between Lines in the Z direction, whereas the (angle) function works only in the XY plane of the current UCS.  So a calculation is probably needed, and it does not require changing the UCS -- Pythagoras is your friend.

Kent Cooper, AIA
0 Likes
Message 12 of 16

Moshe-A
Mentor
Mentor

@theresa_kewley 

 

you only start learning autolisp and you are jumping to hardcore?  😀

of course we need ucs here, check this fix:

 

Moshe

 

 

 

; calculate an angle
(defun c:cang (/ p1 p2 p3 a1 a2 a3)
 (setvar "cmdecho" 0)
 (command "undo" "begin")

 (command "ucs" "w")
 (command "ucs" "z" -90)
 (command "ucs" "x"  90)
  
 (if (and
       (setq p1 (getpoint "\nPoint1 Tension: "))
       (setq p2 (getpoint "\nPoint2 Compression: "))
       (setq p3 (getpoint "\nPoint1 Compression: "))
     )
  (progn
   
   ; calc angles 
   (setq a1 (angle p2 p1))
   (setq a2 (angle p2 p3))

   (if (> a1 a2)
    (setq a3 (- a1 a2))
    (setq a3 (- a2 a1))
   )

   ; make sure sharp angle
   (if (> a3 pi)
    (setq a3 (- (* pi 2) a3))
   )

   
   (princ (strcat "\nAngle = " (angtos a3 1 4)))
  ); progn
 ); if  

 (command "ucs" "w")

 (command "undo" "end")
 (setvar "cmdecho" 1)
  
 (princ) 
); c:cang

 

  

0 Likes
Message 13 of 16

Moshe-A
Mentor
Mentor

@theresa_kewley ,

 

And this is a better version, let you measure angle from any 3 points in 3d.

of course there is an advanced way to do it by selecting lines (instead of specifying points) and reading objects database xyz but hey you are still a beginner so take it step by step.

 

Moshe

 

 

; Calculate an angle
(defun c:cang (/ savExp p1 p2 p3 a1 a2 a3 cucs)
 (setvar "cmdecho" 0)		; turn command echo off
 (command "undo" "begin")	; start undo

 (if (and
       (setq p1 (getpoint "\nPoint1 Tension: "))
       (setq p2 (getpoint "\nPoint2 Compression: "))
       (setq p3 (getpoint "\nPoint1 Compression: "))
     )
  (progn
   (setq savExp (getvar "expert")) ; save expert value
   (setvar "expert" 5) 		   ; allows ucs save work smoothly
   
   (command "ucs" "save" (setq cucs "$cang"))  ; save current ucs
   (command "ucs" "3p" p2 p3 p1)  	       ; create ucs on 3 points

   ; convert points from wcs to ucs
   (setq p1 (trans p1 0 1))
   (setq p2 (trans p2 0 1))
   (setq p3 (trans p3 0 1))
   
   ; calc angles 
   (setq a1 (angle p2 p1))
   (setq a2 (angle p2 p3))

   (if (> a1 a2)
    (setq a3 (- a1 a2))
    (setq a3 (- a2 a1))
   )

   ; make sure sharp angle
   (if (> a3 pi)
    (setq a3 (- (* pi 2) a3))
   )
   
   (princ (strcat "\nAngle = " (angtos a3 1 4)))
   
   (command "ucs" "restore" cucs)  ; restore ucs
   (command "ucs" "delete"  cucs)  ; delete  ucs
   
   (setvar "expert" savExp)	   ; restore normal expert behavior
  ); progn
 ); if  
  
 (command "undo" "end") ; close undo
 (setvar "cmdecho" 1)	; restore command echo
  
 (princ) 
); c:cang

 

 

0 Likes
Message 14 of 16

Sea-Haven
Mentor
Mentor

My $0.05

(setq p1 (getpoint "\nPoint1 Tension: "))
       (setq p2 (getpoint p1 "\nPoint2 Compression: "))
       (setq p3 (getpoint p2 "\nPoint1 Compression: "))

Just an illustration of showing where your picking from. 

 

Also I would look at setting osnaps as you go looks like end is correct.

 

(setq oldsnap (getvar 'osmode)) ; get the current osnaps settings

(setvar 'osmode 1)
(setq p1 (getpoint "\nPoint1 Tension: ")
       p2 (getpoint p1 "\nPoint2 Compression: ")
       p3 (getpoint p2 "\nPoint1 Compression: "))
(setvar 'osmode oldsnap) ; if last getpoint or set to another snap for next get
0 Likes
Message 15 of 16

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

A complication here is that you want an angle between Lines in the Z direction, whereas the (angle) function works only in the XY plane of the current UCS.  So a calculation is probably needed, and it does not require changing the UCS -- Pythagoras is your friend.


Actually, a little trigonometry can do it, without bothering Pythagoras.  After the establishment of the point1Tension / point1Compression / point2Compression variables in Message 1, and assuming the point2compression point is above [as in your image, but could also be below] both the point1 locations, then:

 

(setq p1T point1Tension p1C point1Compression p2C point2Compression); [simplify variable names for use below]
(setq
  verC (- (caddr p2C) (caddr p1C))
  verT (- (caddr p2C) (caddr p1T))
  horC (distance p1C (list (car p2C) (cadr p2C) (caddr p1C)))
  horT (distance p1T (list (car p2C) (cadr p2C) (caddr p1T)))
  angC (atan (/ verC horC))
  angT (atan (/ verT horT))
  angbetween (abs (- angT angC))
)
(prompt (strcat "\nAngle between lines is " (angtos angbetween) "."))

 

That reports the angle in whatever your current angular Units mode and precision settings are.  The Lines are not needed to find the angle, though you can have them drawn if you want.

 

If the point2 apex location might sometimes fall vertically between the Z coordinates of the two point1 locations, it could be made to check for that, and if that's the case, the angle between would be the sum of the two calculated angles:

....

  angbetween (+ angT angC)

....

Kent Cooper, AIA
0 Likes
Message 16 of 16

devitg
Advisor
Advisor

@theresa_kewley My way to do it , the old scalene triangle resolution .

 

Pt 2 shall be pick at the need angle vertex , do not matter the Coordinate system  , as I test it work for any triangle .

 

;;;;;;;;*//*/*/*/*/*/*/*/*/*/*/*/*/**/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/
;; Design by Gabo CALOS DE VIT from CORDOBA ARGENTINA
;;;    Copyleft 1995-2022 by Gabriel Calos De Vit ; DEVITG@GMAIL.COM    
;;

 ; Hecho por  Gabo CALOS DE VIT de CORDOBA ARGENTINA
;;;    Copyleft 1995-2022 por Gabriel Calos De Vit 
;; DEVITG@GMAIL.COM 
;;******************************************************  

(DEFUN ASIN  (NUM)
  (COND
    ((EQUAL NUM 1 1e-12) (/ PI 2))
    ((EQUAL NUM -1 1e-12) (/ PI -2))
    ((< -1 NUM 1)
     (ATAN NUM (SQRT (- 1 (EXPT NUM 2))))
     )
    )
  )






  (SETQ ACAD-OBJ (VLAX-GET-ACAD-OBJECT)) ;_ el programa ACAD 
  (SETQ ADOC (VLA-GET-ACTIVEDOCUMENT ACAD-OBJ)) ;_ el DWG que esta abierto-
  (SETQ MODEL (VLA-GET-MODELSPACE ADOC))



(VL-LOAD-COM)
(DEFUN C:ANG,  (/
;;;1/2AA
;;;A
;;;A+B+C/2
;;;AA
;;;AA-DEG
;;;B
;;;C
;;;P1
;;;P2
;;;P3
;;;PLIST
;;;ROOT
;;;SEMI-B
;;;SEMI-C
;;;SIN1/2AA
                )
  (SETVAR 'OSMODE 8)
  (IF (AND
        (SETQ P1 (GETPOINT "\nPoint1 Tension, : "))
        (SETQ P2 (GETPOINT "\nPoint2 Compression, @ angle vertex: "))
        (SETQ P3 (GETPOINT "\nPoint1 Compression: "))
        )
    (PROGN
      (SETQ PLIST (LIST P1 P2 P3));just to see the points

      (SETQ A (DISTANCE P1 P3))
      (SETQ B (DISTANCE P1 P2))
      (SETQ C (DISTANCE P2 P3))

      (SETQ A+B+C/2 (/ (+ A B C) 2.0))

      (SETQ SEMI-B (- A+B+C/2 B))

      (SETQ SEMI-C (- A+B+C/2 C))

      (SETQ ROOT (/ (* SEMI-C SEMI-B) (* B C)))

      (SETQ SIN1/2AA (SQRT ROOT))



      (SETQ 1/2AA (ASIN SIN1/2AA))

      (SETQ AA-DEG (angtos(SETQ AA (* 2 1/2AA))1 4))

      
     
      ) ; progn
    ) ;end if
  (alert (strcat "AA = "AA-DEG )) 
  ) ;end defun ang,













 Need to localize variables 

 

 

0 Likes