Solid AutoCAD objects in pyautocad (Python)

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.

Figure 1.2: Solid objects from the top view (2D Wireframe)
Figure 1.2: Solid objects from the top right corner (2D Wireframe)

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.

Figure 1.3: Solid objects from the top right corner (Realistic)

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.

Figure 2.1: Properties of the torus
Figure 2.2: Properties of the torus

You May Also Like

Leave a Reply

19 comments

Patrick J. Phillips says:

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.

jack says:

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!

Wei Lin says:

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.

Wei Lin says:

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

Wei Lin says:

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.

Wei Lin says:

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

Wei Lin says:

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

Jorge Paredes says:

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

Jorge Paredes says:

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

Jorge Paredes says:

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.

Maha says:

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

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.