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:

pip install numpy-stl
# Or if you don't have pip available
easy_install numpy-stl

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

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')

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

50 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:

          import stl
          print('File causing the problem: ', stl.__file__)
          
  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!

  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:

          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)
          
        • 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:

            mymesh = stl.Mesh.from_file(filePath)
            
          • 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!

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