Jump to content
tomhamlet

First Lisp Written Solo!

Recommended Posts

tomhamlet

I have been getting back into lisp, after I had a class that scratched the surface of lisp, I never looked back on it until now. This is my first lisp command written without copying it from a book!

(defun c:ibeamp()
(setq pw (getdist "\nEnter Beam Width: "))
(setq ih (getdist "\nEnter Inner Height: "))
(setq pt (getdist "\nEnter Plate Thickness: "))
(setq po (getdist "\nEnter Overhang Distance: "))
(setq ip (getpoint "\nInsertion point: "))
(setq p2 (polar ip (dtr 180.0) (/ pw 2)))
(setq p3 (polar p2 (dtr 270.0) pt))
(setq p4 (polar p3 (dtr 0.0) po))
(setq p5 (polar p4 (dtr 270.0) ih))
(setq p6 (polar p5 (dtr 180.0) po))
(setq p7 (polar p6 (dtr 270.0) pt))
(setq p8 (polar p7 (dtr 0.0) pw))
(setq p9 (polar p8 (dtr 90.0) pt))
(setq p10 (polar p9 (dtr 180.0) po))
(setq p11 (polar p10 (dtr 90.0) ih))
(setq p12 (polar p11 (dtr 0.0) po))
(setq p13 (polar p12 (dtr 90.0) pt))
(command "line" ip p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 "c"
)
(princ)
)
(defun dtr (x)
(* pi (/ x 180.0))
)
(princ)

 

this draws a very general I-beam. Any feedback is appreciated, constructive more so :)

Share this post


Link to post
Share on other sites
MSasu

Some observations:

 

  • To make sure that avoid any interference with current auto Osnap mode, you need to disable it when call the command - check the OSMODE system variable. Also, a good programming practice is to retain the user environment and restore it at the end.

(setq oldOsmode (getvar "OSMODE"))
(setvar "OSMODE" 0)
;call commands
(setvar "OSMODE" oldOsmode)

  • In order to avoid interference with other routines you should use local variables:

(defun c:ibeamp( / [color=red]pv ih pt po ...[/color])

  • To ensure that your code works well with localized versions of AutoCAD (that it, in languages other than English) use an uderscore when call commands and options:

(command "[color=red]_.[/color]LINE" ... "[color=red]_[/color]C")

 

  • Not less important is to get used to add comments to your code; it will be very useful when decide to review it later.

Share this post


Link to post
Share on other sites
tomhamlet

great!

(defun c:ibeamp(pw ih pt po ip)
(setq pw (getdist "\nEnter Beam Width: "))
(setq ih (getdist "\nEnter Inner Height: "))
(setq pt (getdist "\nEnter Plate Thickness: "))
(setq po (getdist "\nEnter Overhang Distance: "))
(setq ip (getpoint "\nInsertion point: "))
(setq p2 (polar ip (dtr 180.0) (/ pw 2)))
(setq p3 (polar p2 (dtr 270.0) pt))
(setq p4 (polar p3 (dtr 0.0) po))
(setq p5 (polar p4 (dtr 270.0) ih))
(setq p6 (polar p5 (dtr 180.0) po))
(setq p7 (polar p6 (dtr 270.0) pt))
(setq p8 (polar p7 (dtr 0.0) pw))
(setq p9 (polar p8 (dtr 90.0) pt))
(setq p10 (polar p9 (dtr 180.0) po))
(setq p11 (polar p10 (dtr 90.0) ih))
(setq p12 (polar p11 (dtr 0.0) po))
(setq p13 (polar p12 (dtr 90.0) pt))
(command "line" ip p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 "c"
)
(princ)
)
(defun dtr (x)
(* pi (/ x 180.0))
)
(princ)

is this what you mean?

Share this post


Link to post
Share on other sites
BlackBox

First, congrats on writing your first LISP. :beer:

 

... One thing to beware, if you prompt the user for input and they do not enter a valid response, you need to account for that rather than allowing the code to progress as this may cause an error.

 

As an example, consider pw = nil. :thumbsup:

 

One common way of mitigating this is to use an IF statement, and in your case an AND statement may also be helpful.

Share this post


Link to post
Share on other sites
tomhamlet
First, congrats on writing your first LISP. :beer:

 

... One thing to beware, if you prompt the user for input and they do not enter a valid response, you need to account for that rather than allowing the code to progress as this may cause an error.

 

As an example, consider pw = nil. :thumbsup:

 

One common way of mitigating this is to use an IF statement, and in your case an AND statement may also be helpful.

I do want to get into the IF and And commands soon. but im making sure I know what these routine do first. Thank you!

Share this post


Link to post
Share on other sites
BlackBox
I do want to get into the IF and And commands soon. but im making sure I know what these routine do first. Thank you!

 

In an attempt to give you an example that does not remove the excitement from having written your first routine, please take from this pseudo code example what you like (building on multiple comments):

 

(defun c:FOO ( / ;|localVariables|; pw ih pt po ip)

 ;; If, the user enters all of the necessary criteria
 (if (and (setq pw (getdist "\nEnter Beam Width: "))
          (setq ih (getdist "\nEnter Inner Height: "))
          (setq pt (getdist "\nEnter Plate Thickness: "))
          (setq po (getdist "\nEnter Overhang Distance: "))
          (setq ip (getpoint "\nInsertion point: "))
     )

   ;; Then, continue the routine
   (prompt
     "\nThanks for entering all of the necessary criteria. "
   )

   ;; Else, tell the user what they failed to specify
   (cond (po (prompt "\n** Insertion point required ** "))
         (pt (prompt "\n** Overhang distance required ** "))
         (ih (prompt "\n** Plate thickness required ** "))
         (pw (prompt "\n** Inner height required ** "))
         ((prompt "\n** Beam width required ** "))
   )
 )
 (princ)
)

Edited by BlackBox

Share this post


Link to post
Share on other sites
tomhamlet
In an attempt to give you an example that does not remove the excitement from having written your first routine, please take from this pseudo code example what you like (building on multiple comments):

 

thanks. I will definately give it a shot!

Share this post


Link to post
Share on other sites
Lee Mac
(defun c:FOO ([color=red];|globalVariables|;[/color] / ;|localVariables|; pw ih pt po ip)

 

The above highlighted section should instead read 'function parameters', as global variables are not declared in the defun expression. ;)

Share this post


Link to post
Share on other sites
BlackBox
The above highlighted section should instead read 'function parameters', as global variables are not declared in the defun expression. ;)

 

Good catch, Lee; code corrected (oops).

Share this post


Link to post
Share on other sites
BlackBox
The above highlighted section should instead read 'function parameters', as global variables are not declared in the defun expression. ;)

 

Good catch, Lee; code corrected (oops).

 

... Actually no, that shouldn't be there either (in this instance).

 

Your correction and reference to the Defun function are correct, it's just that as this is a c: prefixed symbol, the function parameters are not used.

Share this post


Link to post
Share on other sites
BIGAL

Another suggestion rather than use Dtr 180 why not pid, dtr 270 pil, your already using the defun Dtr so why not add a couple more, you can take the lisp value of PI and divide it etc

 

(setq Pil (* pi() 1.5))
(setq pid pi() )
(setq piu (* 0.5 pi() ))
remember pir is 0.0 in radians to right you may want this for consistancy

Share this post


Link to post
Share on other sites
tomhamlet
Another suggestion rather than use Dtr 180 why not pid, dtr 270 pil, your already using the defun Dtr so why not add a couple more, you can take the lisp value of PI and divide it etc

 

I have gotten so far as to know what pid, pil, piu, and pir is yet! thanks for the help guys. An extra thanks to Lee Mac, as his sight and tutorials were a big part, along with afralisp, of helping me understand the functions that went into this first lisp.

Share this post


Link to post
Share on other sites
Lee Mac
An extra thanks to Lee Mac, as his sight and tutorials were a big part, along with afralisp, of helping me understand the functions that went into this first lisp.

 

You're very welcome - I'm delighted that my tutorials were helpful in your learning.

 

Here are my suggestions for your program:

([color=BLUE]defun[/color] c:ibeamp ( [color=BLUE]/[/color] 3pi/2 cm ih ip os p10 p11 p12 p13 p2 p3 p4 p5 p6 p7 p8 p9 pi/2 po pt pw )
   [color=GREEN];; Define function and declare local variables[/color]
   [color=GREEN];; Localising Variables: http://lee-mac.com/localising.html[/color]

   [color=GREEN];; If the following expression returns a non-nil value[/color]
   ([color=BLUE]if[/color]
       [color=GREEN];; All of the following expressions must return a non-nil[/color]
       [color=GREEN];; value for AND to return T[/color]
       ([color=BLUE]and[/color]
           [color=GREEN];; Prompt user for I-Beam parameters[/color]
           ([color=BLUE]setq[/color] ip ([color=BLUE]getpoint[/color] [color=MAROON]"\nInsertion Point: "[/color]))
           ([color=BLUE]setq[/color] pw ([color=BLUE]getdist[/color] ip [color=MAROON]"\nSpecify Beam Width: "[/color]))
           ([color=BLUE]setq[/color] ih ([color=BLUE]getdist[/color] ip [color=MAROON]"\nSpecify Inner Height: "[/color]))
           ([color=BLUE]setq[/color] pt ([color=BLUE]getdist[/color] ip [color=MAROON]"\nSpecify Plate Thickness: "[/color]))
           ([color=BLUE]setq[/color] po ([color=BLUE]getdist[/color] ip [color=MAROON]"\nSpecify Overhang Distance: "[/color]))
       ) [color=GREEN];; end AND[/color]

       ([color=BLUE]progn[/color]
           [color=GREEN];; Wrap the following expressions within a PROGN expression.[/color]
           [color=GREEN];; PROGN will simply evaluate every enclosed expression in turn[/color]
           [color=GREEN];; and will return the result of the last evaluated expression.[/color]
           [color=GREEN];;[/color]
           [color=GREEN];; By enclosing the expressions within the PROGN function, we[/color]
           [color=GREEN];; can pass the *single* PROGN expression to the IF function[/color]
           [color=GREEN];; to constitute the 'then' argument of the IF function.[/color]

           [color=GREEN];; Store some convenient multiples of pi:[/color]
           ([color=BLUE]setq[/color]  pi/2 ([color=BLUE]*[/color] [color=BLUE]pi[/color] 0.5)
                 3pi/2 ([color=BLUE]*[/color] [color=BLUE]pi[/color] 1.5)
           
           [color=GREEN];; Calculate the necessary points:[/color]
                    p2 ([color=BLUE]polar[/color] ip [color=BLUE]pi[/color] ([color=BLUE]/[/color] pw 2.0))
                    p3 ([color=BLUE]polar[/color] p2 3pi/2 pt)
                    p4 ([color=BLUE]polar[/color] p3 0.0 po)
                    p5 ([color=BLUE]polar[/color] p4 3pi/2 ih)
                    p6 ([color=BLUE]polar[/color] p5 [color=BLUE]pi[/color] po)
                    p7 ([color=BLUE]polar[/color] p6 3pi/2 pt)
                    p8 ([color=BLUE]polar[/color] p7 0.0 pw)
                    p9 ([color=BLUE]polar[/color] p8 pi/2 pt)
                   p10 ([color=BLUE]polar[/color] p9 [color=BLUE]pi[/color] po)
                   p11 ([color=BLUE]polar[/color] p10 pi/2 ih)
                   p12 ([color=BLUE]polar[/color] p11 0.0 po)
                   p13 ([color=BLUE]polar[/color] p12 pi/2 pt)
           ) [color=GREEN];; end SETQ[/color]

           [color=GREEN];; Store Object Snap setting[/color]
           ([color=BLUE]setq[/color] os ([color=BLUE]getvar[/color] 'osmode)
           [color=GREEN];; Store CMDECHO setting[/color]
                 cm ([color=BLUE]getvar[/color] 'cmdecho)
           )            
           [color=GREEN];; Disable Object Snap[/color]
           ([color=BLUE]setvar[/color] 'osmode ([color=BLUE]logior[/color] os 16384))
           [color=GREEN];; Turn off CMDECHO[/color]
           ([color=BLUE]setvar[/color] 'cmdecho 0)

           [color=GREEN];; Construct a Polyline[/color]
           [color=GREEN];; "_"    = Accounts for other languages of AutoCAD[/color]
           [color=GREEN];; "."    = Use in-built command, not a redefinition[/color]
           ([color=BLUE]command[/color] [color=MAROON]"_.pline"[/color] ip p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 [color=MAROON]"_C"[/color])

           [color=GREEN];; Reset CMDECHO[/color]
           ([color=BLUE]setvar[/color] 'cmdecho cm)
           [color=GREEN];; Reset Object Snap setting[/color]
           ([color=BLUE]setvar[/color] 'osmode os)
           
       ) [color=GREEN];; end PROGN[/color]

       [color=GREEN];; If we had an 'else' expression for the IF function, it would go here.[/color]
       
   ) [color=GREEN];; end IF[/color]
   
   [color=GREEN];; Suppress the return of the last evaluated expression[/color]
   ([color=BLUE]princ[/color])
) [color=GREEN];; end DEFUN[/color]

I have tried not to deviate too far from your original code to keep the program clear and comprehensible for you to learn from, but please ask if you have any questions about any of my modifications or comments.

Share this post


Link to post
Share on other sites
tomhamlet
You're very welcome - I'm delighted that my tutorials were helpful in your learning.

 

Here are my suggestions for your program:

 

please, deviate as much as you can, the more you deviate, the more things i will see that I haven't before, so i will be forced to ask more questions and learn! Here are 2 that I have from your code:

1. could you explain this line;(setvar 'osmode (logior os 16384)). I am not sure I am familiar with logior or the code 16384.

2. what control is cmdecho?

Share this post


Link to post
Share on other sites
BlackBox
please, deviate as much as you can, the more you deviate, the more things i will see that I haven't before, so i will be forced to ask more questions and learn! Here are 2 that I have from your code:

1. could you explain this line;(setvar 'osmode (logior os 16384)). I am not sure I am familiar with logior or the code 16384.

2. what control is cmdecho?

 

I will not answer for Lee, but in anticipation of his response I would simply offer the suggestion that when curious about a function, feel free to look it up in the Developer Documentation. :thumbsup:

Share this post


Link to post
Share on other sites
tomhamlet

once again dooped by my own tendancy to go straight to the web, rather than use the autocad help right under my nose. thanks RenderMan, i will definately look into it.

Share this post


Link to post
Share on other sites
Lee Mac
please, deviate as much as you can, the more you deviate, the more things i will see that I haven't before, so i will be forced to ask more questions and learn!

 

True - but equally you don't want to be overwhelmed with information when you are just starting out; by keeping close to your original code, you can follow and understand my alterations without feeling that I have simply written the program for you ;)

 

1. could you explain this line;(setvar 'osmode (logior os 16384)). I am not sure I am familiar with logior or the code 16384.

 

The 16384 bit-code disables Object Snap whilst retaining the various Object Snap settings (such as endpoint / midpoint / intersection etc.) - setting the 16384 bit-code in the OSMODE System Variable is the equivalent of the user toggling the Object Snap off using the F3 key.

 

The full list of bit-codes for the OSMODE System Variable is as follows (this list can be found by listing the OSMODE System Variable in the sysvdlg command):

 

0       NONe
1       ENDpoint
2       MIDpoint
4       CENter
8       NODe
16      QUAdrant
32      INTersection
64      INSertion
128     PERpendicular
256     TANgent
512     NEArest
1024    QUIck
2048    APParent Intersection
4096    EXTension
8192    PARallel
16384   Disable Object Snap

As for logior, now we are entering the realm of bitwise logic - logior returns the bitwise inclusive OR (as opposed to the exclusive XOR) of two or more integers. If you need more information about bitwise logic, there are a plethora of examples on the web, as bitwise values are used extensively in many programming languages.

 

2. what control is cmdecho?

 

CMDECHO

 

Or look it up using sysvdlg

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×