Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Need advice on choosing the right tool / mix of tools for scripting

11 REPLIES 11
SOLVED
Reply
Message 1 of 12
msingh_autocad
500 Views, 11 Replies

Need advice on choosing the right tool / mix of tools for scripting

I am looking to automate the drawing of a certain drawing (multiple layers, 2 dimensional). My platform is AutoCAD 2011 for Mac.

 

I expect that I will be going through various iterations of this drawing and want to automate this as much as possible.

 

What I want to do is to draw rectangles (nothing complicated) that are expressible in the following pseudocode:

 

list_of_widths1=[200,300,400];

list_of_lengths1=[1000,1200,2000,2200];

 

some_other_variables

 

.

.

.

 

for i1=1:length(list_of_widths1)

  for j1=1:length(list_of_lengths1)

  x1=result of calculation 1 (function of i1 and some_other_variables);

  y1=result of calculation 2 (function of j1 and some_other_variables);

  draw rectangle with width = i1 and length = j1 at (x1,y1)

     end

end

 

I have been reading up on script files (invoked using script command) and AutoLISP files (invoked using appload command).

 

It appears that the drawing script does not have any complicated constructs such as loops or arithmetic operations. And the AutoLISP (from what I have quickly read about it) does not have any drawing commands.

 

Is it even possible to do what I seek to do above ?

 

Looks like I need to mix the two. Can I embed drawing commands in AutoLISP ?

 

I am somewhat new (used it very briefly 16 years ago, but then never touched it until now) to AutoCAD (though not to using layout programs or scheme).

------------------------------------------------------------------------


AutoCAD 2011 on Mac OSX 10.6.7.
11 REPLIES 11
Message 2 of 12


@msingh_autocad wrote:

....

What I want to do is to draw rectangles ....

.... 

I have been reading up on script files (invoked using script command) and AutoLISP files (invoked using appload command).

 

It appears that the drawing script does not have any complicated constructs such as loops or arithmetic operations. And the AutoLISP (from what I have quickly read about it) does not have any drawing commands.

 

Is it even possible to do what I seek to do above ?

 

Looks like I need to mix the two. Can I embed drawing commands in AutoLISP ?

....


It's not as simple as that.  With certain limitations, you can include Lisp expressions such as arithmetic operations in a Script, or a menu macro item.  And AutoLISP files are actually made available using appload, but whether doing that invokes anything depends on how the code in the file is written.  More often, you need to then enter a command name that's defined in the file, to have it do its thing.

 

Yes, you can certainly embed drawing commands in AutoLISP.  Poke around this forum a little and you'll find countless examples.  Look at the AutoLISP functions (command) and (vl-cmdf).  If the command in question is a drawing command, you can also make entities with (entmake).  If it's an editing command, you can often achieve the same by applying (subst) to an entity's data list.  Etc., etc., ....

 

You would do well to just look over the relevant parts of Help's Customization Guide and the AutoLISP Tuturial first.  Also search the Discussion Group for something related to what you want to do.  It's certainly doable, with things like those lists in the right format, etc.  If there's something you can't figure out, write back.

Kent Cooper, AIA
Message 3 of 12
SafetyFish
in reply to: msingh_autocad

Actually, there are a number of drawing tools in autolisp. I have just recently (the past 3-4 weeks) discovered them myself.

 

The most complicated, but by far the most useful, drawing tool in autolisp is entmake. You could also use command. For entmake, you must become very familiar with the dxf codes. Good instructions on using entmake to draw things using entmake can be found here. I can't help you with the the (command) option because I haven't really explored it, but I know it exists.

 

http://www.dailyautocad.com/2009/10/autolisp10-using-entmake-function-to.html

 

These examples are extremely simplified. The best resource I have found for DXF codes is this:

 

http://images.autodesk.com/adsk/files/acad_dxf2.pdf

 

Another great resource is this:

 

http://docs.autodesk.com/ACD/2011/ENU/filesALR/WS1a9193826455f5ff1a32d8d10ebc6b7ccc-6ade.htm

 

I reccomend this website for learning autolisp:

 

http://www.afralisp.net/autolisp/

 

I would also suggest you write the entmake functions separately from your major drawing code. I, too, find myself drawing some rectangles in precise places repeatedly. I have copied below the function I made for myself to draw a rectangle. It's rather messy, but you should be able to at least get the idea. It was one of the first pieces of lisp I wrote.

 

If you're very new to scripting/programming and you do not have a preferred development environment yet, I have been using notepad++ with great success to create my .lsp files. I hope all this helps you!

 

(defun DrawLWPlineFromLines (PointList Thickness / NPts DFXlist index)
; This function takes a list variable with a set of points in it


;pointlist: ((# # #) (# # #) (# # #) (# # #) etc)

;and uses this list to create a polygon shape of linetype lwpolyline
;thickness is a number

(setq Npts (length pointlist)); assign number of points to variable
(setq index 0); set index to default variable of 0
(setq DFXlist (list
    (cons 0 "LWPolyline"); Entity Type
    (cons 8 (getvar "clayer")); Grab current layer
    (cons 62 7) ; lines colored white/black
    (cons 100 "AcDbEntity"); subclass old acad
    (cons 100 "AcDbPolyline"); subclass new acad
    (cons 90 Npts); Number of vertices in pline, or number of points from point list
    (cons 70 1); PL flag; 0=open, 1=closed
    (cons 43 Thickness); Line Thickness
))

(repeat npts
    (setq DFXlist (append DFXlist (list ; make dfxlist equal to dfxlist + whatever else I add in this loop
        (cons 10 (nth index pointlist))
        ; add points to dfx list based on index (loop iteration and list place)
    )))
    (setq index (+ index 1)); counter
)
(terpri)
;(prin1 dfxlist)
(terpri)

(entmake DFXlist); create polyline
)
(defun SolidHatchLWPLpolygon (EntityName Color / DFXlist NumVer Pair EntDFX VertexList index)
;this function takes the hex name of an entity and an acad color number and hatches said entity said solid color
;before building dfx codes list, take entity name and grab number of vertices
(setq numver (cdr (assoc 90 (entget entityname))))
; assign vertices in object to list, somehow.
;must first create entdfx by assigning entget(entityname)
(setq entdfx (entget entityname))
(foreach pair entdfx
    (if (= (car pair) 10)
        (setq vertexlist (append vertexlist (list
            (cons (car pair) (list (nth 1 pair) (nth 2 pair) 0.0))
        )))
    )    
)    
;begin dfx codes list
(setq DFXlist    (list
    (cons 0 "HATCH")
    (cons 100 "AcDbEntity")
    (cons 67 0)
    (cons 410 "MODEL")
    (cons 8 (getvar "CLAYER"))
    (cons 62 Color)
    (cons 100 "AcDbHatch")
    (cons 10 (list (nth 1 (nth 0 vertexlist)) (nth 2 (nth 0 vertexlist)) 0.0))
    (cons 210 (list 0.0 0.0 1.0))
    (cons 2 "SOLID")
    (cons 70 1)
    (cons 71 0)
    (cons 91 1)
    (cons 92 7)
    (cons 72 1)
    (cons 73 1)
    (cons 93 numver)
))

(setq index 0) ; set index to default 0


;now put vertices in dfxlist
(repeat numver
    (setq dfxlist (append dfxlist (list
        ;(cons 72 1);;; all this stuff commented out to try and make the @!#$%!@#@&##!! hatch work
        
        (cons 10 (cdr(nth index vertexlist)))
        (cons 42 0.0)
    )))
    (setq index (+ index 1))
    ;(setq dfxlist (append dfxlist (list
    ;    (if (= index numver)
    ;        (cons 11 (cdr(nth 0 vertexlist)))
    ;        (cons 11 (cdr(nth index vertexlist)))
    ;    )
    ;)))
)
(setq dfxlist (append dfxlist (list
    (cons 97 0)
    ;(cons 330 entityname)
    (cons 75 0)
    (cons 76 1)
    (cons 47  0.2)
    (cons 98 0)
    (cons 450  0)
    (cons 451  0)
    (cons 460  0.0)
    (cons 461  0.0)
    (cons 452  1)
    (cons 462  1.0)
    (cons 453  2)
    (cons 463  0.0)
    (cons 63  5)
    (cons 421  255)
    (cons 463  1.0)
    (cons 63  7)
    (cons 421  16777215)
    (cons 470 "LINEAR")

)))
(entmake dfxlist)
)

 

 

Message 4 of 12
msingh_autocad
in reply to: SafetyFish

Thanks for the responses.

 

Safetyfish, that was an incredibly informative and helpful response. Thanks.

 

My question - how much of a clear demarcation is there between AutoLISP and VLISP ? I am running this on a Mac, so I do not want to run into issues with internal calls to .com, .net objects and the like.

------------------------------------------------------------------------


AutoCAD 2011 on Mac OSX 10.6.7.
Message 5 of 12
Kent1Cooper
in reply to: SafetyFish


@SafetyFish wrote:

.... 

The most complicated, but by far the most useful, drawing tool in autolisp is entmake. You could also use command. ...

.... 

(defun DrawLWPlineFromLines (PointList Thickness / NPts DFXlist index)
; This function takes a list variable with a set of points in it


;pointlist: ((# # #) (# # #) (# # #) (# # #) etc)

;and uses this list to create a polygon shape of linetype lwpolyline
;thickness is a number

(setq Npts (length pointlist)); assign number of points to variable
(setq index 0); set index to default variable of 0
(setq DFXlist (list
    (cons 0 "LWPolyline"); Entity Type
    (cons 8 (getvar "clayer")); Grab current layer
    (cons 62 7) ; lines colored white/black
    (cons 100 "AcDbEntity"); subclass old acad
    (cons 100 "AcDbPolyline"); subclass new acad
    (cons 90 Npts); Number of vertices in pline, or number of points from point list
    (cons 70 1); PL flag; 0=open, 1=closed
    (cons 43 Thickness); Line Thickness
))

(repeat npts
    (setq DFXlist (append DFXlist (list ; make dfxlist equal to dfxlist + whatever else I add in this loop
        (cons 10 (nth index pointlist))
        ; add points to dfx list based on index (loop iteration and list place)
    )))
    (setq index (+ index 1)); counter
)
(terpri)
;(prin1 dfxlist)
(terpri)

(entmake DFXlist); create polyline
)
....


[By the way, "Thickness" in the code above should be "Width" instead -- "thickness" has a specific and different meaning in AutoCAD entities: vertical thickness/height up off the drawing plane.  See Thickness in the General category in the Properties Box for a selected Polyline, vs. Segment widths and Global width in the Geometry category.]

 

I agree that (entmake) is more complicated, and sometimes a lot.  It's necessary in certain situations [you can't use (command) in a reactor, for instance], and it's advisable in others [if you have a large enough number of things to make all at one shot, you might start to notice the shorter amount of time it can take].

 

But to illustrate how much more complicated it can be, this code using the (command) function instead will do exactly the same thing that the above-quoted code does: make a closed polyline on the current Layer, with [for whatever reason] a forced color of white/black, from a specified list of points, and at a specified global width.

 

(defun LWPpts (lst wid); = LightWeightPolyline from points
  (command "_.pline" (car lst) "_w" wid "")
  (foreach pt (cdr lst) (command pt))
  (command "_c" "_.chprop" "_l" "" "_c" 7 "")
)

Usage would be the same -- type in or enter from other code:

(lwppts ptlist wid)

where 'ptlist' is a list of points [or a variable containing one], and 'wid' is a numerical value [or a variable containing one].

 

I suppose to make it truly and completely equivalent, maybe a line like this:
(setvar 'plinetype 2)

[1 rather than 2 would also do] could be added at the beginning to ensure that it makes a Lightweight Polyline, if you think there's any chance that System Variable might be set to 0 and cause a "heavy" one.

 

No need to know DXF codes, or tell it how many vertices there are, or tell it to use the current Layer, or give it three entries just to define what kind of entity it is, or use any variables....  The PLINE command itself does for you a lot of what (entmake) needs you to spell out.  That's what makes it so much less complicated -- I think of a command as essentially a kind of code-shortcutting sub-routine.

 

[Oh, and if you're drawing rectangles as in your original question, and they're orthogonally oriented, you can make it perhaps even simpler by using the Rectang command -- you only need to give it two opposite corners, not all four, and the Polyline entity type result is inherent in the command.]

Kent Cooper, AIA
Message 6 of 12

Kent,

 

That was a very startling demonstration of complicated nature of entmake.

 

Online references are rife with claims that using command is much slower that AutoLISP. Would this slow down the session irrevocably, or does the session speed up again as soon as command is executed ?

 

What are implications for cross platform use ? I am using this on a Mac.

 

 

------------------------------------------------------------------------


AutoCAD 2011 on Mac OSX 10.6.7.
Message 7 of 12

I will be using the rectangle command. How does one hatch it with the current layer's colors ?

------------------------------------------------------------------------


AutoCAD 2011 on Mac OSX 10.6.7.
Message 8 of 12
dgorsman
in reply to: msingh_autocad

"Slower" is relative.  In most cases people have to code loops in the hundred- or even thousand-cycle range or compare expired time in milliseconds to demonstrate.  Note the delays are only while the function is executing.

 

Since you are on Mac, your options for LISP are quite limited at this time.  No VLISP means (entmake...), (entget...), and other DXF-based function calls are all you have to go with.  For somebody thats just beginning, I would recommend the simplicity of the (command...) route.

----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
"I don't know" is the beginning of knowledge, not the end.


Message 9 of 12


@msingh_autocad wrote:

I will be using the rectangle command. How does one hatch it with the current layer's colors ?


See whether Message 3 on this thread:

http://forums.autodesk.com/t5/Visual-LISP-AutoLISP-and-General/Wanted-Bhatch-options-prompts-etc-exp...

answers that for you.

Kent Cooper, AIA
Message 10 of 12

Thanks for the hint. I figured this one out on my own.

 

Simple way to hatch something you added last:

 

  (command "-HATCH" "Properties" "Solid" "Select" "Last" "" "" "")

 

Here is a neat function that does rectangle drawing and hatching in one step:

 

 

(defun hatchedrectdraw1 ( pt1 pt2); Draw a hatched rectangle between pt1 and pt1 (opposite corners)
 (command "rectang" pt1 pt2)
 (command "-HATCH" "Properties" "Solid" "Select" "Last" "" "" "")
  )

 

------------------------------------------------------------------------


AutoCAD 2011 on Mac OSX 10.6.7.
Message 11 of 12


@msingh_autocad wrote:

....

Here is a neat function that does rectangle drawing and hatching in one step:

 

(defun hatchedrectdraw1 ( pt1 pt2); Draw a hatched rectangle between pt1 and pt1 (opposite corners)
 (command "rectang" pt1 pt2)
 (command "-HATCH" "Properties" "Solid" "Select" "Last" "" "" "")
  )

It looks like Hatch prompts have changed since my 2004 -- I don't have a Properties option in the initial prompt in "plain" Hatch, only in Bhatch, but I assume they've been merged under the Hatch command name [similar to the way the Dtext command used to be different from the Text command long ago, but now Text works the way Dtext used to].  In this case, that merger requires more code from you -- I can do the same thing this way:

....

  (command "HATCH" "Solid" "Last" "")

....

 

In any case, you shouldn't need the hyphen to suppress the dialog box, when inside a Lisp (command) function.

 

Here's another little code-reducing trick -- you can string together more than one command within the same (command) function:

 

(defun hatchedrectdraw1 (pt1 pt2); Draw a hatched rectangle between pt1 and pt2 (opposite corners)
  (command "rectang" pt1 pt2 "Hatch" "Properties" "Solid" "Select" "Last" "" "" "")
)
 
Think of (command) not as a function that lets you use an AutoCAD command, but rather a function that gets you into the Command: prompt line, where you can stay as long as you keep giving it valid input.
 
[With a large number of operations strung together like that, it should speed things up, however slightly, by not repeatedly closing (command) functions and getting back into new ones.  But you'd never notice that difference in a case like this.]
Kent Cooper, AIA
Message 12 of 12

I see a definite speedup, but the function that worked for me was:

 

 

(defun hatchedrectdraw1 ( pt1 pt2); Draw a hatched rectangle between pt1 and pt2 (opposite corners)
 (command "rectang" pt1 pt2 "Hatch" "Solid" "Last" "SI")
 )

 

------------------------------------------------------------------------


AutoCAD 2011 on Mac OSX 10.6.7.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost