How to interface with AutoCAD from Python?

How to interface with AutoCAD from Python?

Anonymous
Not applicable
19,751 Views
30 Replies
Message 1 of 31

How to interface with AutoCAD from Python?

Anonymous
Not applicable

I've the following AutoLISP code

(defun graph ( pts sls tls )
(   (lambda ( l )
        (foreach x l (text (cdr x) (itoa (car x)) 0.0 1))
        (mapcar
           '(lambda ( a b / p q r )
                (setq p (cdr (assoc a l))
                      q (cdr (assoc b l))
                      r (angle p q)
                )
                (entmake (list '(0 . "LINE") (cons 10 p) (cons 11 q) '(62 . 8)))
                (text
                    (mapcar '(lambda ( x y ) (/ (+ x y) 2.0)) p q)
                    (rtos (distance p q) 2)
                    (if (and (< (* pi 0.5) r) (<= r (* pi 1.5))) (+ r pi) r)
                    2
                )
            )            sls tls
        )
    )
    (mapcar 'cons (vl-sort (append sls tls) '<) pts)
)
)
(defun text ( p s a c )
    (entmake
        (list
           '(0 . "TEXT")
            (cons 10 p)
            (cons 11 p)
            (cons 50 a)
            (cons 01 s)
            (cons 62 c)
           '(40 . 2)
           '(72 . 1)
           '(73 . 2)
        )
    )
)

and the input is

(graph
   '((75 25) (115 45) (90 60) (10 5) (45 0) (45 55) (0 25))
   '(1 1 1 1 2 2 3 4 4 5 6)
   '(2 3 4 5 3 6 6 5 7 7 7)
)

The 2D geometry created from the above is exported as a dxf file from AutoCAD.

The actual input is generated in Python

pts = [(75, 25), (115, 45), (90, 60), (10, 5), (45, 0), (45, 55), (0, 25)]sls = [1 1 1 1 2 2 3 4 4 5 6]  
tls = [2 3 4 5 3 6 6 5 7 7 7]

I would like to know how to use the python data types as input and directly interface with AutoCAD from Python, save the AutoCAD output as a dxf file.

0 Likes
Accepted solutions (2)
19,752 Views
30 Replies
Replies (30)
Message 21 of 31

Anonymous
Not applicable

@Sea-Haven Could you please have a look at my last post?

0 Likes
Message 22 of 31

Anonymous
Not applicable

Hi All,

 

I just wanted to keep everyone posted that the issue posted in the last comment hasn't been solved yet.

0 Likes
Message 23 of 31

Anonymous
Not applicable
Accepted solution

"This opens the AutoCAD application, but the command in .src isn't sent. It just opens the drawing file. "

Some command is going wrong with the script file. Since it still opens the drawing, I think it is the (load ...), either because of secureload not set to 0 or the loadpath is not correct. Let's add the secureload the same way as with com, so the script should look like this:

open
<filepath>
(setq *LOAD_SECURITY_STATE* (getvar 'SECURELOAD))
(setvar "SECURELOAD" 0)
(load "...")
(graph ... ... ...)
(setvar "SECURELOAD" *LOAD_SECURITY_STATE*)
saveas 16 dxf
<filepath>
quit

load path should have double "\" or single "/" as path delimiters.

If you add the graph-defun-lisp to the startup-suite of AutoCAD, that (load ...) command is not needed.

 

AutoCAD scripts are a bit fiddly with the correctness. If it stops again at some point, try to see the messages AutoCAD has written into its command line.  That should tell, where the script requires some other answer than what the .scr is giving to it. For example saving and closing might introduce extra yes/no-questions depending on if you save to default format or not, so you might need a yes or a no at some point in the end of the script

Message 24 of 31

Anonymous
Not applicable

I had a wrong order on "saveas 16 dxf".
"saveas dxf 16" is correct.

Message 25 of 31

Anonymous
Not applicable

Hi @Anonymous 

 

I have been trying to generate a drawing from Python and the output dxf files aren't generated for some reason

when 3D points are present ( test1 and 2 in the python file link below).

 

Could you please have a look at this python script which includes the functions discussed above for running autocad and the autolisp code that called from python is available here?

 

I would also like to know if it is possible to specify the units . I want to set the units in `Engineering` `Microns` for the dxf output.

0 Likes
Message 26 of 31

Anonymous
Not applicable

My autocad hangs completely on the (graph ...)-line, I think the command line can only accept lines that are quite short. The point list goes easily over that character limit.

 

I think this can be fixed by separating lists by newline instead of space. Other way would be to write the (graph ... ) in a new .lsp file and then, in the script, load the new lisp file instead of giving the graph-command. I'd go with the lisp file as it produces cleaner output and is faster, since the command line doesn't have to parse so many lines.

So in write_scr, remove f"{graph}\n" and replace with '(load "file.lsp")' in which the file.lsp has that (graph ...) call written to it. Something like this:

 

with open(graph_command_file, 'w') as outfile:
        outfile.write(f"{graph}\n")
with open(GRAPH_SCR_FILE, 'w') as outfile:
        outfile.write("open\n" +
                      f"{GRAPH_DWG_FILE}" + "\n"
                      "(setq *LOAD_SECURITY_STATE* (getvar 'SECURELOAD))\n" +
                      '(setvar "SECURELOAD" 0)\n' +
                      rf'(load "{GRAPH_LISP_FILE}")' + "\n"
                      rf'(load "{graph_command_file}")' + "\n"
                      '(setvar "SECURELOAD" *LOAD_SECURITY_STATE*)\n'
                      "saveas dxf 16\n" +
                      rf"{GRAPH_DXF_FILE}" +"\n"+
                      "quit"
                     )

 

Multiple drawings in the same script might produce a problem later on (you'd need multiple lsp-command files, one for each input dwg). If you need to process multiple files in same .scr, go with replacing the " ".join(...) by "\n".join(...) in iter_to_lisp_string.

0 Likes
Message 27 of 31

Anonymous
Not applicable

My autocad hangs completely on the (graph ...)-line, I think the command line can only accept lines that are quite short. The point list goes easily over that character limit.

Yes, I experienced the same issue while running it manually in AutoCAD and it worked only after changing the point list to multiple lines.

 

I've now followed what was suggested above. `graph_command` is written to a lsp file (in a single line). The output dxf file is generated now but the drawing isn't created and it returns an empty file, unfortunately.

Could you please check these updates?

 

python file

graph command lsp  

function lsp

 

Thanks a lot for your time and kind attention. 

0 Likes
Message 28 of 31

Anonymous
Not applicable
Accepted solution

I don't see what goes wrong. In the python file, there is indentation missing on GRAPH_COMMAND_FILE-write, but I assume you fixed that since the lisp file was created. On my machine this works great. In the script, load GRAPH_COMMAND_FILE should have "\\" or single "/" as path separators, maybe check that?

0 Likes
Message 29 of 31

Anonymous
Not applicable

In the script, load GRAPH_COMMAND_FILE should have "\\" or single "/" as path separators, maybe check that?


Ahh, this worked! Thanks a lot. Since GRAPH_LISP_FILE worked with '\' I thought that shouldn't be a problem.

May I know if it is possible to set the units in `Microns`? 

 

 

0 Likes
Message 30 of 31

Anonymous
Not applicable

System variable INSUNITS controls that, 13 means microns. In script (setvar 'insunits 13) before drawing the graph. 

 

For the 'Engineering', if you want the texts to show in that format, use (rtos number 3) when converting number to string, mode 3 means 'engineering'. I don't know if the drawing can be put to 'engineering-mode' if you mean that. Does anyone else know?

Message 31 of 31

joneshosting_usts
Explorer
Explorer

Use AutoCAD python library an best python library with more features
You can do many thing like handling blocks, layers, groups, properties, ect....
https://jsweb-tech.github.io/AutoCAD/ 

> pip instal autocad
from AutoCAD import AutoCAD, APoint

cad = AutoCAD()

# Circle
circle = cad.add_circle(APoint(0, 0, 0), radius=5)

# Line
line = cad.add_line(APoint(0, 0, 0), APoint(10, 10, 0))

# Rectangle
rect = cad.add_rectangle(APoint(0, 0, 0), APoint(10, 5, 0))

# Ellipse
ellipse = cad.add_ellipse(
    center=APoint(20, 20, 0),
    major_axis=APoint(30, 0, 0),
    ratio=0.5
)

 

0 Likes