LISP getreal question

LISP getreal question

Anonymous
Not applicable
3,057 Views
7 Replies
Message 1 of 8

LISP getreal question

Anonymous
Not applicable

I asked a question a while ago to get help writting  a LISP routine that would atuomaticaly calculate the thickness of tapered insulation on a flat roof given the slope and starting thickness of the insulation.  I got back an excelent LISP routine that works like a charm.  However I'd like to improve/expand on it but I'm having some trouble with it.  Every time I have to run the routine I have to input the slope of the roof and the starting thickness.  So I pulled out the variables from the Local area and set them to be a globale variables.  So now I would like to show what the value of these variables are when prompted for the value.  This way if they need to change I can change them or if they stay the same I can just enter through them.  Kind of like when you are offsetting a line.

 

I would like it to look like this:

 

Enter the slope of the roof <.25>:

Enter starting thickness of just tapered insulation <.5>:

 

It seams to me that this should be a simple task of stating something like "\nEnter the slope of the roof <" *slope* ">: " but this returns an error.

 

Here is what I have for code:

(setq *slope* ".25")
(setq *minins* ".5")
(defun c:ti(/ p1 p2 di)
  (initerr)
  (setvar "cmdecho" 0)
  (command "undo" "m")
  (setq *slope* (getreal "\nEnter the slope of the roof: "))
  (setq *minins* (getreal "\nEnter starting thickness of just tapered insulation: "))
  (setq di (getdist "\nPick two points: "))
  (setq di (/ di 12))
  (setq di (* di *slope*))
  (setq di (+ di *minins*))
  ;(prin1 di)
  (command "_offset" di)
  (while (> (getvar 'cmdactive) 0) (command pause))
  (reset)
  (princ)
 )

I guess I thought it should just be:

  (setq *slope* (getreal "\nEnter the slope of the roof < " *slope* ">: "))
  (setq *minins* (getreal "\nEnter starting thickness of just tapered insulation < " *minins* ">: "))

but this just causes the error.  Any help or guidence you can give would be greatly appreciated.  I think my problem is I don't understand how the getreal works!

0 Likes
Accepted solutions (1)
3,058 Views
7 Replies
Replies (7)
Message 2 of 8

Kent1Cooper
Consultant
Consultant
Accepted solution

The (getreal) function can take an argument for a prompt, but only one.  You need to put the pieces together into one prompt argument:

 

  (setq *slope* (getreal (strcat "\nEnter the slope of the roof < " *slope* ">: "))); but see below....
  (setq *minins* (getreal (strcat "\nEnter starting thickness of just tapered insulation < " *minins* ">: ")))

 

However, it will take some more work to do what you want.  If the User hits Enter at that prompt, the variable will be set to nil.  One way to overcome that:

 

  (setq *slope*

    (cond

      ((getreal (strcat "\nEnter the slope of the roof < " *slope* ">: "))); if User types something, use it

      (*slope*); if they hit Enter, keep the current value

    ); cond

  ); setq

 

You can do it with (if) instead of (cond), but that would require an additional temporary variable:

 

  (if

    (setq slopetemp (getreal (strcat "\nEnter the slope of the roof < " *slope* ">: ")))

    (setq *slope* slopetemp)

  ); if

 

You also need to work with either real numbers or text strings, but what you have is mixing them.  If you want to use *slope* in a (*) calculation, it needs to be a real number, not a string.  You could go either way, but given the (getreal) function [which you would otherwise need to change], I would use the number, and convert that to a string where you need to:

 

(setq *slope* .25)

[value not in double-quotes].  Then in my first suggestion above:

 

  (setq *slope*

    (cond

      ((getreal (strcat "\nEnter the slope of the roof < " (rtos *slope* 2 2) ">: "))); if User types something, use it

      (*slope*); if they hit Enter, keep the current value

    ); cond

  ); setq

 

You can change the (rtos) mode and precision arguments as you prefer, or omit them and it will use whatever the current linear-Units settings are.

Kent Cooper, AIA
Message 3 of 8

Anonymous
Not applicable

Okay so ran the routine and if I don't input any information into the first two lines I get an error of bad argument type: numberp: ".25".  My guess is that I shouldn't call out the (setq *slope* ".25") or (setq *minins* ".5").  If I set it so the numbers are 0.25 and 0.5 (without quotes) I get bad argument type: stringp 0.25. If I input the numbers into the first two lines the routine will run like it's supposed to.  But when I run it the second time I will get bad argument type: stringp 0.25.

 

So if my understanding is correct setting a number between quotes makes the program read it as a string?

So how do I set the variable of *slope* to a number?  I thought it was just (setq *slope* 0.25)

0 Likes
Message 4 of 8

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

Okay so ran the routine and if I don't input any information into the first two lines I get an error of bad argument type: numberp: ".25".  My guess is that I shouldn't call out the (setq *slope* ".25") or (setq *minins* ".5").  If I set it so the numbers are 0.25 and 0.5 (without quotes) I get bad argument type: stringp 0.25. If I input the numbers into the first two lines the routine will run like it's supposed to.  But when I run it the second time I will get bad argument type: stringp 0.25.

 

So if my understanding is correct setting a number between quotes makes the program read it as a string?

So how do I set the variable of *slope* to a number?  I thought it was just (setq *slope* 0.25)


Yes, with the quotes it's a text string, without it's a real number, and your last line above is correct.  My suggestions prior to the "You also need..." paragraph were all based on its being a string as your original code sets it.  Whether you store it as a string or a number [your choice], you need to go through and check all instances of the use of it for the appropriate form.

 

If the variable is a string, in places where it needs to be used as a number [for a calculation such as your (setq di (* di *slope*))], you will need to convert it using (atof):

  (setq di (* di (atof *slope*)))

 

If it's a number, leave it alone in those places, but in places where it needs to be used as a string [prompts], you will need to convert it using (rtos) as suggested earlier.

 

The bad-argument messages are all the result of the variable in one form being fed in where it needs to be [but hasn't been] converted to the other form.

Kent Cooper, AIA
0 Likes
Message 5 of 8

Anonymous
Not applicable
I've now learned my lesson!!! Be sure to read all the way to the bottom of a comment don't just assume the second have is "Option 2"! Thanks for the explanation and helping me out with this code!
0 Likes
Message 6 of 8

robert06
Collaborator
Collaborator

Hi,

 

(setq *slope*

    (cond

      ((getreal (strcat "\nEnter the slope of the roof < " *slope* ">: "))); if User types something, use it

      (*slope*); if they hit Enter, keep the current value

    ); cond

  ); setq

 

It seems that the argument has to be present prior running the lisp for the first time.

Acaddoc.lsp has to contain the desired default value

(setq *slope* 1) etc.

 

How to avoid that?

 

Thank you

 

Robert

0 Likes
Message 7 of 8

Kent1Cooper
Consultant
Consultant

@robert06 wrote:

.... 

It seems that the argument has to be present prior running the lisp for the first time.

Acaddoc.lsp has to contain the desired default value

(setq *slope* 1) etc.

 

How to avoid that?

....


It doesn't have to be in acaddoc.lsp.  The code in Post 1 included a setting of it right at the beginning, but it's better to set that only if there is no previous value, because what they had will overwrite any previous value.  A couple of ways to do that [using a real number, not their original text string version, as the variable content]:

 

(if (not *slope*) (setq *slope* 0.25))

 

or:

 

(or *slope* (setq *slope* 0.25))

 

If you have an initial value that you want offered as a default on the first use, without pre-setting it in that way, you can do something like this:

(setq *slope*

  (cond

    ( (getreal ; returns nil if User hits Enter to accept offered default

        (strcat

          "\nEnter the slope of the roof < "

          (if *slope* (rtos *slope* 2 2) "1.00"); offer current value as default if it exists, 1.00 if not

          ">: "

        ); strcat

      ); getreal

    ); User-input condition [if User types a number, use it]

    (*slope*); if they hit Enter and there is a previous value, keep it [returns nil if no previous value]

    (1.00); if they hit Enter with no previous value, use your initial default

  ); cond

); setq

 

You can monkey with the preferred initial default, number of decimal places, etc., as desired.

Kent Cooper, AIA
Message 8 of 8

robert06
Collaborator
Collaborator

Oops, I misssed the lines in the Michael's post.

Thank you for tutoring!

0 Likes