Reading/writing 3D STL files with numpy-stl

For issues and/or questions, create an issue on Github: WoLpH/numpy-stl issues

As a followup of my earlier article about reading and writing STL files with Numpy, I’ve created a library that can be used easily to read, modify and write STL files in both binary and ascii format.

The library automatically detects whether your file is in ascii or binary STL format and is very fast due to all operations being done by numpy.

First, install using pip or easy_install:
[bash]pip install numpy-stl
# Or if you don’t have pip available
easy_install numpy-stl
[/bash]
Note that numpy numpy and python-utils version 1.6 or greater are required. While these should both be installed automatically by pip/easy_install, for numpy it’s generally recommended to download a binary release so it installs a bit faster.

Example usage: https://github.com/WoLpH/numpy-stl
[python]import numpy
from stl import mesh

# Using an existing stl file:
your_mesh = mesh.Mesh.from_file(‘some_file.stl’)

# Or creating a new mesh (make sure not to overwrite the `mesh` import by
# naming it `mesh`):
VERTICE_COUNT = 100
data = numpy.zeros(VERTICE_COUNT, dtype=mesh.Mesh.dtype)
your_mesh = mesh.Mesh(data, remove_empty_areas=False)

# The mesh normals (calculated automatically)
your_mesh.normals
# The mesh vectors
your_mesh.v0, your_mesh.v1, your_mesh.v2
# Accessing individual points (concatenation of v0, v1 and v2 in triplets)
assert (your_mesh.points[0][0:3] == your_mesh.v0[0]).all()
assert (your_mesh.points[0][3:6] == your_mesh.v1[0]).all()
assert (your_mesh.points[0][6:9] == your_mesh.v2[0]).all()
assert (your_mesh.points[1][0:3] == your_mesh.v0[1]).all()

your_mesh.save(‘new_stl_file.stl’)[/python]

Documentation can be found here: http://numpy-stl.readthedocs.org/en/latest/
Please let me know if you have any problems using it or just to tell me that you like the project 🙂

For the fastest response, ask questions on Github: WoLpH/numpy-stl issues

Bookmark and Share

Tags:

About Rick van Hattem

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

77 Responses to “Reading/writing 3D STL files with numpy-stl”

  1. fahad | 2015-04-16 at 20:44:19 #

    I run above program on raspberrypi and getting this error:

    Traceback (most recent call last):
    File “/home/pi/checkstl.py”, line 1, in
    from stl import stl
    File “/usr/local/lib/python2.7/dist-packages/stl/__init__.py”, line 2, in
    import stl.ascii
    ImportError: No module named ascii

    • Rick van Hattem | 2015-05-28 at 18:25:06 #

      For future reference, this error is caused by a different stl package. Since I started this project someone else apparently had a similar idea. Unfortunately the two projects conflict so if you get this error you need to do a “pip uninstall stl” followed by a “pip install numpy-stl” to get everything working again 🙂

      • Jaydip Biniwale | 2017-04-24 at 06:52:02 #

        Still the error persists. Even after doing the uninstall and reinstall

        • Rick van Hattem | 2017-04-24 at 10:48:10 #

          Do you have a file called “stl.py” by any chance? If so, please rename it since it’s apparently causing colisions.

          To test:
          [python]
          import stl
          print(‘File causing the problem: ‘, stl.__file__)
          [/python]

  2. Miguel | 2015-04-27 at 20:02:34 #

    Hi, I’m trying to create STL files after from generating 3D graphics with Mayavi and Matplotlib.

    I can not find a way to save the 2D arrangements for my variables X, Y and Z in a STL file, these variables are very important because their are used in methods to generate and display 3D surfaces.

    Thanks!

    • Rick van Hattem | 2015-05-28 at 18:06:27 #

      Hi Miguel, I’ve since updated the package to include a Matplotlib example. Perhaps that helps? 🙂

      Have a look at the quickstart: http://numpy-stl.readthedocs.org/en/latest/usage.html#quickstart

      • SELVA | 2019-04-04 at 11:52:18 #

        itis not able generate 3d STL, if i have use 500 slides dicom image ,i try convert stl, but STL forming as single dimension ,so upto 500 slides x y z co-ordinates formed in single dimension, so how to solve this?
        i have generate faces form x y z co-ordinate for STL generation, but this STL look lik single plate? so can share how form 3D STL ?

      • Vinibha | 2019-04-04 at 11:56:04 #

        How to form SLT from X Y Z, i have formed faces from X Y Z, but i cont generate STL, sample code what you have shared its working sample only ,its not working my data , so can you clear the doubts?

  3. Gregory | 2015-06-15 at 12:03:51 #

    Hi Rick,

    This library looks awesome and perfectly suited to my needs. I’d like to create basic solids like cubes, for example and was just wondering whether this was possible with the library and if so, how I would go about doing this.

    Many Thanks 🙂

    • Rick van Hattem | 2015-06-15 at 12:14:41 #

      Hi Gregory,

      It’s definitely possible although I’m not sure if it’s the easiest library for your purpose. Creating your own objects with the library requires you to manually create an array with points for the vertices. The library is meant to read/modify/write existing stl files and creating new stuff is a tad difficult. There are examples in the test though: https://github.com/WoLpH/numpy-stl/blob/master/tests/test_mesh.py#L99

      • Gregory | 2015-06-15 at 12:54:45 #

        Ah, Ok. I’m looking at using the library to create cubes at various points and then concatenate them. Would it be better for me to create the cubes manually as STL files and then use the library to concatenate them?

        • Rick van Hattem | 2015-06-15 at 13:11:46 #

          Concatenation is just appending the data arrays so it doesn’t make much difference really. It would come down to something like this:

          [python]mesh_a = mesh.Mesh.from_file(…)
          mesh_b = mesh.Mesh.from_file(…)
          data = numpy.concatenate((mesh_a.data, mesh_b.data))
          mesh_c = mesh.Mesh(data)
          [/python]

          • SELVA | 2019-04-04 at 11:53:06 #

            tis not able generate 3d STL, if i have use 500 slides dicom image ,i try convert stl, but STL forming as single dimension ,so upto 500 slides x y z co-ordinates formed in single dimension, so how to solve this?
            i have generate faces form x y z co-ordinate for STL generation, but this STL look lik single plate? so can share how form 3D STL ?

        • William Ratcliff | 2015-09-19 at 20:29:16 #

          Hi! Thanks for writing this library! It works beautifully! I have a question about his question–suppose he has 3 cubes –are they describe as points, or are they already tessellated by triangles? Suppose they are interpenetrating? If all he has is the vertices (not triangularized), then I think for the general problem, he may have to use something like alpha shapes to construct the mesh from the collection of points…Some cleanup of points that are inside of the surface may also be necessary–I’m not sure if alpha shapes will remove those automatically…

  4. Iva | 2015-07-08 at 14:37:00 #

    Hi! I am folowing the example at https://github.com/WoLpH/numpy-stl. I am working with WinPython-64bit-2.7.10.1 under Windows 7. My version of python utils is 1.6.2. When trying to execute the example with one of the stl files provided in the package (for example, bynarri Moon.stl) I get the following errors:

    1) AssertionError: File too large, got 1953785888 triangles which exceeds the maximum of 1000000

    2) ValueError: Attempted relative import in non-package.

    The fist one I am trying to solve increasing the default MAX_COUNT in stl.py.

    But I don’t know how to deal with the second one. Could you give me your assistance?

    Thanks!

    • Iva | 2015-07-08 at 15:17:12 #

      I tried to set MAX_COUNT to 1e10, but now I am facing with another problem:

      File “C:\Users\tester\Documents\WinPython-64bit-2.7.10.1\python-2.7.10.amd64\lib\site-packages\stl\stl.py”, line 99, in _load_binary
      return numpy.fromfile(fh, dtype=cls.dtype, count=count)

      MemoryError

      • Rick van Hattem | 2015-07-08 at 16:48:52 #

        The MemoryError is because you’re trying to load an absurd amount of data so it’s most likely detecting your STL file incorrectly. Perhaps it’s trying to load an ascii file as a binary file?

        As for the ValueError, I would need to see the entire stacktrace to know where the problem is. My guess is that your filenames are clashing with the numpy-stl files.

  5. Gopinath Taget | 2015-07-10 at 17:17:26 #

    Hello,

    Thanks for this very useful library.

    I am facing a problem with reading and writing binary STLs through. I get an error at the line:

    packed = struct.pack(‘@i’, self.data.size)

    and:
    count, = struct.unpack(‘@i’, b(fh.read(COUNT_SIZE)))

    The error is:

    TypeError: Struct() argument 1 must be string, not unicode

    I tried adding the following line before importing your STL but it did not help:

    # -*- coding: utf-8 -*-

    The only thing that seems to help is if I manually changed your code to look like this:

    packed = struct.pack(‘@i’.encode(‘utf-8’), self.data.size)

    and:
    count, = struct.unpack(‘@i’.encode(‘utf-8’), b(fh.read(COUNT_SIZE)))

    I really dont want to change your library to fit my needs. Is there a better way to resolve this issue?

    I am relatively new to Python programming so any help would be appreciated.

    • Rick van Hattem | 2015-07-10 at 17:54:50 #

      Hi Gopinath,

      This problem seems similar to one of the currently known bugs: https://github.com/WoLpH/numpy-stl/issues/10

      Can you tell me how you are opening the file and which Python version you are using?

      • Gopinath Taget | 2015-07-10 at 18:06:59 #

        Hi Rick,

        Thanks for the feedback. I am using Python 2.7.6. I am running this in a Virtual Env inside PyCharm. But I get the error even when I run it on command line.

        So you think one of the libraries is the issue?

        Thanks
        Gopinath

        • Rick van Hattem | 2015-07-10 at 18:33:54 #

          In this case it might also be related to how the file is opened. It seems the library needs some fixes so it’s a bit more versatile in different environments.

          How do you read the file exactly?

          • Gopinath Taget | 2015-07-10 at 18:37:21 #

            Hi Rick,

            I let your library read it for me. Here is what my code looks like:

            def ReadMesh(inputFilePath):
            filePath = inputFilePath

            mymesh = stl.StlMesh(filePath)

            # Do my stuff here

          • Rick van Hattem | 2015-07-10 at 18:47:26 #

            In that case you are probably using a pretty old version of numpy-stl. Can you try upgrading with: pip install -U numpy-stl

            And after that use this code instead of the StlMesh:
            [python]
            mymesh = stl.Mesh.from_file(filePath)
            [/python]

          • Rick van Hattem | 2015-07-10 at 18:50:19 #

            I just noticed this tutorial was out of date, I’ve just updated it 🙂

          • Gopinath Taget | 2015-07-10 at 19:34:52 #

            Hi Rick,

            I just started using the library so I already had 1.5.0. But I took your suggestion and upgraded to 1.5.1 and the problem still exists :-(.

            Thanks
            Gopinath

  6. ellan | 2015-12-28 at 10:30:08 #

    hi ,
    STL model to calculate the length and breadth, please give me some ideas
    ths!

    • Rick van Hattem | 2015-12-28 at 12:07:40 #

      Start by reading your STL file completely, after that it depends what you’re looking for. The simplest form of a length and breadth simply involve a mesh.X.max() - mesh.X.min() and mesh.Y.max() - mesh.Y.min()

  7. Guy | 2016-02-27 at 06:56:34 #

    Hi, Im normally a matlab user so I used to create stl files similar to how I would plot a surface.
    IE surf(x,y,z)–>stlwrite(‘name’,x,y,z) where z=f(x,y)
    Just wondering if theres similar syntax for generating an stl from 3 [NxN] arrays in your library?

    Thanks

  8. marco | 2016-03-08 at 16:54:20 #

    Hello ! Congratulations for your numpy-stl module.
    I’ve got a doubt.
    Is it possible extraction only the surface, in order to create an 2D image ?

    • Rick van Hattem | 2016-03-11 at 13:29:24 #

      Hi Marco,
      While it is possible to extract a 2D image out of a 3D image it’s not something the library does internally. With the matplotlib examples however, you can generate 2D images out of your STL files quite easily.

      • marco | 2016-03-11 at 15:55:15 #

        Thank you for answering.
        I got that the numpy-stl module doesnt support directly.
        I just want to use the top surface of the mesh to overlay in other images.
        I think that I need to “draw” in 2D the triangles, I’m not figuring out how.
        For instance; My problem in particular is applied to a PCB.
        I have here the stl file, which corresponds to a PCB mesh.
        A PCB has different copper layers. I want to apply the mesh to different copper layers, and later calculate all the seconds moments per triangle (each triangle will represent an element)
        https://dl.dropboxusercontent.com/u/710615/stlMidpoint.stl

        • Rick van Hattem | 2016-03-11 at 17:13:22 #

          It all depends what you need exactly. Most 3D projections use a single point as the camera of course which might not be what you need here.

          If you simply rotate the object so it aligns with one of the axes you should be able to get a simple 2D projection by flattening one of the axes. After that it’s a simple plot.

          • marco | 2016-03-11 at 17:18:32 #

            I did not get it.
            If I look from top the mesh (on a stl viewer) it is what I want 🙂
            But I’d like extract as coordinates. For instance, in numpy-stl I can extract the vectors and the points (but everything).
            I’d like create a numpy array (2D) which would be a binary image. Then it would be able to do operations and/or plots.

          • Rick van Hattem | 2016-03-11 at 18:39:10 #

            That’s really a job for matplotlib, here’s an example of how you can convert the matplotlib output to a numpy array: http://stackoverflow.com/questions/7821518/matplotlib-save-plot-to-numpy-array

          • marco | 2016-03-14 at 11:56:29 #

            Hi !
            I’ve tried your suggestion.

            However it has returned a huge array (the same size of the huge stl file) with every element 255 .
            I’d preffer coordinates or an image 🙂

          • marco | 2016-03-14 at 14:26:43 #

            Probably the image has so much density that it isn’t impossible to draw a proper triangular mesh with your code.
            I use this code: http://pastebin.com/Fk3nDyqP
            With this stl : https://dl.dropboxusercontent.com/u/710615/stlMidpoint.stl

          • Rick van Hattem | 2016-03-14 at 17:12:41 #

            You might have to increase the resolution quite a bit to make it work properly. But that’s all related to matplotlib and has very little to do with this library 🙂

        • marco | 2016-03-14 at 17:25:23 #

          I don’t know if it will solve.
          If you take a look into the stl, it is huge.

          I need to plot the triangular mesh of the top or the bottom (it’s the same) in order to use it as mask to other layers, which are 2D images.
          The sizes of layers and “mesh mask” should be the same Using matplotlib I would create a distortion on the mesh probably.

          you did a great job with your stl module, I don’t know if I’m able to properly use it.

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

            For your case, because of the size and complexity of the model, you probably need to create some sort of flatten function which squashes the model towards a single dimension.
            Before you can do that it needs to be properly rotated, but I believe that’s already the case looking at the file. So the only job that remains is drawing the triangles on a 2D grid. That should be simple enough since you have the coordinates but the problem might be that this can cause holes in your render due to rounding errors…

          • marco | 2016-03-15 at 11:14:17 #

            How is it organized your “vectors” object?
            For instance, if I have mymesh.vectors, how are they organized?
            Perhaps it is possible isolate only x,y from one of the surfaces.

            I’m thinking, if I have the xs and ys I’m able to render as coordinates using the opencv module.
            Opencv polylines supports numpy arrays.

          • marco | 2016-03-16 at 15:16:50 #

            Or even the Points vector. Is it possible extract coordinates or points to re-organize the numpy arrays in order to load into a figure?

          • Rick van Hattem | 2016-03-16 at 15:48:48 #

            The vectors object is simply a Nx3x3 array where N is the number of triangles and per triangle it’s a collection of 3 points with the X, Y and Z coordinates.

            Docs about the data model:
            http://numpy-stl.readthedocs.org/en/latest/stl.html#stl.base.BaseMesh.dtype
            http://numpy-stl.readthedocs.org/en/latest/stl.html#module-stl.base

            For your case you can also use the x and y attributes which is a Nx3 array with the 3 x and y coordinates of a triangle.

          • marco | 2016-03-22 at 11:35:51 #

            Thank you !
            I’m close to a dead end.
            I even open a stackoverflow questions, without any sucess 🙂

            http://stackoverflow.com/questions/36063129/opencv-python-triangular-mesh-having-coordinates

            I’ll re-read all information, trying to figure it out.

  9. Tibor | 2016-04-15 at 15:36:12 #

    Hi,
    I like your library numpy-stl. Its quick, simple and very easy to use.

    I would like to use it for reading stl files from zip file but I didnt find a way how to give Mesh parameters to read it from opened Zipfile instance.

    #opening zip file in memory
    opened_zipfile = ZipFile(“example.zip”, ‘r’)

    #reading specific file
    opened_zipfile.open(“cube.stl”)

    But how to connect it to Mesh.from_file or I overlook some special function for it?

    Many thanks for help

    • Rick van Hattem | 2016-06-18 at 11:32:19 #

      Hi,

      It’s actually not as hard as you might expect 🙂


      #opening zip file in memory
      opened_zipfile = ZipFile(“example.zip”, ‘r’)

      #reading specific file
      fh = opened_zipfile.open(“cube.stl”)

      your_mesh = mesh.Mesh.from_file('cube or some other name', fh=fh)

  10. Justin | 2016-06-16 at 22:46:27 #

    Hi! Great library!

    I have a software that takes in “surfaces” as a list of nodes(vertices) and elements(faces). I would like to take an .stl I’ve generated using photogrammetry and parse it, but I’m unsure how to determine the elements. Essentially, an element is defined as the 3 corners of each triangle. Is there a way to determine and list out the 3 corners of each triangle?

    Thank You!

  11. APRILIA | 2018-10-23 at 16:00:06 #

    nice posting

  12. karna | 2019-03-01 at 14:49:11 #

    How to generate STL from x y z? in python ?

    can share idea’s , x y z is co-ordinates [n dimension ],

    • Rick van Hattem | 2019-03-01 at 15:06:58 #

      If you simply have coordinates and nothing else you’ll need to do triangulation first. Which is not something this library does but you can let scipy take care of that.

      This library is simply for loading/saving/modifying STL files, converting point data to a mesh is a whole different topic.

      • SelvaKarna | 2019-03-13 at 14:02:45 #

        Can you share sample code?

      • KARNA | 2019-03-13 at 14:05:14 #

        Can you share small code about triangulation creation from x y z and convert to stl file?

        • Rick van Hattem | 2019-03-13 at 14:07:43 #

          For general usage of te library you can try the readme: https://github.com/WoLpH/numpy-stl/
          Or the documentation: https://numpy-stl.readthedocs.io/en/latest/

          As for triangulation, I can’t help you there. That’s not my area of expertise.

          • KARNA | 2019-03-19 at 05:58:53 #

            No use, this code.

          • KARNA | 2019-03-19 at 06:00:03 #

            in any other api is there STL writ from x y z 3d co-ordiantes using python ?you dont know about this ?

          • Rick van Hattem | 2019-04-09 at 13:28:42 #

            To create a mesh from X Y Z coordinates you can look at matplotlib. But it’s outside of the scope of this library.

      • SELVA | 2019-04-09 at 13:21:14 #

        Can you please share steps, to write STL;

        * i have 3d volume image[500 dicom slides]

        * i have extracted X Y Z co-ordinates from 500 slides

        * i have to generated Triangulation from X Y?

        * i have Faces & vertices also?

        * But i cont ,i am not able to write STL?

        below reference i cont understand also its not used for STL generation?

        https://github.com/WoLpH/numpy-stl#quickstart

        • Rick van Hattem | 2019-04-09 at 13:27:34 #

          Generating STL files is also possible, look at this section of the manual: https://github.com/WoLpH/numpy-stl#creating-mesh-objects-from-a-list-of-vertices-and-faces

          It does expect you to have the vertices and faces available already.

          • SELVA | 2019-04-09 at 14:28:51 #

            Rick van Hatte,

            Yes STL generated , but STL look like single dimension , actually x y z are extrected from 500 dicom images slides, this output of STL should 3D, but i got STL every [features–means 500 dicom image x y z ] are formed single dimension ? so this STL shape not like 3D shape, its simply just 2D layer only ?

            so if i have error any steps during STL Generation?

            from your reference output look like 3D STL, but outcome of my customs STL everything plotted single dimension? 2D?

          • Rick van Hattem | 2019-04-09 at 14:49:18 #

            If it’s in 2D something probably went wrong during the triangulation. The triangulation needs to happen in 3D as well between the dicom images. Although you can probably get away with triangulating between 2 dicom images at the same time to make it faster since full 3D triangulation will probably be fairly slow.

  13. SelvaKarna | 2019-09-30 at 12:43:16 #

    How to Generate Step file from Mesh ?

    • Rick van Hattem | 2019-09-30 at 12:48:56 #

      You can read the STL files with this library, converting it to other formats is outside of the scope of this project. It’s called numpy-STL for a reason 😉

  14. Ximena | 2019-10-07 at 23:49:05 #

    Hola que buena biblioteca, quisiera saber si me serviría para subir un archivo al servidor y poder mostrarlo?
    Muchas gracias de ante mano!!

  15. Nico Schlömer | 2019-10-23 at 15:23:35 #

    With meshio [1] (a project of mine) you can do all that, and for a whole range of mesh formats, not just STL.

    Cheers,
    Nico

    [1] https://github.com/nschloe/meshio

  16. SELVA | 2019-12-04 at 10:42:56 #

    its possible to extract shape feature and features based 3d volume component classify ?

    • Rick van Hattem | 2019-12-04 at 10:53:04 #

      The library gives you a list of points and vertices so you can process it in whichever way you need. But it’s definitely not something that’s built-in, that’s a whole separate field of research. Intuitively I would guess that the easiest way to do classification with 3D models is by creating point clouds and feeding that to a deep learning neural net.

  17. jahnavi | 2020-04-09 at 20:50:47 #

    I was trying to generate a Sphere with your code as given below.

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

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

    # Render the cube
    axes.add_collection3d(mplot3d.art3d.Poly3DCollection(Sphere.vectors))

    # Auto scale to the mesh size
    scale = Sphere_back.points.flatten(-1)
    axes.auto_scale_xyz(scale, scale, scale)
    # Show the plot to the screen
    pyplot.show()

    # Write the mesh to file “Sphere.stl”
    Sphere.save(‘Sphere.stl’)

    But I got ana error says…..
    IndexError Traceback (most recent call last)
    in
    27 for i, f in enumerate(faces):
    28 for j in range(3):
    —> 29 Sphere.vectors[i][j] = vertices[f[j],:]
    30
    31 # Create a new plot

    IndexError: index 9 is out of bounds for axis 0 with size 9

    Please help me I am totally new in this field.

Trackbacks/Pingbacks

  1. Reading and writing binary STL files with Numpy | Wolph - 2015-02-12

    […] I’ve since written a library to replace this script and add more functionality such as reading/writing both binary and ascii STL files. See the blog post here […]

Leave a Reply to Guy Click here to cancel reply.