Pick two Points to get Downslope in percents, prompted in CommandLine

Pick two Points to get Downslope in percents, prompted in CommandLine

Anonymous
Not applicable
1,027 Views
25 Replies
Message 1 of 26

Pick two Points to get Downslope in percents, prompted in CommandLine

Anonymous
Not applicable

Hello,

I wrote a lisp which calculates the downslope in percents and returns this downslope's value to CommandLine.

Here it is:

 

; DSE = DownSlopE
; DOWNSLOPE
(defun c:DOWNSLOPE
 (/ ptL1 ptL2 Len_X Len_Y Len Ang DownslopePercents)
 (setvar "cmdecho" 0)
 (setq ptL1 (getpoint "\nSpecify First Point to calculate Downslope: "))
 (setq ptL2 (getpoint "\nSpecify Second Point to calculate Downslope: "))
 (setq XptL1 (car ptL1))
 (setq YptL1 (cadr ptL1))
 (setq XptL2 (car ptL2))
 (setq YptL2 (cadr ptL2))
 (setq Len_X (- XptL2 XptL1))
 (setq Len_Y (- YptL2 YptL1))
; What if XptL1 = XptL2 --> Len_X=0?
; (setq Len
;  (sqrt
;   (+ (* Len_X Len_X) (* Len_Y Len_Y))
;  ); sqrt
; ); Len
; (setq Ang (atan Len_Y Len_X))
;Len_Y/Len_X = DownslopePercents/100
 (setq DownslopePercents (* (/ Len_Y Len_X) 100))
 (setq DownslopePercents2string (rtos DownslopePercents 2 3)); Mode=2=Engineering, Precision=3
 (princ "\nDownslope = ")
 DownslopePercents2string
 (princ "%.")
; (princ "\nAngle = ")
; Length
; (princ " <Here should be current angle units. Should I type 'getvar AUNITS?'>.")
; (princ "\nLength = ")
; Length
; (princ ".")
);defun

 

Some parts of this lisp I ignore with ';', because they will be investigated in other cases - on ground of this lisp I want to write lisps which return to CommandLine Distance and Angle between two picked Points. And I can't do them using 'getdist' and 'getangle', because the user would type his own value for Distance and Angle.

 

So returning to the main topic: This lisp doesn't work properly.

In the CommandLine it returns:

 

Command: DOWNSLOPE
Specify First Point to calculate Downslope:
Specify Second Point to calculate Downslope:
Downslope = %."%."

 

Could you please tell me why it doesn't work in way which I suspected?

0 Likes
1,028 Views
25 Replies
Replies (25)
Message 2 of 26

Anonymous
Not applicable

Hi,

 

Use ' strcat ' to concatenate strings.

 

(setq DownslopePercents2string (rtos DownslopePercents 2 3)); Mode=2=Engineering, Precision=3
 (princ (strcat "\nDownslope = " DownslopePercents2string "%.")) (princ)

 

Regards,

gsktry

 

 

0 Likes
Message 3 of 26

hmsilva
Mentor
Mentor

Hi Damian,

 

your code, revised

 

; DSE = DownSlopE
; DOWNSLOPE
(defun c:DOWNSLOPE (/ angstring angun auni Ang DownslopePercents DownslopePercents2string Len Len_X Len_Y ptL1 ptL2 XptL1 XptL2 YptL1 YptL2)
  (if (and (setq ptL1 (getpoint "\nSpecify First Point to calculate Downslope: "))
	   (setq ptL2 (getpoint "\nSpecify Second Point to calculate Downslope: "))
	   (not (equal ptL1 ptL2 1e-8))
      )
    (progn
      (setq XptL1 (car ptL1))
      (setq YptL1 (cadr ptL1))
      (setq XptL2 (car ptL2))
      (setq YptL2 (cadr ptL2))
      (setq Len_X (- XptL2 XptL1))
      (setq Len_Y (- YptL2 YptL1))
      ; What if XptL1 = XptL2 --> Len_X=0?
      ;; (setq len (distance ptL1 ptL2))
      (setq Len
	     (sqrt
	       (+ (* Len_X Len_X) (* Len_Y Len_Y))
	     ); sqrt
      ); Len
      (setq angun (getvar 'aunits))
      (cond ((or (= angun 0)
		 (= angun 1)
	     )
	     (setq auni "Degrees")
	    )
	    ((= angun 2)
	     (setq auni "Gradians")
	    )
	    ((= angun 3)
	     (setq auni "Radians")
	    )
	    ((= angun 4)
	     (setq auni "Surveyor")
	    )
      )
      (setq Ang (atan Len_Y Len_X))
      (setq angstring (strcat
	     (if (minusp ang) "-" "")
	     (angtos (abs ang) angun 3)))
      ;Len_Y/Len_X = DownslopePercents/100
      (setq DownslopePercents (* (/ Len_Y Len_X) 100))
      (setq DownslopePercents2string (rtos DownslopePercents 2 3))
      ; Mode=2= Decimal, Precision=3
      (princ (strcat "\nDownslope = " DownslopePercents2string  "%."))
      (princ (strcat "\nAngle = " angstring " " auni "."))
      (princ (strcat "\nLength = " (rtos Len 2 3) "."))
    )
    (prompt "\nYou did select the same point!!!")
  )
  (princ)
);defun

 

Henrique

EESignature

0 Likes
Message 4 of 26

Anonymous
Not applicable

Thank you, Henrique!

 

I added lines to get informations about Length_X, Length_Y, which are - apart from Length, Angle and Downslope in Percents, which we soon had in DOWNSLOPE lisp - the basic things we would specify in MEGALINE lsp:

http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/to-write-megaline-lsp/td-p/5481385

http://forums.autodesk.com/autodesk/attachments/autodesk/130/329309/1/lisp%20MEGALINE%20(3).pdf

 

And because not all of thesr results are visible in CommandLine (in which basically shows only two last prompts are visible), on the end. I added a prompt  to  read in CommandLine "Press [F2] button...".

 

Here it is:

 

 

;DRNGLXYA2POIINFHMS=
;Downslope in peRcents
;aNGle
;Length in X, Y, Aligned
;by TWO POInts
;INFo by HMSilva

(defun c:DRNGLXYA2POIINFHMS
 (/ angstring angun auni Ang
  DownslopePercents DownslopePercents2string
  Len Len_X Len_Y
  ptL1 ptL2
  XptL1 XptL2 YptL1 YptL2
 )
  (if (and (setq ptL1 (getpoint "\nSpecify First Point to calculate Downslope: "))
	   (setq ptL2 (getpoint "\nSpecify Second Point to calculate Downslope: "))
	   (not (equal ptL1 ptL2 1e-8))
      )
    (progn
      (setq XptL1 (car ptL1))
      (setq YptL1 (cadr ptL1))
      (setq XptL2 (car ptL2))
      (setq YptL2 (cadr ptL2))
      (setq Len_X (- XptL2 XptL1))
      (setq Len_Y (- YptL2 YptL1))
      ; What if XptL1 = XptL2 --> Len_X=0?
      ;; (setq len (distance ptL1 ptL2))
      (setq Len
	     (sqrt
	       (+ (* Len_X Len_X) (* Len_Y Len_Y))
	     ); sqrt
      ); Len
      (setq angun (getvar 'aunits))
      (cond ((or (= angun 0)
		 (= angun 1)
	     )
	     (setq auni "Degrees")
	    )
	    ((= angun 2)
	     (setq auni "Gradians")
	    )
	    ((= angun 3)
	     (setq auni "Radians")
	    )
	    ((= angun 4)
	     (setq auni "Surveyor")
	    )
      )
      (setq Ang (atan Len_Y Len_X))
      (setq angstring (strcat
	     (if (minusp ang) "-" "")
	     (angtos (abs ang) angun 3)))
      ;Len_Y/Len_X = DownslopePercents/100
      (setq DownslopePercents (* (/ Len_Y Len_X) 100))
      (setq DownslopePercents2string (rtos DownslopePercents 2 3))
      ; Mode=2= Decimal, Precision=3
      (princ (strcat "\nDownslope = " DownslopePercents2string  "%."))
	  (princ (strcat "\nLength_X = " (rtos Len_X 2 3) "."))
	  (princ (strcat "\nLength_Y = " (rtos Len_Y 2 3) "."))
      (princ (strcat "\nAngle = " angstring " " auni "."))
      (princ (strcat "\nLength = " (rtos Len 2 3) "."))
	  (princ "\nPress [F2] to open and close results in CommandLine.")
    )
    (prompt "\nYou did select the same point!!!")
  )
;  (princ "\nPress [F2] button to open and close results in CommandLine.")
);defun

 

But what we will get in CommandLine is:

 

;;;;;;;;;;;;;;;;;;;;;;;;;;;

Command: DRNGLXYA2POIINFHMS
Specify First Point to calculate Downslope:
Specify Second Point to calculate Downslope:
Downslope = 2.000%.
Length_X = 1500.000.
Length_Y = 30.000.
Angle = 1.146 Degrees.
Length = 1500.300.
Press [F2] to open and close results in CommandLine."\nPress [F2] to open and
close results in CommandLine."

 

Command:

;;;;;;;;;;;;;;;;;;;;;;;;;;;

 

 

 

So the error is that this program runs the final prompt twice instead of just once.

If it would run it once, the user would watch all the final prompt. But programm runs it twice and the user watches only end part of final prompt.

 

So I have request: COuld you tell me please, why is error here and how to write this lisp in right way?

 

P.S.

And I don't know why on the very end in COmmandLine the prompt "Command: " appeared.

Could you also tell me why it prompts and how to get only  "Press [F2] to open and close results in CommandLine." prompt at the end of the CommandLine?

0 Likes
Message 5 of 26

hmsilva
Mentor
Mentor

You're welcome, Damian.

 

The AutoCAD Command prompt, display the return from the last evaluated function, to suppress the echo, we add a princ function, without an expression, to exiting quietly.

 

Your code, revised

 

;DRNGLXYA2POIINFHMS=
;Downslope in peRcents
;aNGle
;Length in X, Y, Aligned
;by TWO POInts
;INFo by HMSilva

(defun c:DRNGLXYA2POIINFHMS
 (/ angstring angun auni Ang
  DownslopePercents DownslopePercents2string
  Len Len_X Len_Y
  ptL1 ptL2
  XptL1 XptL2 YptL1 YptL2
 )
  (if (and (setq ptL1 (getpoint "\nSpecify First Point to calculate Downslope: "))
	   (setq ptL2 (getpoint "\nSpecify Second Point to calculate Downslope: "))
	   (not (equal ptL1 ptL2 1e-8))
      )
    (progn
      (setq XptL1 (car ptL1))
      (setq YptL1 (cadr ptL1))
      (setq XptL2 (car ptL2))
      (setq YptL2 (cadr ptL2))
      (setq Len_X (- XptL2 XptL1))
      (setq Len_Y (- YptL2 YptL1))
      ; What if XptL1 = XptL2 --> Len_X=0?
      ;; (setq len (distance ptL1 ptL2))
      (setq Len
	     (sqrt
	       (+ (* Len_X Len_X) (* Len_Y Len_Y))
	     ); sqrt
      ); Len
      (setq angun (getvar 'aunits))
      (cond ((or (= angun 0)
		 (= angun 1)
	     )
	     (setq auni "Degrees")
	    )
	    ((= angun 2)
	     (setq auni "Gradians")
	    )
	    ((= angun 3)
	     (setq auni "Radians")
	    )
	    ((= angun 4)
	     (setq auni "Surveyor")
	    )
      )
      (setq Ang (atan Len_Y Len_X))
      (setq angstring (strcat
	     (if (minusp ang) "-" "")
	     (angtos (abs ang) angun 3)))
      ;Len_Y/Len_X = DownslopePercents/100
      (setq DownslopePercents (* (/ Len_Y Len_X) 100))
      (setq DownslopePercents2string (rtos DownslopePercents 2 3))
      ; Mode=2= Decimal, Precision=3
      (princ (strcat "\nDownslope = " DownslopePercents2string  "%."))
	  (princ (strcat "\nLength_X = " (rtos Len_X 2 3) "."))
	  (princ (strcat "\nLength_Y = " (rtos Len_Y 2 3) "."))
      (princ (strcat "\nAngle = " angstring " " auni "."))
      (princ (strcat "\nLength = " (rtos Len 2 3) "."))
	  (princ "\nPress [F2] to open and close results in CommandLine.")
    )
    (prompt "\nYou did select the same point!!!")
  )
(princ);; exits quietly
);defun

 

And you may try to use the alert function instead of presenting the result at the command line

 

;DRNGLXYA2POIINFHMS=
;Downslope in peRcents
;aNGle
;Length in X, Y, Aligned
;by TWO POInts
;INFo by HMSilva

(defun c:DRNGLXYA2POIINFHMS
 (/ angstring angun auni Ang
  DownslopePercents DownslopePercents2string
  Len Len_X Len_Y
  ptL1 ptL2
  XptL1 XptL2 YptL1 YptL2
 )
  (if (and (setq ptL1 (getpoint "\nSpecify First Point to calculate Downslope: "))
	   (setq ptL2 (getpoint "\nSpecify Second Point to calculate Downslope: "))
	   (not (equal ptL1 ptL2 1e-8))
      )
    (progn
      (setq XptL1 (car ptL1))
      (setq YptL1 (cadr ptL1))
      (setq XptL2 (car ptL2))
      (setq YptL2 (cadr ptL2))
      (setq Len_X (- XptL2 XptL1))
      (setq Len_Y (- YptL2 YptL1))
      ; What if XptL1 = XptL2 --> Len_X=0?
      ;; (setq len (distance ptL1 ptL2))
      (setq Len
	     (sqrt
	       (+ (* Len_X Len_X) (* Len_Y Len_Y))
	     ); sqrt
      ); Len
      (setq angun (getvar 'aunits))
      (cond ((or (= angun 0)
		 (= angun 1)
	     )
	     (setq auni "Degrees")
	    )
	    ((= angun 2)
	     (setq auni "Gradians")
	    )
	    ((= angun 3)
	     (setq auni "Radians")
	    )
	    ((= angun 4)
	     (setq auni "Surveyor")
	    )
      )
      (setq Ang (atan Len_Y Len_X))
      (setq angstring (strcat
	     (if (minusp ang) "-" "")
	     (angtos (abs ang) angun 3)))
      ;Len_Y/Len_X = DownslopePercents/100
      (setq DownslopePercents (* (/ Len_Y Len_X) 100))
      (setq DownslopePercents2string (rtos DownslopePercents 2 3))
      ; Mode=2= Decimal, Precision=3
      (alert (strcat "\nDownslope = " DownslopePercents2string  "%."
                     "\nLength_X = " (rtos Len_X 2 3) "."
                     "\nLength_Y = " (rtos Len_Y 2 3) "."
                     "\nAngle = " angstring " " auni "."
                     "\nLength = " (rtos Len 2 3) "."))
    )
    (prompt "\nYou did select the same point!!!")
  )
(princ);; exits quietly
);defun

 

Henrique

EESignature

0 Likes
Message 6 of 26

Anonymous
Not applicable

Thank you, Henrique.

I hear for the first time in my life about something like the 'alert' function.

It is great that you can display the prompts in Windows TM's Window (what is its real name?).

 

I prefer standard CommandLine, because from the Windows TM's Window I haven't the possibility to select and copy text which is displayed in it.

And when the prompt is displayed in CommandLine, I have he possibility to select and copy text which is displayed in it.

 

0 Likes
Message 7 of 26

hmsilva
Mentor
Mentor
You're welcome, Damian.

Just wanted to share another approach, using dialog box/alert box.

Henrique

EESignature

0 Likes
Message 8 of 26

Anonymous
Not applicable

This lisp has one problem...

If we pick two points which create a vertical line (so Len_X=0 and when this lisp calculates Ang = Len_Y/Len_X, it divides by zero), the 'dividing by zero' error appears in the CommandLine.

 

I tried to solve this problem in two ways, but both of them generate errors, too:

 

; 2 -INFO ABOUT LINE BETWEEN TWO points
(defun c:2
 (/ angstring angun auni Ang
  DownslopePercents DownslopePercents2string
  Len Len_X Len_Y
  ptL1 ptL2
  XptL1 XptL2 YptL1 YptL2
 )
  (if (and (setq ptL1 (getpoint "\nSpecify First Point to calculate Downslope: "))
	   (setq ptL2 (getpoint "\nSpecify Second Point to calculate Downslope: "))
	   (not (equal ptL1 ptL2 1e-8))
      )
    (progn
      (setq XptL1 (car ptL1))
      (setq YptL1 (cadr ptL1))
      (setq XptL2 (car ptL2))
      (setq YptL2 (cadr ptL2))
      (setq Len_X (- XptL2 XptL1))
      (setq Len_Y (- YptL2 YptL1))
      ; What if XptL1 = XptL2 --> Len_X=0?
      ;; (setq len (distance ptL1 ptL2))
      (setq Len
	     (sqrt
	       (+ (* Len_X Len_X) (* Len_Y Len_Y))
	     ); sqrt
      ); Len
      (setq angun (getvar 'aunits))
      (cond ((or (= angun 0)
		 (= angun 1)
	     )
	     (setq auni "Degrees")
	    )
	    ((= angun 2)
	     (setq auni "Gradians")
	    )
	    ((= angun 3)
	     (setq auni "Radians")
	    )
	    ((= angun 4)
	     (setq auni "Surveyor")
	    )
      )
    ;  (setq Ang (atan Len_Y Len_X)) ; if you pick two Points which create Vertical line, the Length_X =0 and in the CommandLine there is ""error: Divide by zero"
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	 ; first way to solve this problem
	 ; that expression doesn't generate error of 'dividing by zero', but generates error of 'bad argument type: stringp'
     ;(setq Ang (getangle ptL1 ptL2))
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; second way to solve this problem.
    ; But it also generates 'dividing by zero' error.
	(
	   if Len_X<>0
	   (setq Ang (atan Len_Y Len_X))
	    (if
		 YptL2>YptL1
	     (setq Ang 90)
		 (setq Ang 270)
	    )
	   )
	   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	(setq angstring (strcat
	     (if (minusp ang) "-" "")
	     (angtos (abs ang) angun 3)))
      ;Len_Y/Len_X = DownslopePercents/100
      (setq DownslopePercents (* (/ Len_Y Len_X) 100))
      (setq DownslopePercents2string (rtos DownslopePercents 2 3))
      ; Mode=2= Decimal, Precision=3
      (princ (strcat "\nDownslope = " DownslopePercents2string  "%."))
	  (princ (strcat "\nLength_X = " (rtos Len_X 2 3) "."))
	  (princ (strcat "\nLength_Y = " (rtos Len_Y 2 3) "."))
      (princ (strcat "\nAngle = " angstring " " auni "."))
      (princ (strcat "\nLength = " (rtos Len 2 3) "."))
	  (princ "\nPress [F2] to open and close results in CommandLine.")
    )
    (prompt "\nYou did select the same point!!!")
  )
(princ);; exits quietly
);defun

 

What is the way to solve this problem?

Maybe use getangle to pick these two points (ptL1, ptL2)? But it would be a little bit not this what I want, because getangle gives possibility to TYPE OR PICK the Angle's value. And I want to have only one possibility - to PICK.

 

Please, help

0 Likes
Message 9 of 26

hmsilva
Mentor
Mentor

Maybe something like this will to do the trick

(Untested, I dont have AutoCAD in this laptop...)

 

; 2 -INFO ABOUT LINE BETWEEN TWO points
(defun c:2
 (/ angstring angun auni Ang
  DownslopePercents DownslopePercents2string
  Len Len_X Len_Y
  ptL1 ptL2
  XptL1 XptL2 YptL1 YptL2
 )
  (if (and (setq ptL1 (getpoint "\nSpecify First Point to calculate Downslope: "))
	   (setq ptL2 (getpoint "\nSpecify Second Point to calculate Downslope: "))
	   (not (equal ptL1 ptL2 1e-8))
      )
    (progn
      (setq XptL1 (car ptL1))
      (setq YptL1 (cadr ptL1))
      (setq XptL2 (car ptL2))
      (setq YptL2 (cadr ptL2))
      (setq Len_X (- XptL2 XptL1))
      (setq Len_Y (- YptL2 YptL1))
      ; What if XptL1 = XptL2 --> Len_X=0?
      ;; (setq len (distance ptL1 ptL2))
      (setq Len
	     (sqrt
	       (+ (* Len_X Len_X) (* Len_Y Len_Y))
	     ); sqrt
      ); Len
      (setq angun (getvar 'aunits))
      (cond ((or (= angun 0)
		 (= angun 1)
	     )
	     (setq auni "Degrees")
	    )
	    ((= angun 2)
	     (setq auni "Gradians")
	    )
	    ((= angun 3)
	     (setq auni "Radians")
	    )
	    ((= angun 4)
	     (setq auni "Surveyor")
	    )
      )
    ;  (setq Ang (atan Len_Y Len_X)) ; if you pick two Points which create Vertical line, the Length_X =0 and in the CommandLine there is ""error: Divide by zero"
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	 ; first way to solve this problem
	 ; that expression doesn't generate error of 'dividing by zero', but generates error of 'bad argument type: stringp'
     ;(setq Ang (getangle ptL1 ptL2))
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; second way to solve this problem.
    ; But it also generates 'dividing by zero' error.
	(if (zerop Len_X)
	   (setq Ang (atan Len_Y Len_X))
	    (if (> YptL2 YptL1)
	     (setq Ang 90)
		 (setq Ang 270)
	    )
	   )
	   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	(setq angstring (strcat
	     (if (minusp ang) "-" "")
	     (angtos (abs ang) angun 3)))
      ;Len_Y/Len_X = DownslopePercents/100
      (if (zerop Len_X)
        (setq DownslopePercents 100)
        (setq DownslopePercents (* (/ Len_Y Len_X) 100))
      )
      (setq DownslopePercents2string (rtos DownslopePercents 2 3))
      ; Mode=2= Decimal, Precision=3
      (princ (strcat "\nDownslope = " DownslopePercents2string  "%."))
	  (princ (strcat "\nLength_X = " (rtos Len_X 2 3) "."))
	  (princ (strcat "\nLength_Y = " (rtos Len_Y 2 3) "."))
      (princ (strcat "\nAngle = " angstring " " auni "."))
      (princ (strcat "\nLength = " (rtos Len 2 3) "."))
	  (princ "\nPress [F2] to open and close results in CommandLine.")
    )
    (prompt "\nYou did select the same point!!!")
  )
(princ);; exits quietly
);defun

 

Henrique

EESignature

0 Likes
Message 10 of 26

Anonymous
Not applicable

 

 

(if (zerop Len_X)

 (setq Ang (atan Len_Y Len_X))

 (if (> YptL2 YptL1)

    (setq Ang 90)

    (setq Ang 270)

 )

)

 

I think this red part stays in wrong place. Now this expression means: "If Len_X =0, calculate Ang=atan( Len_Y/ Len_X). And we know that if Len_X=0, the Ang is equal to 90 or 270.

 

So I change its position:

 

(if (zerop Len_X)

 (if (> YptL2 YptL1)

   (setq Ang 90)

   (setq Ang 270)

 )

 (setq Ang (atan Len_Y Len_X))

)

 

 

But it still returns 'divide by zero' error.

 

 

So I thought this might work:

 

(if (/= Len_X 0)
	  (setq Ang (atan Len_Y Len_X))
	   	(if (> YptL2 YptL1)
	         (setq Ang 90)
		 (setq Ang 270)
	        )
)

 But it also returns 'divide by zero' error.

 

 

0 Likes
Message 11 of 26

hmsilva
Mentor
Mentor

Your correct

(if (/= Len_X 0)
  (setq Ang (atan Len_Y Len_X))
   (if (> YptL2 YptL1)
         (setq Ang 90)
(setq Ang 270)
        )
)

 

but you'll need also to test further down in the code, the Len_X value, at

 

   ;Len_Y/Len_X = DownslopePercents/100
      (if (zerop Len_X)
        (setq DownslopePercents 100)
        (setq DownslopePercents (* (/ Len_Y Len_X) 100))
      )

 

Henrique

EESignature

0 Likes
Message 12 of 26

Anonymous
Not applicable

 

Now this lisp looks like this:

; 2 -INFO ABOUT LINE BETWEEN TWO points
(defun c:2
 (/ angstring angun auni Ang
  DownslopePercents DownslopePercents2string
  Len Len_X Len_Y
  ptL1 ptL2
  XptL1 XptL2 YptL1 YptL2
 )
  (if (and (setq ptL1 (getpoint "\nSpecify First Point to calculate Downslope: "))
	   (setq ptL2 (getpoint "\nSpecify Second Point to calculate Downslope: "))
	   (not (equal ptL1 ptL2 1e-8))
      )
    (progn
      (setq XptL1 (car ptL1))
      (setq YptL1 (cadr ptL1))
      (setq XptL2 (car ptL2))
      (setq YptL2 (cadr ptL2))
      (setq Len_X (- XptL2 XptL1))
      (setq Len_Y (- YptL2 YptL1))
      ; What if XptL1 = XptL2 --> Len_X=0?
	  
      ;; (setq len (distance ptL1 ptL2))
      (setq Len
	     (sqrt
	       (+ (* Len_X Len_X) (* Len_Y Len_Y))
	     ); sqrt
      ); Len
	  
      (setq angun (getvar 'aunits))
      (cond ((or (= angun 0)
		 (= angun 1)
	     )
	     (setq auni "Degrees")
	    )
	    ((= angun 2)
	     (setq auni "Gradians")
	    )
	    ((= angun 3)
	     (setq auni "Radians")
	    )
	    ((= angun 4)
	     (setq auni "Surveyor")
	    )
      )
	  
     ; (setq Ang (atan Len_Y Len_X)) ; if you pick two Points which create Vertical line, the Length_X =0 and in the ;CommandLine there is ""error: Divide by zero"
	(if (/= Len_X 0)
      (setq Ang (atan Len_Y Len_X))
        (if (> YptL2 YptL1)
         (setq Ang 90)
         (setq Ang 270)
        )
    )

	(setq angstring (strcat
	     (if (minusp Ang) "-" "")
	     (angtos (abs Ang) angun 3)))
		 
      ;Len_Y/Len_X = DownslopePercents/100
	        (if (zerop Len_X)
        (setq DownslopePercents 100)
        (setq DownslopePercents (* (/ Len_Y Len_X) 100))
      )
	  
      (setq DownslopePercents2string (rtos DownslopePercents 2 3))
      ; Mode=2= Decimal, Precision=3
      (princ (strcat "\nDownslope = " DownslopePercents2string  "%."))
	  (princ (strcat "\nLength_X = " (rtos Len_X 2 3) "."))
	  (princ (strcat "\nLength_Y = " (rtos Len_Y 2 3) "."))
      (princ (strcat "\nAngle = " angstring " " auni "."))
      (princ (strcat "\nLength = " (rtos Len 2 3) "."))
	  (princ "\nPress [F2] to open and close results in CommandLine.")
    )
	
    (prompt "\nYou did select the same point!!!")
  )
(princ);; exits quietly
);defun

 

 But when I pick two points on the Line which Angle is 90, there is such prompt in CommandLine:

 

Command: 2
Specify First Point to calculate Downslope:
Specify Second Point to calculate Downslope:
Downslope = 100.000%.
Length_X = 0.000.
Length_Y = 36.657.
Angle = 116.620 Degrees.
Length = 36.657.
Press [F2] to open and close results in CommandLine.

Command:

 

What about this number? It should be equal 90, not 116.620. Is that because of 'angun 3'? 

 

 

0 Likes
Message 13 of 26

hmsilva
Mentor
Mentor

Change the test, to

 

(if (/= Len_X 0)
          (setq Ang (atan Len_Y Len_X))
          (if (> YptL2 YptL1)
            (setq Ang (* pi 0.5))
            (setq Ang (* pi 1.5))
          )
        )

 

Henrique

EESignature

0 Likes
Message 14 of 26

Anonymous
Not applicable

I have solution for this problem.

 

And, what's more, I noticed, that there was one more not good made thing.

What was that thing?

 

So, if we draw line AB where point B is in the south-west direction from A, and if we click on this Line, in the Properties Palette (Ctrl+1) there will be an Angle value of some number between 180 and 270. And in this lisp which we had, in this situation in CommandLine there would be an value between (-180) and (-90) Degrees.

 

So i repair this thing too.

 

And now, here is our good made lisp:

 

 

; 2 -INFO ABOUT LINE BETWEEN TWO points
(defun c:2
 (/ angstring angun auni Ang
  DownslopePercents DownslopePercents2string
  Len Len_X Len_Y
  ptL1 ptL2
  XptL1 XptL2 YptL1 YptL2
 )
  (if (and (setq ptL1 (getpoint "\nSpecify First Point to calculate Downslope: "))
	   (setq ptL2 (getpoint "\nSpecify Second Point to calculate Downslope: "))
	   (not (equal ptL1 ptL2 1e-8))
      )
    (progn
      (setq XptL1 (car ptL1))
      (setq YptL1 (cadr ptL1))
      (setq XptL2 (car ptL2))
      (setq YptL2 (cadr ptL2))
      (setq Len_X (- XptL2 XptL1))
      (setq Len_Y (- YptL2 YptL1))
      ; What if XptL1 = XptL2 --> Len_X=0?
	  
      ;; (setq len (distance ptL1 ptL2))
      (setq Len
	     (sqrt
	       (+ (* Len_X Len_X) (* Len_Y Len_Y))
	     ); sqrt
      ); Len
	  
      (setq angun (getvar 'aunits))
      (cond ((or (= angun 0)
		 (= angun 1)
	     )
	     (setq auni "Degrees")
	    )
	    ((= angun 2)
	     (setq auni "Gradians")
	    )
	    ((= angun 3)
	     (setq auni "Radians")
	    )
	    ((= angun 4)
	     (setq auni "Surveyor")
	    )
      )
	  
     ; (setq Ang (atan Len_Y Len_X)) ; if you pick two Points which create Vertical line, the Length_X =0 and in the CommandLine there is ""error: Divide by zero"
	(if (/= Len_X 0)
      (setq Ang (atan Len_Y Len_X))
        (if (> YptL2 YptL1)
         (setq Ang (/ PI 2))       ; I gave PI/2 and 3PI/2 instead of 90 and 270, because Ang is an angle in Radians
         (setq Ang (* 3 (/ PI 2))
         )
	    )
    )

	(setq angstring 
	  (strcat
	     (if (minusp Ang)
		 (angtos (- (* 2 PI) (abs Ang) ) angun 3) ; I gave 2PI-Ang instead of (-Ang) in order to have a value ;such like it would be in Properties Palette
		 (angtos (abs Ang) angun 3)
		 )
	  )
	)
		 
      ;Len_Y/Len_X = DownslopePercents/100
	        (if (zerop Len_X)
        (setq DownslopePercents 100)
        (setq DownslopePercents (* (/ Len_Y Len_X) 100))
      )
	  
      (setq DownslopePercents2string (rtos DownslopePercents 2 3))
      ; Mode=2= Decimal, Precision=3
      (princ (strcat "\nDownslope = " DownslopePercents2string  "%."))
	  (princ (strcat "\nLength_X = " (rtos Len_X 2 3) "."))
	  (princ (strcat "\nLength_Y = " (rtos Len_Y 2 3) "."))
      (princ (strcat "\nAngle = " angstring " " auni "."))
      (princ (strcat "\nLength = " (rtos Len 2 3) "."))
	  (princ "\nPress [F2] to open and close results in CommandLine.")
    )
	
    (prompt "\nYou did select the same point!!!")
  )
(princ);; exits quietly
);defun

 

 

Thank you all for help. Now we could enjoy it and inspect all things we need with this one lisp.

0 Likes
Message 15 of 26

hmsilva
Mentor
Mentor
Glad you have it sorted!

Henrique

EESignature

0 Likes
Message 16 of 26

Anonymous
Not applicable

I noticed, that when I picked two points which create 'Line' which Angle Property is 90 or 270, in CommandLine there is prompt that Downslope= some very big number of %'s.

But it should prompt Downslope=100% for Angle=90 and -100% for Angle=270.

 

So I rewrote this lisp (instead of this I used this).

 

 

And now it looks like this:

 

; 2 -INFO ABOUT LINE BETWEEN TWO points
(defun c:2231
 (/ angstring angun auni Ang
  DownslopePercents DownslopePercents2string
  Len Len_X Len_Y
  ptL1 ptL2
  XptL1 XptL2 YptL1 YptL2
 )
  (if (and (setq ptL1 (getpoint "\nSpecify First Point to calculate Downslope: "))
	   (setq ptL2 (getpoint "\nSpecify Second Point to calculate Downslope: "))
	   (not (equal ptL1 ptL2 1e-8))
      )
    (progn
      (setq XptL1 (car ptL1))
      (setq YptL1 (cadr ptL1))
      (setq XptL2 (car ptL2))
      (setq YptL2 (cadr ptL2))
      (setq Len_X (- XptL2 XptL1))
      (setq Len_Y (- YptL2 YptL1))
      ; What if XptL1 = XptL2 --> Len_X=0?
	  
      ;; (setq len (distance ptL1 ptL2))
      (setq Len
	     (sqrt
	       (+ (* Len_X Len_X) (* Len_Y Len_Y))
	     ); sqrt
      ); Len
	  
      (setq angun (getvar 'aunits))
      (cond ((or (= angun 0)
		 (= angun 1)
	     )
	     (setq auni "Degrees")
	    )
	    ((= angun 2)
	     (setq auni "Gradians")
	    )
	    ((= angun 3)
	     (setq auni "Radians")
	    )
	    ((= angun 4)
	     (setq auni "Surveyor")
	    )
      )
	  
     ; (setq Ang (atan Len_Y Len_X)) ; if you pick two Points which create Vertical line, the Length_X =0 and in the CommandLine there is ""error: Divide by zero"
	(if (/= Len_X 0)
	
      (
		(setq Ang (atan Len_Y Len_X))
		(setq DownslopePercents (* (/ Len_Y Len_X) 100))
	  )
	  
      (if (> YptL2 YptL1)
	  
		(
         (setq Ang (/ PI 2))       ; I gave PI/2 and 3PI/2 instead of 90 and 270, because Ang is an angle in Radians
         (setq DownslopePercents 100)
		)
		
		(
         (setq Ang (* 3 (/ PI 2)))
		 (setq DownslopePercents (- 0 100))
		) 
	  )
    )

	(setq angstring 
	  (strcat
	     (if (minusp Ang)
		 (angtos (- (* 2 PI) (abs Ang) ) angun 3) ; I gave 2PI-Ang instead of (-Ang) in order to have a value ;such like it would be in Properties Palette
		 (angtos (abs Ang) angun 3)
		 )
	  )
	)
		 
;Len_Y/Len_X = DownslopePercents/100
;	        (if (zerop Len_X)
;        (setq DownslopePercents 100)
;        (setq DownslopePercents (* (/ Len_Y Len_X) 100))
;      )
	  
      (setq DownslopePercents2string (rtos DownslopePercents 2 3))
      ; Mode=2= Decimal, Precision=3
      (princ (strcat "\nDownslope = " DownslopePercents2string  "%."))
	  (princ (strcat "\nLength_X = " (rtos Len_X 2 3) "."))
	  (princ (strcat "\nLength_Y = " (rtos Len_Y 2 3) "."))
      (princ (strcat "\nAngle = " angstring " " auni "."))
      (princ (strcat "\nLength = " (rtos Len 2 3) "."))
	  (princ "\nPress [F2] to open and close results in CommandLine.")
    )
	
    (prompt "\nYou did select the same point!!!")
  )
(princ);; exits quietly
);defun

 

But there is some error.

In CommandLine there is:

"; error: bad function: 0.329309"

 

And I don't know what the cause could be.

Could you tell me what I wrote wrong?

0 Likes
Message 17 of 26

hmsilva
Mentor
Mentor

Hi Damian,

 

at the momentdon't have AutoCAD to test your code, but in a quick read I have noticed that the test 'if' are not written correctly...

 

e.g.

 (if (/= Len_X 0)
 (
  (setq Ang (atan Len_Y Len_X))
  (setq DownslopePercents (* (/ Len_Y Len_X) 100))
   )

 

in a 'if' function, we must have the

 

(if (test function)

(expression to be evaluated if not nil)

(expression to be evaluated if nil)

)

 

Henrique

EESignature

0 Likes
Message 18 of 26

Anonymous
Not applicable

I add some ';' marks to modify my modified lisp (and now instead of this I use this). Now this lisp with ';' is working:

 

; 2 -INFO ABOUT LINE BETWEEN TWO points
(defun c:234
 (/ angstring angun auni Ang
  DownslopePercents DownslopePercents2string
  Len Len_X Len_Y
  ptL1 ptL2
  XptL1 XptL2 YptL1 YptL2
 )
  (if (and (setq ptL1 (getpoint "\nSpecify First Point to calculate Downslope: "))
	   (setq ptL2 (getpoint "\nSpecify Second Point to calculate Downslope: "))
	   (not (equal ptL1 ptL2 1e-8))
      )
    (progn
      (setq XptL1 (car ptL1))
      (setq YptL1 (cadr ptL1))
      (setq XptL2 (car ptL2))
      (setq YptL2 (cadr ptL2))
      (setq Len_X (- XptL2 XptL1))
      (setq Len_Y (- YptL2 YptL1))
      ; What if XptL1 = XptL2 --> Len_X=0?
	  
      ;; (setq len (distance ptL1 ptL2))
      (setq Len
	     (sqrt
	       (+ (* Len_X Len_X) (* Len_Y Len_Y))
	     ); sqrt
      ); Len
	  
      (setq angun (getvar 'aunits))
      (cond ((or (= angun 0)
		 (= angun 1)
	     )
	     (setq auni "Degrees")
	    )
	    ((= angun 2)
	     (setq auni "Gradians")
	    )
	    ((= angun 3)
	     (setq auni "Radians")
	    )
	    ((= angun 4)
	     (setq auni "Surveyor")
	    )
      )
	  
     ; (setq Ang (atan Len_Y Len_X)) ; if you pick two Points which create Vertical line, the Length_X =0 and in the CommandLine there is ""error: Divide by zero"
	(if (/= Len_X 0)
	  
;	  (
        (setq Ang (atan Len_Y Len_X))
;	    (setq DownslopePercents (* (/ Len_Y Len_X) 100))
;	  )
	  
      (if (> YptL2 YptL1)
		
;		(
         (setq Ang (/ PI 2))       ; I gave PI/2 and 3PI/2 instead of 90 and 270, because Ang is an angle in Radians
;		 (setq DownslopePercents 100)
;        ) 
		
;		(
		 (setq Ang (* 3 (/ PI 2)))
;		 (setq DownslopePercents (- 0 100))
;	    )
      )
	)  

	(setq angstring 
	  (strcat
	     (if (minusp Ang)
		 (angtos (- (* 2 PI) (abs Ang) ) angun 3) ; I gave 2PI-Ang instead of (-Ang) in order to have a value ;such like it would be in Properties Palette
		 (angtos (abs Ang) angun 3)
		 )
	  )
	)
		 
      ;Len_Y/Len_X = DownslopePercents/100
	        (if (zerop Len_X)
        (setq DownslopePercents 100)
        (setq DownslopePercents (* (/ Len_Y Len_X) 100))
      )
	  
      (setq DownslopePercents2string (rtos DownslopePercents 2 3))
      ; Mode=2= Decimal, Precision=3
      (princ (strcat "\nDownslope = " DownslopePercents2string  "%."))
	  (princ (strcat "\nLength_X = " (rtos Len_X 2 3) "."))
	  (princ (strcat "\nLength_Y = " (rtos Len_Y 2 3) "."))
      (princ (strcat "\nAngle = " angstring " " auni "."))
      (princ (strcat "\nLength = " (rtos Len 2 3) "."))
	  (princ "\nPress [F2] to open and close results in CommandLine.")
    )
	
    (prompt "\nYou did select the same point!!!")
  )
(princ);; exits quietly
);defun

 

It might help to solve my problem.

0 Likes
Message 19 of 26

Anonymous
Not applicable

Not correnctly? 

(if (condition)

    (then do this)

    (else do this)

)

 

I want to do two things in "then do this" part, and to do two things in "else do this" part.

 

(if (> YptL2 YptL1) ; condition
	  
		( ; then
         (setq Ang (/ PI 2))       ; I gave PI/2 and 3PI/2 instead of 90 and 270, because Ang is an angle in Radians
         (setq DownslopePercents 100)
		) ; end of then
		
		( ; else
         (setq Ang (* 3 (/ PI 2)))
		 (setq DownslopePercents (- 0 100))
		) ; end of else
	  ); end of if

 

Maybe Autocad reads 

(setq DownslopePercents 100)

as an argument for

(setq Ang (/ PI 2))

? But Autocad doesn't should read it that way...

 

Maybe in the 'if' statement, in both "then do this" part, and in "else do this" part, there should be only one thing to do?

 

0 Likes
Message 20 of 26

Anonymous
Not applicable

I see, that my statemant:

"Maybe in the 'if' statement, in both "then do this" part, and in "else do this" part, there should be only one thing to do?"

is correct.

 

I wrote second if, separately, specailly for 'Downslope':

 

; 2 -INFO ABOUT LINE BETWEEN TWO points
(defun c:2
(/ angstring angun auni Ang
DownslopePercents DownslopePercents2string
Len Len_X Len_Y
ptL1 ptL2
XptL1 XptL2 YptL1 YptL2
)
(if (and (setq ptL1 (getpoint "\nSpecify First Point to calculate Downslope: "))
(setq ptL2 (getpoint "\nSpecify Second Point to calculate Downslope: "))
(not (equal ptL1 ptL2 1e-8))
)
(progn
(setq XptL1 (car ptL1))
(setq YptL1 (cadr ptL1))
(setq XptL2 (car ptL2))
(setq YptL2 (cadr ptL2))
(setq Len_X (- XptL2 XptL1))
(setq Len_Y (- YptL2 YptL1))
; What if XptL1 = XptL2 --> Len_X=0?

;; (setq len (distance ptL1 ptL2))
(setq Len
(sqrt
(+ (* Len_X Len_X) (* Len_Y Len_Y))
); sqrt
); Len

(setq angun (getvar 'aunits))
(cond ((or (= angun 0)
(= angun 1)
)
(setq auni "Degrees")
)
((= angun 2)
(setq auni "Gradians")
)
((= angun 3)
(setq auni "Radians")
)
((= angun 4)
(setq auni "Surveyor")
)
)

; First 'if', for 'Angle'
; (setq Ang (atan Len_Y Len_X)) ; if you pick two Points which create Vertical line, the Length_X =0 and in the CommandLine there is ""error: Divide by zero" (if (/= Len_X 0) ; ( (setq Ang (atan Len_Y Len_X)) ; (setq DownslopePercents (* (/ Len_Y Len_X) 100)) ; ) (if (> YptL2 YptL1) ; ( (setq Ang (/ PI 2)) ; I gave PI/2 and 3PI/2 instead of 90 and 270, because Ang is an angle in Radians ; (setq DownslopePercents 100) ; ) ; ( (setq Ang (* 3 (/ PI 2))) ; (setq DownslopePercents (- 0 100)) ; ) ) ) ; end of first 'if'
; second 'if', this time for 'Downslope' (if (/= Len_X 0) ; ( ; (setq Ang (atan Len_Y Len_X)) (setq DownslopePercents (* (/ Len_Y Len_X) 100)) ; ) (if (> YptL2 YptL1) ; ( ; (setq Ang (/ PI 2)) ; I gave PI/2 and 3PI/2 instead of 90 and 270, because Ang is an angle in Radians (setq DownslopePercents 100) ; ) ; ( ; (setq Ang (* 3 (/ PI 2))) (setq DownslopePercents (- 0 100)) ; ) ) ); end of second 'if' (setq angstring (strcat (if (minusp Ang) (angtos (- (* 2 PI) (abs Ang) ) angun 3) ; I gave 2PI-Ang instead of (-Ang) in order to have a value ;such like it would be in Properties Palette (angtos (abs Ang) angun 3) ) ) ) ;Len_Y/Len_X = DownslopePercents/100 ; (if (zerop Len_X) ; (setq DownslopePercents 100) ; (setq DownslopePercents (* (/ Len_Y Len_X) 100)) ; ) (setq DownslopePercents2string (rtos DownslopePercents 2 3)) ; Mode=2= Decimal, Precision=3 (princ (strcat "\nDownslope = " DownslopePercents2string "%.")) (princ (strcat "\nLength_X = " (rtos Len_X 2 3) ".")) (princ (strcat "\nLength_Y = " (rtos Len_Y 2 3) ".")) (princ (strcat "\nAngle = " angstring " " auni ".")) (princ (strcat "\nLength = " (rtos Len 2 3) ".")) (princ "\nPress [F2] to open and close results in CommandLine.") ) (prompt "\nYou did select the same point!!!") ) (princ);; exits quietly );defun

 And now it works good.

 

 

0 Likes