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

Leave a Reply

18 thoughts on “Solid AutoCAD objects in pyautocad (Python)

  1. 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.

  2. Thank you for this blog post, but I have a question, how do I use this method?
    RetVal = object.AddExtrudedSolidAlongPath(Profile, Path)

    1. 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!

  3. 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.

    1. 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.

  4. 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

    1. 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.

        1. Sure. Contact form sent. And LinkedIn invitation to Tanmay done. Hope to hear from you soon. Wechat Pay is very convenient if possible. Thanks.

          1. 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

  5. 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.

    1. 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

  6. 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.

      1. 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

        1. 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)

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.

Close

Meta