In our previous blog posts, we learned about some basic geometrical objects such as the AutoCAD polyline, AutoCAD circle, AutoCAD arc, etc. Moving forward, we will discuss how to deal with the solid objects from AutoCAD using pyautocad in this blog post.
Initializing AutoCAD drawing and pyautocad script
As usual, we will set up our environment to integrate python with AutoCAD by importing the pyautocad library.
from pyautocad import Autocad, APoint
acad = Autocad(create_if_not_exists=True)
Understanding the basics of solid AutoCAD objects
In AutoCAD, we have different solid objects, e.g. box, cone, cylinder, sphere, etc. and each one of them has object-specific methods to create those individual objects.
But unlike the basic geometrical objects such as lines, polylines, circles, arcs, etc., to find the properties of the objects, we have a common set of methods that shall be used for all sorts of solid objects.
To make this clearer, we will start exploring solid objects.
Writing Python code for solid AutoCAD objects using pyautocad
In this blog post I will talk about some basic solid objects i.e. box, cone, cylinder, elliptical cone, elliptical cylinder, sphere, torus and wedge.
Each individual of the above-mentioned objects has its own methods to create those objects according to their respective geometrical properties.
I will mention the parameters to be passed with each of the commands that we will use for respective objects:
# Box: (Origin/Center, Length, Width, Height)
box = acad.model.AddBox(APoint(0, 0, 0), 1000, 1200, 750)
# Cone: (Center, Base radius, Height)
cone = acad.model.AddCone(APoint(2000, 0, 0), 750, 800)
# Cylinder: (Center, Radius, Height)
cyl = acad.model.AddCylinder(APoint(3200, 0, 0), 350, 1250)
# Elliptical Cone: (Center, MajorRadius, MinorRadius, Height)
econe = acad.model.AddEllipticalCone(APoint(4000, 500 , 0), 450, 225, 1275.62)
# EllipticalCylinder: (Center, MajorRadius, MinorRadius, Height)
ecyl = acad.model.AddEllipticalCylinder(APoint(1500, 2000 , 0), 750, 400, 950)
# Sphere: (Center, Radius)
sph = acad.model.AddSphere(APoint(2500, 3500, 0), 250)
# Torus: (Center, TorusRadius, TubeRadius)
tor = acad.model.AddTorus(APoint(1000, 4000, 0), 500, 100)
# Wedge: (Center, Length, Width, Height)
wed = acad.model.AddWedge(APoint(2000, 5000, 0), 1000, 1200, 750)
Drawing solit AutoCAD objects
Using the code given in point 3 I will draw the objects on the AutoCAD template.
As we can observe from Figures 1.1 and 1.2 the objects have been created.
But if we look closer in the top left corner of the template, we are using 2D wireframe by default, because of which the objects are not appearing like 3D objects.
We will set the visual style from 2D wireframe to the “realistic” style.
As we can see from Figure 1.3, the objects look more like 3D objects & realistic than in Figures 1.1 and 1.2.
5. Properties of solid objects
It is because the solid objects are a collection of polylines resulting in a solid object, the solid object has a similar set of properties that can be fetched using similar methods.
For example, we have methods to find the radius of gyration, the moment of inertia, volume, etc. and each object type possesses these properties.
Let us implement these methods against the box we have created and fetch the properties.
print("Volume of box: " + str(box.Volume))
print("Centroid of box: " + str(box.Centroid))
print("Moment of Inertia of box: " + str(box.MomentOfInertia))
print("Product of inertia of box: " + str(box.ProductOfInertia))
print("Principal directions of box: " + str(box.PrincipalDirections))
print("Principal moments of box: " + str(box.PrincipalMoments))
print("Radius of giration of box: " + str(box.RadiiOfGyration))
O/p:
Volume of box: 900000000.0
Centroid of box: (0.0, 0.0, 0.0)
Moment of Inertia of box: (150187500000000.0, 117187500000000.0, 183000000000000.0)
Product of inertia of box: (-0.0, -0.0, -0.0)
Principal directions of box: (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
Principal moments of box: (150187500000000.0, 117187500000000.0, 183000000000000.0)
Radius of gyration of box: (408.5033659592048, 360.8439182435161, 450.92497528228944)
To make sure this works for complex objects, we will use these commands against Torus.
O/p:
Volume of Torus: 98696044.01089358
Centroid of Torus: (1000.0, 4000.0, 0.0)
Moment of Inertia of Torus: (1592090559950727.0, 111649899787323.36, 1703246979517996.0)
Product of inertia of Torus: (-394784176043574.3, -0.0, -0.0)
Principal directions of Torus: (1.0, 0.0, -0.0, -0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
Principal moments of Torus: (12953855776429.75, 12953855776429.781, 25414231332805.0)
Radius of giration of Torus: (4016.372741666291, 1063.6023693091324, 4154.214727237869)
If we calculate the volume for torus using V=(πr^2)(2πR), we will get the same value as 98721640.0
where, r = Minor radius = 100 & R = Major radius = 500.
Else, if we use an inbuild AutoCAD command “MASSPROP” against torus, we will get the same results. Let’s check the same.
Civil engineer interested in automation in core subjects such as civil, mechanical and electrical, using IT skills comprising cloud computing, devops, programming languages and databases along with the technical skills gained while working as a civil engineer since past 3 years.
19 comments
Mr. Sawant,
Thank you for this blog post and the previous one about 2D objects. Can you tell me more bout the environment you are using? Python 2 or 3? What version of pyautocad? I only ask because I’m getting errors when trying to use the Copy() method and Move() method on circle and line objects.
Hello Mr. Phillips,
Thanks a lot for your question. The python version I am using is 3.9.7, and the pyautocad version is 0.2.0. Talking about copy and move commands, we have posted a blog regarding the same. This is the link : https://www.supplychaindataanalytics.com/operations-with-autocad-objects-using-pyautocad-python/
Please check this out. Have a great day!
Thank you
Thank you for this blog post, but I have a question, how do I use this method?
RetVal = object.AddExtrudedSolidAlongPath(Profile, Path)
Hello Jack,
Thanks for your question.
Firstly any Add method for geometries like AddCircle, AddLine, AddPolyline etc returns us ‘win32com.client.CDispatch’. This “CDispatch” has to be converted to “IDispatch” so that we can create an Array of Dispatch type of elements to form a region using VT_DISPATCH objects.
Secondly, the profile (region) and the path have to be in two different planes from each other.
After achieving the above-mentioned points we can draw an Extruded Solid by using the AddExtrudedSolidAlongPath method.
Have a great day!
Thank you for your very helpful writing.
I have a question. How to do Boolean operation to solid object such as _union in pyautocad?
Thanks in advance.
Hi,
Thanks a lot for the appreciation.
Can you please elaborate more on this? Like what exactly are you trying to achieve, and the problem you want to solve.
Kind regards.
Thank you. Tanmay Sawant
For example, below code will draw three cylinders, where cylinder 2 is on top of 1, and cylinder 3 penetrate both cylinder 1 and 2.
import pyautocad
acad = pyautocad.Autocad()
from pyautocad import APoint
cyl1 = acad.model.AddCylinder(APoint(0, 0, 0.5), 1, 1)
cyl2 = acad.model.AddCylinder(APoint(0, 0, 1.5), 1.1, 1)
cyl3 = acad.model.AddCylinder(APoint(0, 0, 1), 0.2, 4)
Now, I want to combine them into a new item say “cyl”. If using autocad I must type down “union” then manually selecting both, then hit Space or Enter. How to do it with pyautocad?
I tried below (just guess) but of course they didn’t work:
cyl = acad.model.Union(cyl1, cyl2)
cyl1.UnionWith(cyl2)
Secondly, I want to deleting the overlapping space of cyl3 tp cyl1 and cyl2. In autocad the operation is:
1) type down “su”
2) select cyl1 & 2 (or select cyl if they are combined in previous step), hit space
3) select cyl3, hit space again.
Thanks a lot for your help.
Kindly Regards,
Wei Lin
Linnart Felkl, Thank you.
Where can I find the Tanmay paid session? Or I probably just need a one line answer, how to do “union” in pyautocad ? (i.e., to piece solid objects together) Thank you.
I understand. You can send me an inquiry via the contact form on this website, or you can contact Tanmay on LinkedIn. Some bucks, maybe PayPal.
Sure. Contact form sent. And LinkedIn invitation to Tanmay done. Hope to hear from you soon. Wechat Pay is very convenient if possible. Thanks.
Hi Mr. Lin,
First of all thanks for reaching out to us. I read your problem and I think it is easy.
Actually there are two ways to solve that problem, one is by creating a region and the other one is more direct approach by using 2 entities to perform Boolean operation such as Union, Intersection and Subtraction.
You can use,
object1.Boolean(0, object2)
Where,
0=Union
1=Intersection
2=Subtraction
Object = Region or 3D Object
Also, you cannot store that object using any variable since this method returns nothing. But you can loop through the sheet to fetch the object and assign a variable to the same.
Once I come across the solution using Region (as it is more useful that this one), I will definitely let you know or create a separate blog post for the same.
Kind regards
Hi Mr Sawant
I have a new question: how to export solid objects into .stl files? (As you know .stl files are popular for many purposes)
Just following the above tutorial case, firstly I add two lines:
wed.Boolean(0, cyl)
wed.Move(APoint(0,0,0),APoint(2000,2000,2000))
which means I combine the solid of wedge and that of cylinder into one. Then move it into the positive coordinate domain. Now from the autocad GUI, I can easily export them into a .stl file, and save the file in places like my C:\Users\…\Desktop
Is it possible to do it automatically?
Thanks a lot.
Hi Mr. Lin,
Thanks for the question.
Unfortunately using pyautocad or pywin32 we wont be able to convert our .dwg file to .stl format.
The Export method only works when we want to convert our dwg to .wmf, .sat, .eps, .dxf, or .bmp formats.
The syntax to export the files is:
acad.doc.Export(FileName, Extension, SelectionSet)
File name = full path where the file is to be saved
Extensions = any of the above-mentioned formats (without “.”, capital or small anything is accepted)
Selection set = a selection set can be created to specify which object is to be exported
For WMF, SAT, and BMP formats, the selection set specifies the objects to be exported. For EPS and DXF formats, the selection set is ignored and the entire drawing is exported.
Though I will check if there is any other way in which I could export our .dwg to .stl
Kind regards
Good morning, thank you for sharing your knowledge, I would like you to help me with a problem.
I have generated a 3D solid and assigned it to the variable: loft_3D
In VBA, that solid would normally be taken to a new UCS with the TransformBy method, passing the UCS matrix obtained with GetUCSMatrix as a parameter. However with pyautocad I can’t find the solution.
Here I get the array of the target UCS
VarMatrix = MiUCS.GetUCSMatrix()
Here I try to transfer my solid: loft 3D, to the new UCS
loft_3D.TransformBy(VarMatrix)
However, getting the following error:
File “C:\Python37\lib\site-packages\comtypes\client\lazybind.py”, line 182, in caller
return self._comobj._invoke(descr.memid, descr.invkind, 0, *args)
File “C:\Python37\lib\site-packages\comtypes\automation.py”, line 729, in _invoke
dp, var, None, argerr)
_ctypes.COMError: (-2147352567, ‘Ocurrió una excepción.’,
(None, None, None, 0, None))
I have tried changing the UCS array from tuple to list, also transforming said array to array with numpy, also changing the syntax, but I can’t get it to work. Please help.
Hi Jorge,
Thanks for your question, can you please share your code with me? I’ll check the same and get back to you.
Kind regards
from pyautocad import Autocad, APoint
acad = Autocad()
# Create Loft 3D (a box)
loft_3D = acad.model.AddBox(APoint(0, 0, 0), 4, 6, 2)
# Data coordinates
x1 = 10
y1 = 10
x2 = 7
y2 = 8
# Points
p0 = APoint(x1,y1,0) # Point origin
py = APoint(x2,y2,0) # Point in axis y
# Point orthogonal to vector pi-py in axis x
px = APoint(0,0,0)
px.x = p0.x + (py.y – p0.y)
px.y = p0.y – (py.x – p0.x)
px.z = 0
# Create UCS
MiUCS = acad.doc.UserCoordinateSystems.Add(p0, px, py, ‘UCS_NEW_1’)
# We get UCS Matrix
VarMatrix = MiUCS.GetUCSMatrix()
# Translation and rotation of solid
loft_3D.TransformBy(VarMatrix) # Here the error occurs
i found a way to do it:
import win32com.client
import pythoncom
acad = win32com.client.Dispatch(“AutoCAD.Application”)
acadDoc = acad.ActiveDocument
acadModel = acadDoc.ModelSpace
acadUtil = acadDoc.Utility
def APoint(x, y, z = 0):
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x, y, z))
def aDouble(xyz):
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (xyz))
def aVariant(vObject):
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_DISPATCH, (vObject))
# Creamos el Loft 3D
loft_3D = acadModel.AddBox(APoint(0, 0, 0), 4, 6, 2)
# Coordenadas dato
x1 = 10
y1 = 10
x2 = 7
y2 = 8
# Coordenadas de origen y en el eje y
p0 = APoint(x1,y1,0) # Punto origen
py = APoint(x2,y2,0) # punto en eje y
# A los objetos creados con win32com solo lo puede tocar AutoCAD, es decir,
# solo se puede leer sus propiedades y ejecutar los métodos predefinidos por AutoCAD
# Punto ortogonal a vector pi-pf en eje x
px = [0,0,0]
px[0] = x1 + (y2 – y1)
px[1] = y1 – (x2 – x1)
px[2] = 0 # punto en y
# px = APoint(aDouble(tuple(px))) # no deja colocar lista, es estricto
px = APoint(px[0],px[1])
# Creamos UCS
MiUCS = acadDoc.UserCoordinateSystems.Add(p0, px, py, ‘UCS_NUEVO_1’)
# Obtenemos Matriz del UCS
VarMatrix = MiUCS.GetUCSMatrix()
# Convertimos a Double de win32com
VarMatrix = aDouble(VarMatrix)
# Trasladamos y rotamos sólido
loft_3D.TransformBy(VarMatrix)
Great man, thanks a lot. We had posted in the forum as well as we did not know this error ourselves.
import win32com.client
import pythoncom
acad = win32com.client.Dispatch(“AutoCAD.Application”)
doc = acad.ActiveDocument
msp = doc.ModelSpace
def APoint(x, y, z = 0):
return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x, y, z))
# Define the 2D geometry to revolve
circle = doc.ModelSpace.AddCircle(APoint(0,0),50)
# Create a point at (1, 2, 3)
point1 =APoint(-100,200,0)
point2 =APoint(-100, -200,0)
# Define the axis of revolution
line = doc.ModelSpace.AddLine(point1,point2)
# Revolve the 2D geometry around the axis
solid = doc.ModelSpace.AddRevolvedSolid(circle,line,180)
print(“done”)
i got a com_error: (-2147352571, ‘Type mismatch.’, None, 1), in the line of solid variable