Trying to make a basic LISP to Create a Square

Trying to make a basic LISP to Create a Square

JCKRU47
Advocate Advocate
660 Views
9 Replies
Message 1 of 10

Trying to make a basic LISP to Create a Square

JCKRU47
Advocate
Advocate

I am trying to make my first LISP command and I am teaching myself from online information an tutorials. There is a lot of information out there and I know a command like this already exists, but I am trying to make sure I understand the basics. So far the command I have is as follows:

 

(Defun C:ESQ ()
(setq InitLen (getreal (strcat "Would you kindly enter a length?("rtos InitLen 2 0)")))
(if Len (setq initLen Len)(setq Len 4))
(While (setq user_point (getpoint "Select Desired End Point: "))
(command "polygon, 4" user_point "L" Len "")
)

 

I can't get this to work and I know it has problems, but I am unsure of what they are. I  just need a good step in the right direction if possible.

 

For a little bit more background, I took a little bit of what I learned and a little bit of what looked like the right command form different LISP commands to make this Frankenstein's monster.

 

Any and all feedback is greatly appreciated.

0 Likes
Accepted solutions (1)
661 Views
9 Replies
Replies (9)
Message 2 of 10

Kent1Cooper
Consultant
Consultant

(Defun C:ESQ ()
;  (setq InitLen (getreal (strcat "Would you kindly enter a length?("rtos InitLen 2 0)")))

;    Reversal [and an extraneous quotation mark] -- you don't want the parenthesis in the prompt to the User, and AutoLisp functions all start with a left parenthesis followed immediately by the function name.  Also, (getdist) is better than (getreal), because you have the option to give it by picking two points as well as typing it in in any valid format [including things like feet and inches and fractions when in Architectural units]:

  (setq InitLen (getdist (strcat "Would you kindly enter a length?" (rtos InitLen 2 0))))

;  But if InitLen does not yet exist, the (rtos) function will fail.  I think you want to offer Len as the default, but only if it already exists, otherwise offer 4, and defaults are typically shown in pointy brackets:

  (setq InitLen (getdist (strcat "Length <" (if Len (rtos Len 2 0) "4") ">: ")))

 

;  (if Len (setq initLen Len)(setq Len 4))

;  Checking for the wrong thing -- If the User supplied a length above [InitLen], use that, otherwise the prior value of Len if there is one, otherwise 4.  I think you really mean:
  (setq Len (cond (InitLen) (Len) (4)))

 

  (While (setq user_point (getpoint "Select Desired End Point: "))
;  (command "polygon, 4" user_point "L" Len "")

;  Review the actual prompts and sequence when you do the command manually.  Each entry must be its own [nothing like "polygon, 4"]; a number can be fed in as one, without quotes;  the option is "Edge" [not L], and if using it, calling for it comes before giving a point; 

  (command "polygon" 4 "_edge" user_point .....)

but then there's a problem....  you can't feed in Len for the length of the edge under the circumstances -- it's asking for the other end as a location.  You can aim the cursor and type in a length, but a routine can't feed in your set Length at that point [how does it know when you've got it aimed in the direction you want, to feed it in?]  You could add more steps by having it ask for an aim direction, with a (getangle) function, which it could then use to calculate where to put the other end of the edge.  Or you could make it always orthogonal:

  (command "polygon" 4 "_edge" user_point (polar user_point 0 Len))

in which case you could prompt for the desired Lower Left Corner.  But consider whether you really want/need to do it by specifying the edge, rather than starting with the center in typical Polygon fashion.

  ) ; need closing parenthesis for (while) function
); defun

 

For a square, it would be much easier to build the things around the RECTANG command than POLYGON.

 

Also, do you really want to use (rtos InitLen 2 0)?  That will display only whole numbers -- no squares of 2.5-unit edge length.  If you really only use whole-number values, I would use (getint) rather than (getreal)/(getdist), and (itoa) instead of (rtos).

Kent Cooper, AIA
Message 3 of 10

JCKRU47
Advocate
Advocate

I will try to rework the function as you noted and I am thankful for the feedback.

 

While I was waiting on a reply I may have found a different way for it to work as intended, but it's not loading and working properly.

 

(Defun C:ESQ (/ initlen user_point)
(if (setq InitLen (getreal (strcat "Would you kindly enter a length?")))
(progn (while (setq user_point (getpoint "Would you kindly set an end point: "))
(command "polygon" "4" user_point "C" (/ initlen 2))
)
)
(princ)
)

 

Is there an easy way to ensure that the rectangle command would output a perfect square set be length?

0 Likes
Message 4 of 10

ronjonp
Mentor
Mentor

Cross posted HERE.

Message 5 of 10

JCKRU47
Advocate
Advocate

Just clicked that you are the same one helping me in the other forum. Hopefully I can get this figured out with everyone's help.

0 Likes
Message 6 of 10

Kent1Cooper
Consultant
Consultant
Accepted solution

@JCKRU47 wrote:

....

(if (setq InitLen (getreal (strcat "Would you kindly enter a length?")))
(progn (while (setq user_point (getpoint "Would you kindly set an end point: "))
(command "polygon" "4" user_point "C" (/ initlen 2))

....

Is there an easy way to ensure that the rectangle command would output a perfect square set be length?


The point the user gives is the center, not an endpoint, so I would change the prompt.  The (strcat) isn't doing anything for you -- concatening one string with...itself.  And the (progn) wrapper isn't doing anything -- the (while) function is the single 'then' expression in response to the (if) test, so no wrapper is needed.

 

If you want to specify, for example, the lower left corner instead of the middle, RECTANG will do nicely:

 

(defun C:ESQ (/ InitLen user_point)

  (if (setq InitLen (getdist "Square edge length: "))

    (while (setq user_point (getpoint "Lower left corner: ")); then

      (command "_.rectang" "_non" user_point "non" (mapcar '+ user_point (list InitLen InitLen)))

    ); while

  ); if

  (princ)

); defun

 

Yours looks like it should work, even without my corrections.  How are you loading it?  is missing a right parenthesis, to close either the (progn) or (if) function.

Kent Cooper, AIA
Message 7 of 10

JCKRU47
Advocate
Advocate

I still have to play around with where the parentheses goes, but for now I have a question about the set that you made. I was wondering why it still has me set opposite corners instead of basing the square size on the input?

0 Likes
Message 8 of 10

JCKRU47
Advocate
Advocate

So I got it to work with the following:

 

(defun C:ESQ (/ InitLen user_point)

(if (setq initlen (getreal (strcat "Would you kindly enter a length: ")))

(while (setq user_point (getpoint ""))

(command "polygon" 4 "_edge" user_point (polar user_point 0 Len))

)

)

(princ)

)

 

but it still asks for the length twice. Which one of the commands might be the culprit?

0 Likes
Message 9 of 10

Kent1Cooper
Consultant
Consultant

@JCKRU47 wrote:

... I have a question about the set that you made. I was wondering why it still has me set opposite corners instead of basing the square size on the input?


If you mean the version I wrote using the RECTANG command, that doesn't do what you describe for me.  It asks for an edge length, and then for every place I pick, it draws a square of the specified edge length from that as the lower left corner:

Squares.gif

Kent Cooper, AIA
0 Likes
Message 10 of 10

Kent1Cooper
Consultant
Consultant

@JCKRU47 wrote:

...

(defun C:ESQ (/ InitLen user_point)

(if (setq initlen (getreal (strcat "Would you kindly enter a length: ")))

(while (setq user_point (getpoint ""))

(command "polygon" 4 "_edge" user_point (polar user_point 0 Len))

....

but it still asks for the length twice. Which one of the commands might be the culprit?


Make the variable name where it's used the same as where it's set.

Kent Cooper, AIA
0 Likes