Visual LISP, AutoLISP and General Customization

Reply
New Member
Posts: 2
Registered: ‎05-03-2013
Message 1 of 6 (1,795 Views)

Change room size lisp to metric?

1795 Views, 5 Replies
07-25-2013 11:12 AM

Hello,

 

I have the following LISP routine that I need to convert to metric, can anyone help me? please include some comments so i can try and fix some other LISPs I have please.

 

(defun dtr (a)
(/ (* a pi) 180)
)

(defun rtd (a)
(/ (*a 180) pi)
)

(defun c:room ()
(setvar "cmdecho" 0)
(command "undo" "g")
(write-line "\nTHIS ROUTINE GIVES YOU ROOM DIMENSIONS")
(SETQ ROOM1 (STRCASE (GETSTRING "\n ENTER ROOM NAME: " "t" )))
(SETQ OS (GETVAR "OSMODE"))
(SETQ LA (GETVAR "CLAYER"))
(SETQ TS (GETVAR "TEXTSTYLE"))
(SETVAR "OSMODE" 33)
(SETQ P1 (GETPOINT "\n PICK FIRST CORNER: "))
(SETQ P2 (GETCORNER P1 "\n PICK SECOND CORNER: "))
(SETQ DX (ABS (- (CAR P2) (CAR P1))))
(SETQ DY (ABS (- (CADR P2) (CADR P1))))
(SETQ P5 (LIST (/ (+ (CAR P2) (CAR P1)) 2) (/ (+ (CADR P2) (CADR P1)) 2)))
(SETQ P4 (POLAR P5 (DTR 90) 10))
(COMMAND "LAYER" "M" "Design Text" "C" "4" "" "")
(SETVAR "OSMODE" 0)
(SETQ DXFT (ATOI (RTOS (CVUNIT DX "IN" "FT") 2)))
(SETQ DYFT (ATOI (RTOS (CVUNIT DY "IN" "FT") 2))) 
(SETQ DXIN (- DX (* 12 DXFT))) 
(SETQ DYIN (- DY (* 12 DYFT)))
(SETQ STR (STRCAT (RTOS DXFT 2 0) "'" (RTOS DXIN 4 2) "x" (RTOS DYFT 2 0) "'" (RTOS DYIN 4 2)))
(COMMAND "TEXT" "S" "ROOM-NAME" "j" "m" P4 0 ROOM1)
(COMMAND "TEXT" "S" TS "j" "M" P5 0 STR)
(SETVAR "OSMODE" OS)
(SETVAR "CLAYER" LA)
(COMMAND "UNDO" "E")
(setvar "cmdecho" 1)
(PRINC)
)

 

Thanks, Paul

*Expert Elite*
dgorsman
Posts: 4,710
Registered: ‎10-12-2006
Message 2 of 6 (1,772 Views)

Re: Change room size lisp to metric?

07-25-2013 03:33 PM in reply to: phenderson

Two generic comments to start with.  First, as you've already noted, the code isn't commented.  That can make simple code difficult to follow for those not familiar with LISP, while long complicated routines can be troublesome to interpret for even long-time users, even when they wrote the code in the first place.

 

Second, is localization of variables.  Note the (defun c:room () ... ) line?  That defines the function.  The empty brackets are used to define arguments and variables for this specific function, separated by a slash character (/).  Command line functions (thats the "c:" prefix) don't take arguments so that can be ignored for now.  Variables store data, and when they aren't defined for the function they keep that value even when the function finishes.  So what, I hear you ask.  Well, here's what: lets say you've scooped up another LISP function off the internet that also uses variable names like P1, P2, and so on.  That function, or this one, may not be expecting those variables to already have values in them.  No point in creating problems for yourself.  Normally you would see that (defun ....) structured as:

 

(defun c:room ( / QA LS TS P1 P2 DX DY ...) ...)

  with all the variables used inside this function defined.  When the function is started, any other functions which already use those variable names put them aside in favor of these new ones until completed, when they are discarded and won't interfere with other functions later on.

 

One final general comment, on the naming of variables.  There is some back and forth on this, some prefer short names as they can be typed faster.  I prefer "verbose" names so its more obvious what they are for.  P1 and P2 don't mean much unless you scan up the code to see whats happening with them.  If they are named first_corner and second_corner its much more obvious, if more typing.  Either way, consistent formatting and abbreviation choices can make a world of difference in figuring out what the code is doing.

 

 

----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
Adopt. Adapt. Overcome. Or be overcome.
A good question will be halfway to a good answer.


*Expert Elite*
Kent1Cooper
Posts: 4,966
Registered: ‎09-13-2004
Message 3 of 6 (1,767 Views)

Re: Change room size lisp to metric?

07-25-2013 05:45 PM in reply to: phenderson

 

 

Welcome aboard!  I'm going to paste your code in below and comment with suggested changes, but first, even for Imperial measurements, this whole stretch:

 

(SETQ DXFT (ATOI (RTOS (CVUNIT DX "IN" "FT") 2)))
(SETQ DYFT (ATOI (RTOS (CVUNIT DY "IN" "FT") 2))) 
(SETQ DXIN (- DX (* 12 DXFT))) 
(SETQ DYIN (- DY (* 12 DYFT)))
(SETQ STR (STRCAT (RTOS DXFT 2 0) "'" (RTOS DXIN 4 2) "x" (RTOS DYFT 2 0) "'" (RTOS DYIN 4 2)))

 

can be replaced, if you're looking for feet, no hyphen, and inches to the nearest 1/4", by just this:

 

(setq str

  (strcat

    (vl-string-subst "" "-" (rtos DX 4 2))

    "x"

    (vl-string-subst "" "-" (rtos DY 4 2))

  ); end strcat

); end setq

 

The (vl-string-subst) functions remove the hyphens from what (rtos) returns, which will take care of the feet and inches and fractions for you, so you don't need to break it up and re-build it.  But you don't need that for metric units.

 

Assuming your drawing unit is millimeters, and you want room dimensions in millimeters, try this:

 

; (dtr) is used only once, and the same can be done more concisely and directly

;   [see below], so it's really not needed.

; (rtd) is never used.

(defun c:room (/ room1 os la ts p1 p2 dx dy p5 p4 str)
  (setvar "cmdecho" 0)
  (command "_.undo" "_begin")

  ; Underscores ensure it will work in non-English-language versions -- advisable

  ;   for this international forum but not essential if you have an English version;

  ; Period forces it to use the native AutoCAD command, avoiding potential problems

  ;   with redefined commands;

  ; Spelling out options avoids problems with changes in later versions [even by 2004,

  ;   G is no longer the abbreviation for beGin, and is not even offered, though it still

  ;   honors it -- it's now BEgin].
  (prompt "\nTHIS ROUTINE GIVES YOU ROOM DIMENSIONS")

  ; You can use (write-line) for this, but that's built to do more than you need, and

  ;   prompting is what you're really doing.

  (SETQ

  ; You can combine multiple variable settings into one (setq) function.

    ROOM1 (STRCASE (GETSTRING T "\n ENTER ROOM NAME: "))

    ; Yes, it works with a T in quotes and at the end, but the AutoLISP Reference

    ;   has it before the message, so it "looks" wrong to me after it.  Also, anything

    ;   non-nil will do, so "Q" or 17.23 would work as well; T without quotes [True]

    ;   is the "usual" way of doing it.
    OS (GETVAR 'OSMODE)

    ; System Variable names in (getvar)/(setvar) can have double-quotes on both

    ;   ends, or an apostrophe only at the beginning.
    LA (GETVAR 'CLAYER)
    TS (GETVAR 'TEXTSTYLE)

    ; The current Text Style could be anything, including something without a fixed

    ;   height, which would mess things up for you.  Spell it out explicitly below in the

    ;   Text command, and use this only to reset it at the end.
  ); end setq

  (SETVAR "OSMODE" 33)

  (SETQ

    P1 (GETPOINT "\n PICK FIRST CORNER: ")
    P2 (GETCORNER P1 "\n PICK SECOND CORNER: ")
    DX (ABS (- (CAR P2) (CAR P1)))
    DY (ABS (- (CADR P2) (CADR P1)))
    P5 (LIST (/ (+ (CAR P2) (CAR P1)) 2) (/ (+ (CADR P2) (CADR P1)) 2)))

    ; There's a shorter way: (mapcar '/ (mapcar '+ p1 p2) '(2 2 2))
    P4 (POLAR P5 (/ pi 2) 250))

    ; (/ pi 2) is 90 degrees in radians, eliminating need for (dtr) function

    ; Change 250 to whatever is appropriate [probably not original 10]
  ); end setq

  (COMMAND "LAYER" "M" "Design Text" "C" "4" "" "")
  (SETVAR "OSMODE" 0)
  (SETQ STR (STRCAT (RTOS DX 2 0) "x" (RTOS DY 2 0))); directly in millimeters

  ; If meters are desired, presumably decimal, and units are millimeters, adjust:
  (COMMAND

  ; You can include multiple commands in one (command) function.

    "_.TEXT" "_style" "ROOM-NAME" "_middle" P4 0 ROOM1

    ; Justify option is expendable -- you can go directly to the justification you want.
    "_.TEXT" "_style"SpecifyOne" "_middle" P5 0 STR

  ); end command
  (SETVAR 'OSMODE OS)
  (SETVAR 'CLAYER LA)

  (setvar 'textstyle TS); back to what it was
  (COMMAND "_.UNDO" "_End")
  (setvar 'cmdecho 1)
  (PRINC)
); end defun

Kent Cooper
*Expert Elite*
Kent1Cooper
Posts: 4,966
Registered: ‎09-13-2004
Message 4 of 6 (1,756 Views)

Re: Change room size lisp to metric?

07-25-2013 08:32 PM in reply to: Kent1Cooper

Kent1Cooper wrote:
....
    P5 (LIST (/ (+ (CAR P2) (CAR P1)) 2) (/ (+ (CADR P2) (CADR P1)) 2)))

    P4 (POLAR P5 (/ pi 2) 250))

...

  (COMMAND "LAYER" "M" "Design Text" "C" "4" "" "")

....


Whoops -- I neglected to remove the final right parentheses from the first two lines above [leftovers from when they were there to finish separate (setq) functions before I combined them], so get rid of them.  I don't think I missed others -- I looked, and didn't detect any.

 

And for consistency, I should have suggested the same kinds of changes to that (command) function line, thus:

 

  (COMMAND "_.LAYER" "_Make" "Design Text" "_Color" "4" "" "")

Kent Cooper
New Member
Posts: 2
Registered: ‎05-03-2013
Message 5 of 6 (1,737 Views)

Re: Change room size lisp to metric?

07-26-2013 11:01 AM in reply to: Kent1Cooper

Thanks for the help Kent,

 

I've been fiddling around with the code and I can get my output with millimeters but I can't seem to get it into meters. I've tried creating variable that take DX and divide it by 100:

   DXM (DX(/ 100)) ;I declared DXM

 

but that doesn't work. And I've tried dividing by 100 right in the string command:

   (SETQ STR (STRCAT (RTOS (DX(/ 100)) 2 2) "x" (RTOS (DY(/ 100)) 2 2))); 

 

Can you help me out?

*Expert Elite*
Kent1Cooper
Posts: 4,966
Registered: ‎09-13-2004
Message 6 of 6 (1,731 Views)

Re: Change room size lisp to metric?

07-26-2013 11:58 AM in reply to: phenderson

phenderson wrote:

... I can get my output with millimeters but I can't seem to get it into meters. I've tried creating variable that take DX and divide it by 100:

   DXM (DX(/ 100)) ;I declared DXM

 

but that doesn't work. And I've tried dividing by 100 right in the string command:

   (SETQ STR (STRCAT (RTOS (DX(/ 100)) 2 2) "x" (RTOS (DY(/ 100)) 2 2))); 

....


Read up on the syntax for the (/) function in the AutoLISP Reference.  More broadly speaking, LISP functions always start with a left parenthesis followed by the function name and then appropriate arguments, all inside the parentheses for that function.  [And I think you want 1000 rather than 100.]  Try this:

 

   (SETQ STR (STRCAT (RTOS (/ DX 1000) 2 3) "x" (RTOS (/ DY 1000) 2 3)))

 

[I changed the precision to 3 decimal places to read down to the millimeter level, but use whatever suits your drafting standards.]

Kent Cooper

You are not logged in.

Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register

Announcements
Welcome to the new Autodesk Community!
If this is your first visit, click here to get started and make the most of the Community. Let us know what you think of the new experience in the Community Feedback Forum.

Need installation help?

Start with some of our most frequented solutions to get help installing your software.

Ask the Community