Rendering your STL files with matplotlib using numpy-stl

It’s been a while since the first version of numpy-stl and a lot has changed since.

Most importantly, usage has become even easier. So here’s a demo on how to use matplotlib to render your stl files:

from stl import mesh
from mpl_toolkits import mplot3d
from matplotlib import pyplot

# Create a new plot
figure = pyplot.figure()
axes = mplot3d.Axes3D(figure)

# Load the STL files and add the vectors to the plot
your_mesh = mesh.Mesh.from_file('tests/stl_binary/HalfDonut.stl')
axes.add_collection3d(mplot3d.art3d.Poly3DCollection(your_mesh.vectors))

# Auto scale to the mesh size
scale = your_mesh.points.flatten(-1)
axes.auto_scale_xyz(scale, scale, scale)

# Show the plot to the screen
pyplot.show()

You can make the render prettier yourself of course, but it is certainly useful for testing.

Screen Shot 2015-07-10 at 18.53.28

Bookmark and Share

Tags:

About Rick van Hattem

Rick van Hattem is a Dutch Internet entrepreneur and co-founder of Fashiolista.com

14 Responses to “Rendering your STL files with matplotlib using numpy-stl”

  1. Luis | 2016-09-09 at 17:00:49 #

    Hi Rick,

    I have a question regarding rendering a stl file with python, do you think is possible to measure distance on an irregular stl model captured with a 3d scanner?

    I look forward for your answer

    Kind regards
    Luis

    • Rick van Hattem | 2016-09-09 at 17:53:24 #

      Hi Luis,

      Technically it’s not impossible of course but it’s definitely not that easy to do right. You need to filter out incorrect data and fill missing information which makes it very difficult. It’s definitely outside of the numpy-stl scope for the time being but you could easily use numpy-stl to do the processing using numpy and matplotlib.

      Best, Rick

      • Luis | 2016-09-11 at 15:44:59 #

        Hi Rick,

        Thanks a lot for your answer, but this is what I’m trying to do, to specify, I have a stl model of a welding bead, which I obtained from a 3d scanner and I would like to obtain its dimension (height and widht of the bead) . I was thinking of cutting many cross section measure this sections get their values and then obtain the mean and the standard deviation, but I don’t have any clue of how can I do this in Python, so any little help is welcome.

        I look forward for your answer
        Thank you

        Luis

        • Rick van Hattem | 2016-09-14 at 18:08:20 #

          I think one of the easiest solutions would be to store all of the points in an kd-tree or octree. From that point on you can easily process the object bit by bit. Although instead of layers it will be clusters of points which are most likely more useful anyhow.

          It’s a bit outside of my expertise though and I have no idea if that’s the most convenient solution.

          A quick google gave me this overview, it could be helpful: http://www.meshrepair.org/

          • Uvar | 2017-06-30 at 09:53:36 #

            Once we have some free time, we definitely should get working on integrating my (Python 2.7) code.
            It includes mesh repair and automatic rotation to optimal print direction. (based on heuristics which are sort of complicated, but expert-validated for > 200 objects)
            To then obtain dimensions would be as simple as (object[X].max() – object[X].min()). 😉

  2. SAGAR HUKKIRE | 2017-01-31 at 14:21:14 #

    hi
    I have two stl files of with two organs data of original MRI file . How I can merge to stl files to get the part I needed

    Thanks
    Sagar

    • Rick van Hattem | 2017-01-31 at 16:20:51 #

      The simple solution is to read both files and simply write it to a new file. Something along the lines of:

      import numpy
      from stl import mesh
      
      mesh_a = mesh.Mesh.from_file('file_a.stl')
      mesh_b = mesh.Mesh.from_file('file_b.stl')
      new_mesh = mesh.Mesh(numpy.concatenate([mesh_a.data, mesh_b.data]))
      

      Note that this will require you to have enough memory to keep both of the original models in your memory twice.

      This is definitely not the fastest solution since you’ll be parsing the data while copying it. A much faster solution would be to simply concatenate the files and merge the headers. That’s a bit outside of the scope of this project but it’s actually not that hard to do.

      For the binary stl format you simply need to add the sizes of both files to eachother (bytes 80 to 84) and concatenat bytes 84 till the end of both files to the new file.

      For the ascii format it’s pretty similar, you need to skip the “endsolid …” line for the first file and skip the “solid …” line for the second file and beyond that you can simply concatenate.

  3. Erez | 2017-07-16 at 17:15:32 #

    HI Rick,

    I am trying to run the numpy-STL examples and when I try to load an STL I get:
    ValueError: incompatible dimensions for cross product
    (dimension must be 2 or 3)

    could you tell me what I am doing wrong?
    Thanks

    • Rick van Hattem | 2017-07-19 at 23:39:48 #

      Without seeing the code I can’t be sure what’s causing it. The only parts of the code that generate cross-products are the remove_empty_areas method and the update_normals method.
      Can you create an issue at the Github repository with the code? I’m guessing you’re specifying the data incorrectly somehow but I can’t be sure.

      Add Github Issue

  4. Georege | 2017-07-26 at 00:55:06 #

    is it possible to make numpy-stl compatible with python3?
    Thanks!

    • Rick van Hattem | 2017-07-26 at 01:39:12 #

      It is Python 3 compatible, tested on Python 3.4, 3.5 and 3.6 actually 🙂

      • Georege | 2017-07-26 at 02:16:17 #

        Thank you for reply. I am a bit new to python…It seems I can install in python3 now.
        but when I try to install in my python 2.7 environment, it seems the enum module has no enum.IntEnum. and I tried to install the flufl.enum and modified ‘import enum’ to be ‘import flufl.enum as enum’. Then when I try to run the example code to get stl file, I got an error

        import numpy as np
        from stl import mesh
        vertices = np.array([\
            [-1, -1, -1],
            [+1, -1, -1],
            [+1, +1, -1],
            [-1, +1, -1],
            [-1, -1, +1],
            [+1, -1, +1],
            [+1, +1, +1],
            [-1, +1, +1]])
        # Define the 12 triangles composing the cube
        faces = np.array([\
            [0,3,1],
            [1,3,2],
            [0,4,7],
            [0,7,3],
            [4,5,6],
            [4,6,7],
            [5,1,2],
            [5,2,6],
            [2,3,6],
            [3,7,6],
            [0,1,5],
            [0,5,4]])
        
        # Create the mesh
        cube = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype))
        for i, f in enumerate(faces):
            for j in range(3):
                cube.vectors[i][j] = vertices[f[j],:]
        

        I got the error message:

        surface = mesh.Mesh(np.zeros(faces_tot.shape[0], dtype=mesh.Mesh.dtype))
          File "C:\Program Files\xxx\Python27\lib\site-packages\stl\base.py", line 176, in __init__
            if RemoveDuplicates.map(remove_duplicate_polygons).value:
        TypeError: 'EnumValue' object is not callable
        

        where xxx is where my python being installed.

        Am I totally wrong at somewhere?
        Thanks!

        • Rick van Hattem | 2017-07-26 at 02:22:14 #

          Normally installing should be as simple as pip install numpy-stl, that should automatically install the enum module as well. The flufl.enum is not the right one at least, you need the enum34 module: https://pypi.python.org/pypi/enum34

          • Georege | 2017-07-26 at 07:03:53 #

            Thanks Rick. seems I had an Enum module installed before. It’s ok after it is uninstalled.

Leave a Reply