Code covered by the BSD License  

Highlights from
stlwrite(filename, varargin)

4.875
4.9 | 25 ratings Rate this file 234 Downloads (last 30 days) File Size: 10 KB File ID: #20922 Version: 1.8
image thumbnail

stlwrite(filename, varargin)

by

Sven (view profile)

 

30 Jul 2008 (Updated )

Export a variety of inputs (patch, surface) to an STL triangular mesh

| Watch this File

File Information
Description

** Big speed boost courtesy of Oliver Woodford. Recommended to update to latest version **
    stlwrite(FILE, FV) writes a stereolithography (STL) file to FILE for a
    triangulated patch defined by FV (a structure with fields 'vertices'
    and 'faces').
 
    stlwrite(FILE, FACES, VERTICES) takes faces and vertices separately,
    rather than in an FV struct
 
    stlwrite(FILE, X, Y, Z) creates an STL file from surface data in X, Y,
    and Z. stlwrite triangulates this gridded data into a triangulated
    surface using triangulation options specified below. X, Y and Z can be
    two-dimensional arrays with the same size. If X and Y are vectors with
    length equal to SIZE(Z,2) and SIZE(Z,1), respectively, they are passed
    through MESHGRID to create gridded data. If X or Y are scalar values,
    they are used to specify the X and Y spacing between grid points.
 
    stlwrite(...,'PropertyName',VALUE,'PropertyName',VALUE,...) writes an
    STL file using the following property values:
 
    MODE - File is written using 'binary' (default) or 'ascii'.
 
    TITLE - Header text (max 80 chars) written to the STL file.
 
    TRIANGULATION - When used with gridded data, TRIANGULATION is either:
                    'delaunay' - (default) Delaunay triangulation of X, Y
                    'f' - Forward slash division of grid quads
                    'b' - Back slash division of quadrilaterals
                    'x' - Cross division of quadrilaterals
                    Note that 'f', 'b', or 't' triangulations now use an
                    inbuilt version of FEX entry 28327, "mesh2tri".
 
    FACECOLOR - Single colour (1-by-3) or one-colour-per-face (N-by-3)
                    vector of RGB colours, for face/vertex input. RGB range
                    is 5 bits (0:31), stored in VisCAM/SolidView format
                    (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL)
 
    Example 1:
      % Write binary STL from face/vertex data
      tmpvol = false(20,20,20); % Empty voxel volume
      tmpvol(8:12,8:12,5:15) = 1; % Turn some voxels on
      fv = isosurface(~tmpvol, 0.5); % Make patch w. faces "out"
      stlwrite('test.stl',fv) % Save to binary .stl
 
    Example 2:
      % Write ascii STL from gridded data
      [X,Y] = deal(1:40); % Create grid reference
      Z = peaks(40); % Create grid height
      stlwrite('test.stl',X,Y,Z,'mode','ascii')
 
    Example 3:
      % Write binary STL with coloured faces
      cVals = fv.vertices(fv.faces(:,1),3); % Colour by Z height.
      cLims = [min(cVals) max(cVals)]; % Transform height values
      nCols = 255; cMap = jet(nCols); % onto an 8-bit colour map
      fColsDbl = interp1(linspace(cLims(1),cLims(2),nCols),cMap,cVals);
      fCols8bit = fColsDbl*255; % Pass cols in 8bit (0-255) RGB triplets
      stlwrite('testCol.stl',fv,'FaceColor',fCols8bit)

Acknowledgements

Surf2stl and Mesh2tri inspired this file.

This file inspired Stlwrite Write Binary Or Ascii Stl File, Export Voxel Data, Stl Tools, and Puncture Surface.

MATLAB release MATLAB 7.13 (R2011b)
MATLAB Search Path
/
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (61)
04 Jun 2015 Murat Aykin

Simple and nice.

04 May 2015 JiangShui Hong

Could u teach me how to use it?I am so stupid.

21 Apr 2015 Sven

Sven (view profile)

@nithish: Please formulate your question in a way that describes clearly what problem you have.

Comment only
21 Apr 2015 Sven

Sven (view profile)

@Matthias:

Most important steps:

1. Get your data into two variables:
"vertices" (an nx3 array of xyz coordinates. If you have 10 coordinates, it will be a 10x3 array)
"faces" (a px3 array of integer numbers (1, 2, 3, 4, etc) for your faces. If points 5, 6, and 3 form your first triangle, then the first row of this variable will be [5 6 3; ...])

2. Run the command:
figure, patch('Faces',faces,'vertices',vertices,'FaceColor','g')

If you can't get these two steps to work, then stlwrite will not work for you either, so it will not be helpful for you to try and work out why you can't write an stl file.

Comment only
21 Apr 2015 Sven

Sven (view profile)

@Gaétan

Here's how I would prepare a cylinder for stlwrite (or the patch() command). Note that I'm using the surfToMesh() and triangulateFaces() functions from David Legland's excellent geom3d file exchange entry:

[X,Y,Z] = cylinder(1,10);
[vertices, faces4] = surfToMesh(X,Y,Z,'xPeriodic', true);
faces3 = triangulateFaces(faces4);
stlwrite('file.stl',faces3,vertices)

figure, patch('Faces',faces3,'vertices',vertices,'FaceColor','g')

Comment only
21 Apr 2015 nithish kalakonda

Hello Sven,

Thank you for the code. But What i dont dont understand is how can i pass My data which is stored in array into stl ?

Comment only
16 Apr 2015 Gaétan AÜLLO

Hello and first, thank you for your contribution !
I have a little problem with my export. A lot of points in my figure have the same x and y coordinates (but differents z), because of the cylinder-like shape. So the export using the coordinates for arguments doesn't give me an appropriate STL file. I'm currently searching a way to create a triangulated patch of my geometry as you mentionned it in the program, but I really don't know how. Probably you know how to ..? Thanks a lot again for your time and your job.

16 Apr 2015 nithish kalakonda

I stored my text data into an array. But I dont understand how to give my array as input. Can please someone help me

Comment only
08 Apr 2015 Matthias

Matthias (view profile)

Thx for the answer.
I have tried to display the data with patch respectively the surf command of matlab but sadly I don't get any result.

But would it be possible otherwise to create a stlfile by using the coordinates of the triangles computed in the connectivitylist of the command convexhull after a triangulation?

Comment only
01 Apr 2015 Sven

Sven (view profile)

@Matthias:
The help of read_vtk says:
% [vertex,face] = read_vtk(filename, verbose);
%
% 'vertex' is a 'nb.vert x 3' array specifying the position of the vertices.
% 'face' is a 'nb.face x 3' array specifying the connectivity of the mesh.

The help of stlwrite says:
% stlwrite(FILE, FACES, VERTICES) takes faces and vertices separately

So why not just the following?

[vertex,faces] = read_vtk('file.vtk');
stlwrite('file.stl',faces,vertex)

This is direct. I don't understand what you're trying to do with MX, MY, MZ.

Here's a hint: if you cannot send your faces/vertices directly to MATLAB's patch() command (or your X,Y,Z data directly to MATLAB's surf() command) and get what you want on the screen, then using stlwrite() won't give what you want either.

Comment only
31 Mar 2015 Matthias

Matthias (view profile)

@ Sven

[vertex,faces] = read_vtk('file.vtk');
MX(1:length(vertex), 1)=vertex(1, 1:length(vertex));
MY(1:length(vertex), 1)=vertex(2, 1:length(vertex));
MZ(1:length(vertex), 1)=vertex(3, 1:length(vertex));
stlwrite('file.stl', MX,MY,MZ)

Basically I am sending the vertexes information of my objects, which is a simple cylinder. But the resulting object as stl-file isn't a closed volume anymore.

This is the result
http://postimg.org/image/ufpjdddrb/

Comment only
30 Mar 2015 Sven

Sven (view profile)

@Will: Ah, yes, that print error was annoying me too :)
I had it fixed on my machine, but the fex entry has been updated now as well.

Comment only
30 Mar 2015 Sven

Sven (view profile)

@Matthias: You need to provide some more details such as the command(s) you run when calling stlwrite, the variables you are sending to stlwrite, and what goes wrong (an error message?)

Comment only
29 Mar 2015 Will

Will (view profile)

Thanks for the great utility. When I run this, I always get the message "Wrote 1 facet" when it finishes. Perhaps I don't understand the terminology, but I expected the number of facets to be equal to the number of triangles being written, which I think is the second dimension of the facets matrix. (size(facets, 2))

25 Mar 2015 Matthias

Matthias (view profile)

Hallo, I am having trouble to create stlfile, i am extrakting the vertices and faces from a vtk-file using read_vtk but i dont know how to commit the data correctly to the stlwrite function? Any suggestions?
I am gratefull for every help trx

Comment only
11 Mar 2015 Sven

Sven (view profile)

@ye: I need more information to be able to help you there. Perhaps send your data and command you're using to call stlwrite.

Comment only
11 Mar 2015 Sven

Sven (view profile)

@Rebecca: There is no warning like that emitted from stlwrite itself. I believe you may be specifying that you want "triangulation" of XY data when that isn't the actual style of data you are providing.

It sounds like you have full 3D data rather than gridded XY data, so triangulating it based on its XY coordinate will not make sense due to the fact that you have *multiple* points that are above each other on your cylinder at the same XY coordinate. The warning you see is therefore spat out by the "delaunay" function (which does the triangulation).

Maybe you have quadrilaterals instead of triangles so you're trying to split them? If so, describe (or send) the data that you have, and there's probably a nice way to do that easily.

Comment only
11 Mar 2015 Rebecca Oyler

hi,
i'm writing a cylinder to an stl file, but stlwrite keeps eliminating repeating data points, which results in a simple circle instead of a 3D image. how can i get around this?

"Warning: Duplicate data points have been detected and removed.
Some point indices will not be referenced by the triangulation. "

thanks.

09 Mar 2015 ye lianhui

I use this to get a stl file, but when i use solidworks to open it, that become a plan not the 3D picture i polted in matlab, i don't know why,if anyone can help me?

Comment only
05 Jan 2015 Alexander Kosenkov

Very simple, clean and fast implementation!

26 Sep 2014 Thomas

Thomas (view profile)

Great work! And binary as well, i like it.

As a minor it would be cool to be able to specify the normals as well. (not that i couldn't do this myself, but it would save a minute ;) )

01 Sep 2014 Salaheddin Hosseinzadeh  
09 Aug 2014 Luis Castro

Dear

I Might you explain a little detail how to perform the conversion of stl right through points. I have 22050 points (xyz) belonging to the riverbed. My task is to generate an STL file.
In what format should I take the points?
As I run the compile stlwrite ?. They could give me the steps?
Please, could you help me.

Comment only
21 Jul 2014 Urlea

Urlea (view profile)

Thank you Sven,

Works out great

Cheers

Comment only
14 May 2014 Sven

Sven (view profile)

@Urlea: Yes, you can do this when (or after) you generate the faces/vertices.

If you are using the isosurface() function to generate your faces/vertices from a logical, remember that isosurface() will *always* produce faces pointing from low to high. In that case, you can just invert your logical mask (to have ones outside and zeros inside) when you call isosurface.

To flip faces after you've got faces vertices, just use the following:

fv.faces = fv.faces(:,[2 1 3])

Comment only
14 May 2014 Urlea

Urlea (view profile)

I am trying to Write binary STL from face/vertex data file with the example you give in your code. I then import the file generated in Magics (Materialise) and use an automatic tool to generate a diagnostig of the body. It says that all the faces are inverted (normals pointing inside out). Is there a way to fix this inside the Matlab code ?

Comment only
26 Mar 2014 Steve

Steve (view profile)

Thanks so much!

23 Feb 2014 Adam Hart

Great!

20 Feb 2014 Adam

Adam (view profile)

Awesome! Thanks!

05 Oct 2013 Reza

Reza (view profile)

Hi Friends,

Excellent job. I use it for a complex geometry which comes out of images. I created the .stl file but many surfaces are open and not connected. I want to have close surfaces with volume.

Thanks for your comments and help.

26 Sep 2013 Ben

Ben (view profile)

@Sven: I have done both your tricks. I found the problem is not your code; it is the software I am using to view meshes. I tried Meshlab and ParaView. None of them works for color surface. Probably they work for the other interpretation. VisCam works well for this. Thanks!

25 Sep 2013 Sven

Sven (view profile)

@Ben: Here's an example that uses the VisCam colour specification:

tmpvol = true(20,20,20); % Zeros on the inside means
tmpvol(8:12,8:12,5:15) = 0; % isosurface makes triangles
fv = isosurface(tmpvol, 0.5); % point out of object
faceColVal = fv.vertices(fv.faces(:,1),3); % Colour by Z height
cRange = [min(faceColVal) max(faceColVal)];
nCols = 255;
colMap = jet(nCols);
faceColsDbl = interp1(linspace(cRange(1),cRange(2),nCols),colMap, faceColVal);
faceCols8bit = faceColsDbl*255;
stlwrite('testCol.stl',fv,'FaceColor',faceCols8bit)
figure, patch(fv,'FaceVertexCData',faceColsDbl,'FaceColor','flat')

I used the free viewer here http://viscam-view.software.informer.com/download/, and the colours show up nicely.

You'll notice two tricks in my code above.
1. Make sure your face normals are pointing outwards. VisCam only displays the outer sides with colour and the inner sides without.
2. Make sure you provide 8-bit scaled colours (ie, between 0 and 255 rather than MATLAB's 0 and 1).

Did that work out for you? I might include that as an example in the help as long as it still works for you. Note that there are two competing "interpretations" of colour in an STL file. This is just one of them so I hope your software can interpret it well.

Comment only
25 Sep 2013 Ben

Ben (view profile)

Can anyone give an example of writing a stl file with per face color? I tried several times but did not make it.

Thanks!

Comment only
16 Aug 2013 Haojie

Haojie (view profile)

Works great!

27 Jun 2013 Ben

Ben (view profile)

Very nice code and amazing fast! Thanks for sharing!

11 Apr 2013 JD

JD (view profile)

@Sven: Thanks. It worked like a charm! It didn't work when I tried to connect it with using triangulation in stlwrite but when I used used mesh2tri to generate the faces and vertices and then used those in stlwrite, it worked! Thanks a lot again for such a quick reply!

Comment only
11 Apr 2013 Sven

Sven (view profile)

@JD:
The issue is that your input is "gridded data" not "triangulated data" because each of x, y, z is a 20-by-20 matrix, rather than a set of vertices and triangles.
This can be handled by stlwrite (see the help file for the "triangulation" parameter), but you'll need to understand that the default "triangulation" of gridded data is a delaunayTri of the X-Y 2D data. In this sense you have repeated X-Y pairs (one at the top of the sphere, one at the bottom). The warning you're getting comes from "delaunay", not from "stlwrite".
You can overcome this by specifying how you want your gridded data triangulated:

stlwrite('test1.stl',x,y,z,'mode','ascii','triangulation','f')

Note that you'll need "mesh2tri" from http://www.mathworks.com/matlabcentral/fileexchange/28327 for this to work. I will ask Kevin for permission to include it in stlwrite (it's a small but very handy function) for a next release.

Comment only
10 Apr 2013 JD

JD (view profile)

Hi! I am facing the same issues as Alexandra. I was trying to gererate surface mesh for a sphere and then converting into .stl format. When I tried to view it in Meshlab, one half of the sphere was gone. I did get a warining about duplicate data points.

Warning: Duplicate data points have been detected and removed.
Some point indices will not be referenced by the triangulation.

The commands I used are below:
[x,y,z]=sphere(20);
stlwrite('test1.stl',x,y,z,'mode','ascii');

Any help will be highly appreciated. Thanks.

Comment only
08 Oct 2012 Sven

Sven (view profile)

@Alexandra, I'll bet that probably there are some duplicated/disjoint vertices in MATLAB prior to using stlwrite. Can you send me an example of the data that is coming through open?

Comment only
06 Oct 2012 Alexandra

Hej,
I have the problem that I get open surfaces after using STLwrite. Has anybody an idea what to do about this?

02 Jul 2012 or litany

does anyone know how to show the different colors per face I used? I've tried meshlab and 3d max

Comment only
20 Jun 2012 Adam

Adam (view profile)

Thanks for your help Sven, turns out the problem was in my import settings in Gambit. It needed to be a little different because of the more complex geometries in those files. Again, wonderful program!!

Comment only
19 Jun 2012 Sven

Sven (view profile)

Ha, that last message was from me - logged on from another computer at work.

Comment only
19 Jun 2012 Binu

Binu (view profile)

@Nick and Adam, I'm not sure what issues may be at play with your files. Feel free to email a .mat file with your points/faces data *and* the 2 or 3 lines you use to create a working(!) figure from this data in MATLAB (note that I'll only have time to look at it if the figure creates cleanly).

Comment only
19 Jun 2012 Adam

Adam (view profile)

Great program. It worked fine for 2 of my files with relatively simple geometries, but one other didn't output a readable mesh (I tried to open it in both Solidworks and Gambit), the other didn't connect the mesh into triangles, there were just some points in Gambit. Both mesh just fine using the trimesh function. Any ideas?

02 Jun 2012 Nick

Nick (view profile)

@Sven you've been very clear, thanks. i ask an other question, to better understand.

my set of p x-y-z describes a 3D surface that i can see properly in matlab (using plot3 or trisurf), as you say.

to write the stl, I can use directly the function "stlwrite"?
Does this make a triangulation of my 3D coordinates?

In that case, which options I have to give to the function to make it works properly? because I have tried many ways, but when i give 'triangulation' it wants other options and values, and I don't know what to put into.

thanks again!

Comment only
01 Jun 2012 Sven

Sven (view profile)

@Nick: If you create a Delaunay triangulation from a set of p X-Y-Z points:

dt = DelaunayTri(x,y,z)

The result (dt.Triangulation) will not be a "triangular surface mesh". You'll notice that the result is an n-by-4 matrix. This means that each row in the triangulation represents a tetrahedron - a small *solid* with 4 triangular faces - not a surface triangle.

STL format describes surface triangles rather than tetra solids. Perhaps you want the convex hull of your points? (ie, only the *outermost faces* of all of your tetra solids) Note this will only work if your simple solid body is in fact convex.

Here's my advice: plot to the screen before trying to write to an STL file. If you can get a 3d surface plot (using patch, trisurf, etc) working in MATLAB first, *then* you will be able to write to STL without problems.

Comment only
01 Jun 2012 Nick

Nick (view profile)

hi, I have a set of coordinates of a simple solid body, and I have to create finite volumes to work on. So I made a 3D Delaunay triangulation, and I have now a n-by-4 matrix with the points of resultant tetrahedron. Now, I need to create a .stl file to export this work. how do I do this? Is it possible? Because in the option There is only the voice for a triangulation in 2D. Thanks a lot.

Comment only
04 May 2012 Joachim  
11 Mar 2012 Romain W  
03 Feb 2012 Sven

Sven (view profile)

@ava: glad to hear that the issue (nodes indices) was resolved

Comment only
15 Jan 2012 ava

ava (view profile)

@Sven:I am using STL viewer and also MiniMagics 2.o to see the result file but all the faces are disconnected.

Comment only
14 Jan 2012 Sven

Sven (view profile)

@ava: This is the first I've encountered such an issue. Does the same thing happen when you run the example in the stlwrite help? If not, try using the splitFV FEX entry to see if the original faces/vertices are indeed connected. If the stlwrite example itself comes out unconnected, what software do you use to read the .stl?

Comment only
14 Jan 2012 ava

ava (view profile)

Faces are not connected in the result stl. ,Does anyone have any idea?

Thanks

Comment only
04 Jan 2012 William Thielicke

Works nicely. For my old Matlab version, I had to remove one line to make it work:
narginchk(2, inf)

28 Nov 2011 Oliver Woodford

Binary output is now very fast! :)

13 Oct 2011 Sven

Sven (view profile)

@Oliver
The latest update has made significant speed improvements with vectorised face normal calculation and combining adjacent fwrite calls. Hope it's useful.

Comment only
13 Sep 2010 Oliver Woodford

Works well, though very slow (in binary mode at least).

02 Jul 2009 Holger Roth

Great! That's what I looked for...

28 Apr 2009 Georg Stillfried

Worked fine!

02 Aug 2008 Scott Burnside

Nice companion to cad2matdemo.m. Very useful.

Updates
11 Oct 2011 1.1

Vectorised normal direction calculations and streamlined fprint/fwrite calls. 75% faster writing speeds.

17 Oct 2011 1.3

Allowed for more general input types, and added capability for more features to be written to STL file.

24 Nov 2011 1.4

Huge speed improvements courtesy of Oliver Woodford. Reduction in write-time is proportional to file size.

20 Aug 2012 1.6

Added faceColor implementation

11 Apr 2013 1.7

Embedded version of Kevin's mesh2tri for convenience.

30 Mar 2015 1.8

Corrected face count printed output bug. Added example with coloured faces.

Contact us