version 1.9.0.0 (10.6 KB) by
Sven

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

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

Sven (2021). stlwrite - write ASCII or Binary STL files (https://www.mathworks.com/matlabcentral/fileexchange/20922-stlwrite-write-ascii-or-binary-stl-files), MATLAB Central File Exchange. Retrieved .

Created with
R2011b

Compatible with any release

**Inspired by:**
surf2stl, mesh2tri

**Inspired:**
BiofilmQ, MRIqual, stlTools, Brain Projections, NIfTI Studio, Microscopy Image Browser (MIB), Microscopy Image Browser 2 (MIB2), stlwrite - Write binary or ascii STL file, punctureSurface, Export Voxel Data

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!Create scripts with code, output, and formatted text in a single executable document.

Meg NoahElijah UcheHi,

Please I need help with how to convert my rough surface model generated in MATLAB to an .stl file which would make it compatible with CST.

I have tried to use this code, but I don't seem to achieve the correct conversion.

Kindly oblige me please.

Thanks

Amir MinoofarWould it be possible for someone to tell me what should I do?

It gives me error and says unable to write the file.

Unable to write to test.stl

I'm using a simple one just for test:

[X,Y] = deal(1:40); % Create grid reference

Z = peaks(40); % Create grid height

surf2stl('test.stl',X,Y,Z)

际都 于Olivier MauzacCraig PuetzI have been trying to use this code without success. I can generate 3D plots using the Matlab commands trisurf and surf. I have plotted with both latitude, longitude coordinates, and with a distance based grid that I generated using meshgrid. Some of my data contains NaN as the surface is not a rectangular area. I have tried removeing these points, as well as setting them all to a floor that is slightly below my lowest real altitudes.

I haven't had success with any of these data sets. The results from stlwrite (and also from other Matlab Central routines surf2stl and surf2solid) is a flat plane, located on a Z coordinate system that I do not understand. Can anyone help with ideas? Thanks in advance.

Balachander GnanasekaranHi Sven,

I used the function and it worked perfectly. Is there a way to modify the code such that the maximum number of facets is given by the user?

Thank you.

Hongyang Zhouchaimaa hermamaHi

Great work, thank you.

One thing i observe that i can't generate more than one surface (eg : packed of spheres) in one fil. So how can i do it ?

Best regards

Stephan SchmiemannGreat work, works perfectly.

One thing I noticed, when I tried to export a sphere. At the poles, where two or more vertices fall together, the facet normals can't be calculated (due to normalization of a vektor of zero length). This can yield to errors in other programms.

I added the line "facets = facets(:,:,~squeeze(any(any(isnan(facets)))));" after the facets where created. This ignores all facets with zero area.

Yaeji KimSo Cool! Thank you!

B QiuMy data is medical image data. For example, there are pixel spacing and thickness in CT images. Mathematically, pixel spacing means the physical distance between the centers of each two-dimensional pixel.

Does anybody know how to set the pixel spacing and thickness in this code?

Eugenio GrabovicIt always writes just 3 faces, even the examples ones.

CherryGreat work, thanks for sharing!

However, I need to write a lot of small solids (separate volumes) in a single file when using binary format, I've tried many times to revise the code, no success yet.

Please, anyone can help? How to append multiple separate solids in a single stl file for binary format?

Thank you in advance!

Eva Pepergaetano mallardoworked properly to me passing (name, element matrix 3x3, xyz nodescordinates)

WA18784Hi can someone help - ive tried to use this function to create an stl file of a cube. The figure window comes out fine with like a patch works of 12 triangles and the stl function works fine until i view the stl file in a viewer and all i can see is just a straight line not a cube.

These are my V and F values and the code i'm using :

V2 = [0 0 0;

2 0 0;

0 2 0;

2 2 0;

0 0 2;

2 0 2;

0 2 2;

2 2 2];

Ftri =

[ 1 2 4;

1 4 3;

1 2 6;

1 6 5;

5 6 8;

5 8 7;

3 4 8;

3 8 7;

2 4 8;

2 8 6;

1 3 7;

1 7 5;]

figure(1)

cube = patch('faces',Ftri,'vertices',V1,'FaceAlpha',1,'FaceColor','green');

axis equal

stlwrite('Cube',Ftri,V1)

harsh jainDonald HumeBaisseyev MiramWilliam WarrinerJon KingHow would you use stlwrite to generate an .stl file for a graph with specified coordinates for nodes, along with different edgeweights?

Douglas CookMy experience is that this is not as robust as the much older surf2stl by Bill McDonald.

E. CheynetRingo CheungHi Sven,

This stlwrite module is great and it helps me much in generating a .stl file.

Now I successfully use the patch command to create a colored 3D model for visualization in Matlab. However, when I use stlwrite to export it there is no color at all.

I tried to use stlwrite('filename.stl', fv, 'FaceColor', [0 0 1]); but no color can be output, the file remains colorless when I view it using Microsoft 3DBuilder. Did I do anything wrong or the syntax is not correct? Please help.

Thanks,

Ringo

Yazanhi, Sven

How to convert a 3D volume generated from 2D stacked masks to .stl

Qi zengMonique PienaarThank you for sharing. One question how can I create a surface in the YZ plane at x = 0 ? Error Delanunay triangulation - points may be collinear?

B Qiuhi, Sven, thank you for your sharing. But i still have a problem. because my model is very jagged. Is it possible to do smooth for my stl model?

Sven@Alejandro: There are two issues: (1) You don't use the keyword "function" unless you are *defining* a function. Here you're just using the function. (2) The size of Z should be "Z = ones(6000,3000); " to match the sizes of X and Y.

Sven@rff123: you wrote that you have "the coordinates of all the points, n×4, named A". Is this just a typo? 3D points will be nx3. Ah... I think I see what you mean - the first column is an index. But then you say your *tetrahedral* data is mx4?

STL files take triangulated faces (mx3), not tetrahedrons which are 3d pyramid-like shapes. So basically, you need to identify your FACES and your VERTICES. The VERTICES are easy (note: your data is not gridded so your x,y,z variables don't make sense to me):

VERTICES = A(:,2:4);

Next, you need the faces. Maybe you mean your variable B defines *quadrilaterals*? If so, do the following:

FACES = triangulateFaces(B)

stlwrite('test.stl', FACES, VERTICES)

Sven@rff123: you wrote that you have "the coordinates of all the points, n×4, named A". Is this just a typo? 3D points will be nx3. Ah... I think I see what you mean - the first column is an index. But then you say your *tetrahedral* data is mx4?

STL files take triangulated faces (mx3), not tetrahedrons which are 3d pyramid-like shapes. So basically, you need to identify your FACES and your VERTICES. The VERTICES are easy (note: your data is not gridded so your x,y,z variables don't make sense to me):

VERTICES = A(:,2:4);

Next, you need the faces. Maybe you mean your variable B defines *quadrilaterals*? If so, do the following:

FACES = triangulateFaces(B)

stlwrite('test.stl', FACES, VERTICES)

Alejandro FernandezHi,

I am trying to use the stlwrite function for gridded data, STLWRITE(FILE, X, Y, Z), and I am following the same usage than Example 2, provided in the code description.

However, I get the following, probably silly, error: Error: File: stlwrite.m Line: 1 Column: 34

Unexpected MATLAB expression.

When I put the mouse on line 34 (the beggining of 'mode'), it yields the following message:

''Parse error at 'mode': usage may be an invalid MATLAB syntax''.

Please, find here below the code extract:

filename = 'Firsttest.stl'

Z = ones(3000,6000);

Y = (1:6000);

X = (1:3000);

function stlwrite(filename,X,Y,Z,'mode','ascii');

I have already tryied by transposing the vectors, removing the 'mode' argument, using double quotation marks ''.

Thanks

Alejandro

rff123Hi,

I have some problems. Now I have the coordinates of all the points, n×4, named A, the first column of the data is the sequence numbers of these points. Besides, I have the data of four points sequence number of all the tetrahedral, m×4,named B, and I try many ways to get the right .stl file, but it doesn’t works.

①x=A(:,2); y=A(:,3); z=A(:,4);

Stlwrite(‘test.stl’,x,y,z);

The result is “Duplicate data points have been detected and removed...”

②Then, I following JD’s comment(11 Apr 2013), used mesh2tri to generate the F and V,

[F,V]=mesh2tri(x,y,z,’f’);

But the F=[],it’s empty.

③I get the tri_data(p×3)from tetra_data(m×4），eg.

[1 2 3 4 ]=[1 2 3;1 2 4;1 3 4;2 3 4]

named C, and, stlwrite((‘test.stl’,C,A), then get the .stl file, but I found the normal vector of these facets are disunity, when I used the other software(DEFORM) to open this file ,I get the warning:It seems that the geometry contains open surfaces,.....

So can you help me? Am I doing something wrong? Thanks a lot for your job and your time.

Ryan ScottPhilip BatesGreat stuff, does exactly what I need, works well with the output of the delauny function to produce files that import into cloudcompare/Polyworks metrology software.

Sven@Duc, The problem you have is just that you've defined your faces in quadrilaterals (4 points) whereas STL is a triangulated format (3 points). There is a package called geom3d by David Legland which contains a simple triangulateFaces function. You can pass your F, variables as follows:

Ftri = triangulateFaces(F)

stlwrite('yourFile.stl',Ftri,V)

I will put in an explicit check for this issue as it comes up occasionally.

Duc NguyenHi. I'm trying to export stl file of a tesselated mouse atlas so I can work on it in Comsol. The faces in the atlas file is a nx4 matrix, vertices a nx3 matrix. This is causing your reshape to fail. Please advise.

Sven@Sheldon, there's no part of stlwrite that would do what you're describing. Perhaps you're passing quadrilateral data instead of triangular data? (if you have vertices and faces, what size is your matrix of faces?) Perhaps you've got gridded data and you're choosing 'x' triangulation? Without more information it's difficult to tell - for instance I'm also not sure what you mean by converting your points to Cartesian coordinates (aren't they already?)

Sheldon BridgesI am having an issue with exporting a triangular model using the STLWRITE function. Whenever i export the file, it changes my equilateral triangle to a right triangle. I tried converting the points to Cartesian coordinates but it still doesn't work. Is there something in the stlwrite function that i can change for that not to happen?

Sven@Steven: In that case then I think you should start with the first stlwrite example and see if that works for you. If the example works but your content does not, then the troubleshooting comes down to identifying what is different between the example and your data. Note that in the example, the command: "figure, patch('faces',fv.faces,'vertices',fv.vertices,'faceColor','g')" works to make a nice 3d figure. Does it work for you? Maybe your faces and vertices aren't N-by-3 doubles?

Steven LewisI am calling with just an FV variable created by isosurface.

Sven@Steven Lewis:

Those sizes of data seem reasonable - I wouldn't expect it to fail on a memory issue. Two potential issues: (1) are you calling with faces/vertices in the correct order? The signature is STLWRITE(FILE, FACES, VERTICES) if being passed separately. If still having trouble you can email me example data (sven dot holcombe at gmail).

Steven LewisI am getting an error every time I try to save my FV files saying index exceeds matrix dimensions., then Error in stlwrite (line 133); c0 = bitor(bitshift(bitand(2^6-1, facecolor(:,1)),10),c0). My FV variables contain 78576 X 3 faces, and 26192 X 3, both being double precision. I don't have any texture or color components to these FV variables. Any suggestions?

Faez AlkadiHi,

Is there anyway to offset STL File in 3D direction. I know surf2solid turns thin surface to a solid part. But what I'm looking for is to offset STL body. for example positive offset factor makes the body bigger and return new vertices, and negative offset factor make the body smaller and also return the new vertices.

The function (transformSTL.m) in the IGES Toolbox by Per Bergström does only transform STL. But what I'm looking for is something like( offsetIGES.m ) in the same toolbox except for STL instead of IGES file format.

Is there any function that does that?

Thank you so much

Ville LiimatainenGreat tool! The only thing I would add to the description is how to append multiple solids when using ascii format (tweak permissions), and how to write multiple separate volumes in a single file when using binary format (even though this is done before passing the data to stlwrite).

Carl WitthoftA suggestion: to deal with possibly 'unbalanced' input face/vertex sets, drop this code in near line 85:

facefoo = faces';

facefoo = facefoo(1:(end - mod(numel(facefoo),9)));

facets = reshape(facets(:,facefoo), 3, 3, []);

Sven@Greg Fivash

The problem you have is just that you've defined your faces in quadrilaterals (4 points) whereas STL is a triangulated format (3 points). There is a package called geom3d by David Legland which contains a simple triangulateFaces function. You can pass your F, variables as follows:

Ftri = triangulateFaces(F)

stlwrite('yourFile.stl',Ftri,V)

TillMany thanks, works perfect for getting stuff from Matlab to OpenSCAD and then into reality!

Sven@PHUONG TRAN:

Have you checked out my surf2solid file exchange entry? It might be just what you're looking for as it allows you to offset a surface to turn an infinitely thin surface into a closed volume.

Greg FivashI see that many people have had positive results from this script, but I have been encountering very basic problems. I defined a cube using faces and vertices, which displays properly using patch(), but it does not export into the same cube as an .stl file.There seems to be some misinterpretation of how the faces are connected between the vertices when the file is exported. Does anyone have any idea about what might be going wrong in my case?

My cube below:

V = [0 0 0;

1 0 0;

0 1 0;

1 1 0;

0 0 1;

1 0 1;

0 1 1;

1 1 1];

F = [1 2 4 3;

1 2 6 5;

5 6 8 7;

3 4 8 7;

2 4 8 6;

1 3 7 5;];

PHUONG TRANThanks Sven,

I just wonder if we can thicken the surface before or after converting to stl format.

Thanks

James ClementsJonathan TowneJonathan TowneThe third argument of reshape in line 81 should be size(faces,2) instead of 3 in order to account for a variable number of faces per patch surface. Other than that, good job.

Manuel CalvoDid the trick for me!

Just two tips I find useful for beginners (like me), and I think would be helpful if added to the documentation:

- You can create de faces-vertices structure from a volumetric 3D array, say V, with your data simply by:

fv = isosurface(X, Y, Z, V);

where X, Y, Z are vectors with the dimension of your volumetric array.

- The string argument 'FILE' or 'filename' (whatever you may call it) MUST INCLUDE the '.stl' extension, otherwise you'll create a file that is not that format. Lost five minutes figuring that out lol, thought it would be added by the script.

Alexander Lautnevermind, I found an easy solution to flipping the normals. say you used :

stlwrite([name,'.stl'],con+1,pts,'mode','ascii'); % exports mirror information to STL format

simply make:

con = [con(:,1),con(:,3),con(:,2)];

this will walk the other direction around each triangle flipping the normal for you.

Alexander Lautis there a convenient way to flip the normals as an option. Sometimes I'll build a symmetric region of the mesh, transform (X,Y,Z) to (X,-Y,Z) and the inside will become the outside.

Amirali Nojoomili zheStingarThis worked very well for me! Is there a simple way to densify the model? The shape should be the same, but with more triangles/vertices/faces.

manuel FOSSARamachandra KuraviI have been able to tweak the permissions command to use to append ascii type stl file. But the same doesn't seem to work with binary format files. Please advise.

Yang ShiThank you! Works well with Adam A's "STL to ACIS SAT conversion" for facet to solid conversion for many CAD programs.

BluppSven@Daschulka, yes, an STL file has triangles and faces, so you will need to turn your point cloud into a mesh in order to make an STL file. The solution to do this always depends on your particular problem - some simple shapes can be meshed using Delaunay triangulation but it will all be dependent on the point clouds you have and the meshes you want to make.

DaschulkaHi there,

I have been looking for a solution for receiving open surfaces after using stlwrite, like it is the case for Alexandra, but could not find a solution in the comments.

What is the way to resolve it? My input data is a point cloud... does it need to be turned into a mesh first? If that is the case, which functions have you been using to resolve the issues?

Many Thanks for the help!

dan brakejust what i needed to be able to 3d print from matlab surfaces. at least if the object has a well-defined interior. now to find a good solidifier... still waiting on that one.

Shelly LeeDan ChavezGreat job, very useful!

Chih-HaoIñigo MorenonOID eAmANJoeI was able to figure it out. Your codes work beautifully together. I doubt I could have done this better in any other way.

Thanks!

Joe@Sven

I've gotten your code to work for my 2D image--making it a surf() and then exporting fully into SolidWorks. I'm wanting to add thickness or full volume to it as in your surf2solid script.

Is there a way to take the surf2solid 'Block' and transfer it to an .stl with stlwrite()?

Thank you for your help! This code is awesome.

Mahmoud TahaThalles Leite@Sven

Thank you for your help! But it's still creating something like a basis under the solid, like a sheet.

Sven@Thalles

It's difficult to troubleshoot without being able to reproduce your error, but here's a way to take a 2D image and produce an STL of its surf() result. Does it give you a clue on how to fix your issue?

I = imread('rice.png');

I2 = conv2(double(I),ones(5)/5,'valid'); % Make it a little smoother

figure

sH = surf(I2);

% Get XData and YData as grids (not vectors)

[XD,YD] = meshgrid(sH.XData,sH.YData);

stlwrite('testSurf.stl',XD,YD,sH.ZData)

Thalles LeiteHi Sven, thanks for your really good work!

I'm having some problems with my stl, can you help me?

I have a image, I'm reading it and transforming into a double image. Then I'm selecting one of the 3(RGB) slices of the matrix to surf it with the function surface(), which give me the

propertys XData, YData and YData to use in your writestl(), but it's creating something like a basis under the solid, like a sheet and when I open this stl on the CubePro software, to print, I receive a bad file message.

Can you help me? Am I doing something wrong?

Thank you.

LIN HongbinI creat a struct and solve it,Thank you for your code.

LIN HongbinHello, Sven.

I have a vertex p matrix:8x3

and a triangualtion t matrix:12x3

I used stlwrite('test.stl',t,p),but I received:

Attempted to access facecolor(:,1); index out of bounds because size(facecolor)=[0,0].

Error in stlwrite (line 133)

c0 = bitor(bitshift(bitand(2^6-1, facecolor(:,1)),10),c0);

I was confused on how to use your command.Thank you

Sam KimDavid VerrelliHello, Sven.

Following Will's comment (29 Mar 2015), I too am still getting an apparently incorrect message if I write out in ASCII mode: I consistently get "Wrote 4 facets". When I write out in binary mode, I get correct values: e.g. 149194 facets or 205532 facets, verified by checking the number of faces I provided as input. Besides this minor glitch, the ASCII file seems to be okay so far.

Thanks for the contribution.

—DIV

Ilya BelevichSvenHi Benjamin, I suspect your issue is simply a matter of which reader you are using. If your software doesn't interpret the colour format chosen (see the help contents) then it will look like nothing has changed.

See for example the comments to this file below around September 2013 - others have found some software (Meshlab and Paraview) doesn't interpret this version of colour, while other software (VisCam) does.

Beniamin BogoselThe example you give using FaceColor does not seem to work. Adding face colors produces the same output as without colors.

RAJIB ROYGreat work, helped a lot

SvenHi Tyron, sorry for the slow reply. I think that most solid meshing will be done downstream in a mesher - I would expect that Abacus itself has a "tetra-mesh" function that can fill a closed STL volume with solid elements.

Sonomatic AustraliaHi Sven, Thank you this works a treat!

I've combined several patches to form an enclosed 3D object and exported that to *.stl using your function. How could I "solidify" this such that it could be meshed in Abaqus for example?

Murat AykinSimple and nice.

JiangShui HongCould u teach me how to use it？I am so stupid.

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

Sven@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.

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

nithish kalakondaHello 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 ?

Gaétan AÜLLOHello 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.

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

MatthiasThx 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?

Sven@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.

Matthias@ 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/

Sven@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.

Sven@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?)

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

MatthiasHallo, 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

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

Sven@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.

Rebecca Oylerhi,

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.

ye lianhuiI 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?

Alexander KosenkovVery simple, clean and fast implementation!

ThomasGreat 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 ;) )

Salaheddin HosseinzadehLuis CastroDear

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.

UrleaThank you Sven,

Works out great

Cheers

Sven@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])

UrleaI 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 ?

SteveThanks so much!

Adam HartGreat!

AdamAwesome! Thanks!

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

Ben@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!

Sven@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.

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

Thanks!

HaojieWorks great!

BenVery nice code and amazing fast! Thanks for sharing!

JD@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!

Sven@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.

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

Sven@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?

AlexandraHej,

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

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

AdamThanks 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!!

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

Binu@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).

AdamGreat 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?

Nick@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!

Sven@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.

Nickhi, 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.

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

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

Sven@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?

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

Thanks

William ThielickeWorks nicely. For my old Matlab version, I had to remove one line to make it work:

narginchk(2, inf)

Oliver WoodfordBinary output is now very fast! :)

Sven@Oliver

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

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

Holger RothGreat! That's what I looked for...

Georg StillfriedWorked fine!

Scott BurnsideNice companion to cad2matdemo.m. Very useful.