Jump to content

LISP routine format and commands


traumathecat

Recommended Posts

Hi all,

 

I've never written a LISP routine before and I am finding myself in need of a function that I can't seem to be able to do without LISP, so I have begun my first attempt. It's not going so well.

 

I need to be able to pick two points and have a square drawn that uses those two points as opposite corners.

 

I think if I can check the angle between the two points, then add or subtract 45-degrees from that, I will get the rotation for the square, and I can then use the RECTANGLE command to draw it by picking the first point, setting the rotation, and then pick the second point.

 

I think the code should look something like this:

(defun C:square (/p1 rot p2)

(set q p1 (getpoint "\n Pick first corner:"))

(set q p2 (getpoint "\n Pick opposite corner:"))

(set q rotang (-45 (
ANGLE
p1 p2)))

(command "RECTANGLE" p1 "R" " rotang "" p2)

(princ)

)

The first problem I run into is that I don't know how to check the angle between the two points. I know I can get it by using the DIST command and the value comes up as "Angle in XY-plane" but I don't know how to then use that value as my ANGLE value.

 

Second, I have no idea if I am even on the right track as far as writing the code.

Any help would be greatly appreciated.

I'm working in Civil 3D 2011.

Link to comment
Share on other sites

Perhaps this will point you towards your goal :

 

(defun c:square ( / pt2 pt2 ang ) ; Define function and localise variables

 (if ; If the following
   (and ; Both the statements must return T
     (setq pt1 (getpoint "\nSpecify First Point: ")) ; Prompt for first point
     (setq pt2 (getpoint "\nSpecify Opposite Corner: " pt1)) ; Prompt for second point
   )
   (progn
     (setq ang (- (angle pt1 pt2) (/ pi 4.))) ; get angle (in rads) and subtract 45 degrees
     
     (command "_.rectangle" "_non" pt1 "_R" (* 180. (/ ang pi)) "_non" pt2) ; Invoke Rectangle command
   )
 )

 (princ) ; Exit Quietly
)

PS> Nice one for localising your variables, most people miss that :)

 

To expand, you will have to watch out for OSnap, and also perhaps consider switching CMDECHO to 0, then reset. But we'll take it one step at a time.

Edited by Lee Mac
Updated to avoid OSnap
Link to comment
Share on other sites

As a bit of food for thought, this is how I would approach it:

 

(defun c:square ( / *error* pt2 pt2 ang side )

 (defun *error* ( msg )
   (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
       (princ (strcat "\n** Error: " msg " **")))
   (princ)
 )

 (if
   (and
     (setq pt1 (getpoint "\nSpecify First Point: ")) 
     (setq pt2 (getpoint "\nSpecify Opposite Corner: " pt1))
   )
   (progn
     (setq pt1  (trans pt1 1 0) pt2 (trans pt2 1 0)
           ang  (- (angle pt1 pt2) (/ pi 4.))
           side (sqrt (/ (expt (distance pt1 pt2) 2) 2.)))

     (LM:LWPoly (list pt1 (polar pt1 ang side)
                      pt2 (polar pt1 (+ ang (/ pi 2.)) side))
       1
     )
   )
 )

 (princ)
)

(defun LM:LWPoly ( lst cls )
 (entmakex
   (append
     (list
       (cons 0 "LWPOLYLINE")
       (cons 100 "AcDbEntity")
       (cons 100 "AcDbPolyline")
       (cons 90 (length lst))
       (cons 70 cls)
     )
     (mapcar '(lambda ( p ) (cons 10 p)) lst)
   )
 )
)

Perhaps it might be a bit above you at the moment, but maybe its something to work towards :)

Link to comment
Share on other sites

Perhaps this will point you towards your goal :

 

(defun c:square ( / pt2 pt2 ang ) ; Define function and localise variables

(if ; If the following
(and ; Both the statements must return T
(setq pt1 (getpoint "\nSpecify First Point: ")) ; Prompt for first point
(setq pt2 (getpoint "\nSpecify Opposite Corner: " pt1)) ; Prompt for second point
)
(progn
(setq ang (- (angle pt1 pt2) (/ pi 4.))) ; get angle (in rads) and subtract 45 degrees

(command "_.rectangle" pt1 "_R" (* 180. (/ ang pi)) pt2) ; Invoke Rectangle command
)
)

(princ) ; Exit Quietly
)

PS> Nice one for localising your variables, most people miss that :)

 

To expand, you will have to watch out for OSnap, and also perhaps consider switching CMDECHO to 0, then reset. But we'll take it one step at a time.

 

THANK YOU, THANK YOU, THANK YOU! :D I love it! So far it is working perfectly. You have saved me hours and hours of manually calculating and placing squares (I have around 4,000 of them).

 

PS> Thank you... I tried to find whatever information and tutorials I could online to at least attempt to write something on my own, so I was able to figure out a little bit of the format, but I still have a lot to learn!

Link to comment
Share on other sites

As a bit of food for thought, this is how I would approach it:

 

(defun c:square ( / *error* pt2 pt2 ang side )

(defun *error* ( msg )
(or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
(princ (strcat "\n** Error: " msg " **")))
(princ)
)

(if
(and
(setq pt1 (getpoint "\nSpecify First Point: ")) 
(setq pt2 (getpoint "\nSpecify Opposite Corner: " pt1))
)
(progn
(setq pt1 (trans pt1 1 0) pt2 (trans pt2 1 0)
ang (- (angle pt1 pt2) (/ pi 4.))
side (sqrt (/ (expt (distance pt1 pt2) 2) 2.)))

(LM:LWPoly (list pt1 (polar pt1 ang side)
pt2 (polar pt1 (+ ang (/ pi 2.)) side))
1
)
)
)

(princ)
)

(defun LM:LWPoly ( lst cls )
(entmakex
(append
(list
(cons 0 "LWPOLYLINE")
(cons 100 "AcDbEntity")
(cons 100 "AcDbPolyline")
(cons 90 (length lst))
(cons 70 cls)
)
(mapcar '(lambda ( p ) (cons 10 p)) lst)
)
)
)

Perhaps it might be a bit above you at the moment, but maybe its something to work towards :)

 

haha... definitely above me, but I like a challenge. And, I hate not knowing how to do things. :) So, I definitely will take a look and try to understand how you've done this.

Link to comment
Share on other sites

My pleasure - happy to help.

 

With regards to the first code, it is a 'preliminary' of sorts, as you will have trouble as far as OSnap interference goes - perhaps use "_non" before supplying the points to the command function to ignore OSnap. (I'll update the code).

 

The second is faster and you needn't worry about OSnap as it adds the object directly to the drawing database, bypassing all command calls.

 

As for help with LISP, I posted this thread a while back, hopefully you can glean something from it:

 

http://www.cadtutor.net/forum/showthread.php?49515-Useful-LISP-Links

 

Lee

Link to comment
Share on other sites

My pleasure - happy to help.

 

With regards to the first code, it is a 'preliminary' of sorts, as you will have trouble as far as OSnap interference goes - perhaps use "_non" before supplying the points to the command function to ignore OSnap. (I'll update the code).

 

The second is faster and you needn't worry about OSnap as it adds the object directly to the drawing database, bypassing all command calls.

 

As for help with LISP, I posted this thread a while back, hopefully you can glean something from it:

 

http://www.cadtutor.net/forum/showthread.php?49515-Useful-LISP-Links

 

Lee

 

I've been using the second code and it has been working great (I've done 50 sets of points). But, I just got to this set of points and I got the funky square in red. I ran the first one on the same points and got the blue square. I'm not sure what threw it off here. The rest are giving me the same square using either method.

 

squares.JPG

 

Thanks for the link, I look forward to checking it out and learning more. :)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...