Code covered by the BSD License

Download apps, toolboxes, and other File Exchange content using Add-On Explorer in MATLAB.

### Highlights from surf2solid - make a solid volume from a surface for 3D printing

4.69231
4.7 | 15 ratings Rate this file 79 Downloads (last 30 days) File Size: 6.08 KB File ID: #42876 Version: 1.5

# surf2solid - make a solid volume from a surface for 3D printing

by

### Sven (view profile)

29 Jul 2013 (Updated )

Turns thin surfaces into closed solids by adding a flat base or offsetting by a given thickness.

### Editor's Notes:

This file was selected as MATLAB Central Pick of the Week

File Information
Description

SOLID_FV = SURF2SOLID(FV,...) takes in a triangulated patch defined by
FV (a structure with fields 'vertices' and 'faces'), and returns a
solid patch SOLID_FV closed by options (described below).

SOLID_FV = SURF2SOLID(F, V,...) takes faces and vertices separately.

[F,V] = SURF2SOLID(...) returns solid faces and vertices separately.

SURF2SOLID(...) with no output argument plots the 3 components
(orig-surface, side-walls, under-surface) to a new figure.

SURF2SOLID(X, Y, Z, ...) reads in surface data in X, Y, and Z matrices,
and triangulates this gridded data into a surface using triangulation
options specified below. Z must be a 2D matrix. X and Y can be 2D
matrices of the same size as Z, or vectors of length equal to SIZE(Z,2)
and SIZE(Z,1), respectively. If X or Y are scalar values, they are used
to specify the X and Y spacing between grid points.

SURF2SOLID(...,'PropertyName',VALUE,...) makes a solid volume from thin
surface using any of the following property/value options:

ELEVATION - Extends the surface down to a flat base at the given
(Z) elevation value. Useful for turning a thin
elevation map into a solid block with a flat base. The
ELEVATION value should be below the lowest (or above
the highest) data point. If no other options are given,
ELEVATION defaults to MIN(Z)-0.1*(MAX(Z)-MIN(Z)).
Variable ELEVATION may also be given per-point, via a
2D matrix (the same size as Z for X,Y,Z style input) or
a 1D array (with length equal to the number of vertices
given in face/vertex input).

THICKNESS - Value to offset the given thin surface to make a
thickened solid slab. Each node on the surface will be
projected along its normal direction by thickness. When
negative thickness is given, offset will be away from
face normal direction. Variable thickness can also be
specified via a 2D matrix (of same size as Z, for X,Y,Z
input) or an N-by-1 array of thicknesses (where N is
the number of vertices in the thin surface)

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 'x' triangulations use an
inbuilt version of FEX entry 28327, "mesh2tri". 'x'
style triangulation cannot be used with variable
ELEVATION or THICKNESS parameters.

NORMALS - When THICKNESS options is used, the direction to
thicken the surface is (by default) determined by the
surface (unit vector) normal directions at each vertex.
To override these default directions, you may specify
NORMALS as an N-by-3 array of normal directions (where
N is the number of vertices in the thin surface). This
is useful when underlying data gives more precise
normal directions than face orienatations (for an
example, see the isonormals function).

Note 1: Currently surf2solid will return a closed surface with face
normals pointing "out". With user feedback, I'd be happy to change this
behaviour to either "in" or "unchanged from input direction".
Note 2: If a single ELEVATION value is specified (i.e., flat base), the
resulting patch will have minimal triangles on the flat base to reduce
patch/file size.

Example (shows both THICKNESS and ELEVATION forms):
n = 30;
[X,Y] = meshgrid(linspace(0,1,2*n+1));
L = (40/51/0.9)*membrane(1,n);
figure, subplot(2,2,[1 3]), title 'Thin surface'
surf(X,Y,L,'EdgeColor','none'); colormap pink; axis image; camlight
subplot(2,2,2), title 'Block elevation'
surf2solid(X,Y,L,'elevation',min(L(:))-0.05); axis image; camlight; camlight
subplot(2,2,4), title 'Thickness'
surf2solid(X,Y,L,'thickness',-0.1); axis image; camlight;

Original idea adapted from Paul Kassebaum's blog post
http://blogs.mathworks.com/community/2013/06/20/paul-prints-the-l-shaped-membrane/
Many thanks to Paul for his further input and improvements.

Acknowledgements

Mesh2tri inspired this file.

This file inspired Puncture Surface.

Required Products MATLAB
MATLAB release MATLAB 8.1 (R2013a)
Tags for This File   Please login to tag files.
Comments and Ratings (25)
19 Jul 2016 sumana

### sumana (view profile)

09 Jul 2016 Josafat Quiroz

### Josafat Quiroz (view profile)

Hi seven,

is there any way to get the area and volumen of the generated solid?

24 Jun 2016 Leila Ghanbari

### Leila Ghanbari (view profile)

Hi Sven,

Great job. I would like to generate a smooth surface;
FV_closed = surf2solid(x,y,z,'triangulation', 'delaunay', 'thickness',-2);

I am using 'triangulation', 'delaunay', since only specific range of x and y is desirable. But the surface is not smooth. Is there any way to fix it?

Comment only
29 Jun 2015 Meghan Kazanski

### Meghan Kazanski (view profile)

Is there any way to combine multiple surfaces (as two sets of X,Y,Z matrices) into one solid?

Comment only
28 May 2015 Sven

### Sven (view profile)

@Sarah: You gave a property ('elevation') without a value. You need to specify the actual elevation that you desire. Try this code, which specifies an elevation of "3" such that faces are extruded down to a Z-coordinate of 3:

V = [0 0 10; 1 2 11; 2 4 12; 4 2 11; 5 0 10; 2.5 0 9];
F = [1 2 6; 6 4 5; 2 4 6; 2 3 4];
surf2solid(F,V,'Elevation',3)

Does this solve your problem?

Comment only
27 May 2015 Sarah Weissenberger

### Sarah Weissenberger (view profile)

Hi Sven,

I would like to use your code, giving it faces and vertices.
I tried using: surf2solid (F,V, 'elevation');

But Matlab is throwing an error. Can you imagine what is wrong with that?

Thank you very much.

30 Nov 2014 Evan

### Evan (view profile)

Hi, a question when trying to figure out a solid with holes inside. For example, the "meshgrid" creates a 5*5 matrix, but I only need to use the central ring area to create solid ring-cylinder. I tried to set the thickness of those pixels(unwanted) to 0, but it still carried out a flat plan covering the whole 5*5 area (I expect no solid in the center hole). How could I set it? Thanks so much.

29 Aug 2014 Nathan Tomlin

### Nathan Tomlin (view profile)

Works really great and imports into openscad perfectly!

29 Aug 2014 Nathan Tomlin

06 Aug 2014 Sven

### Sven (view profile)

Hi Mona, the output from surf2solid (a faces/vertices structure) can be given directly to stlwrite:

FV = surf2solid(...)
stlwrite('yourfile.stl', FV)

Comment only
06 Aug 2014 Mona M Kanafi

### Mona M Kanafi (view profile)

Hi Sven,

Could you give me a clue on how to convert this generated solid topography into STL format? For instance using your older 'stlwrite - Write binary or ascii STL file' code.

Thanks for the awesome work in advance! :)

23 Jul 2014 Sven

### Sven (view profile)

Hi Marios:

1) Use the triangulated faces/vertices input (SURF2SOLID(F, V,...)) instead of the gridded input (SURF2SOLID(X, Y, Z, ...)) and you can make arbitrary shaped surfaces instead of a grid. I would simply put 0 thickness at the nodes you don't want solid instead of NaN thickness.

2) This is possible, you just need to calculate the distance you want each node to be offset and use that 'thickness'. Basically, give the thickness as the difference between the original surface and your desired surface.

Here's a small example that uses most of those options:

v = [2 4 0; 2 6 0; 8 4 1; 8 0 0; 0 4 0]
f = [1 2 3; 1 3 4; 5 2 1]
figure, surf2solid(f,v,'thickness',[0 0 3 2 0])

Comment only
23 Jul 2014 Marios

### Marios (view profile)

Hi Sven,

Very good work. Two questions.

1) Can I change the rectangular mesh to an irregular (curved) one. I have NaN to areas I don't want to create a solid, but it says that it is not supported.

2) Is it possible that user provide a different bottom surface (assuming that up and down surface have the same x,y coordinates).

Comment only
23 Feb 2014 Adam Hart

Great!

20 Feb 2014 Adam

### Adam (view profile)

Awesome! Thanks!

08 Feb 2014 Daniel

### Daniel (view profile)

Thanks for the update Sven! After removing degenerate faces from my surfaces, I feel like this works very well. I've even fed the result through stlwrite, and successfully printed one.

-Daniel

30 Nov 2013 Sven

### Sven (view profile)

Hi Daniel, I've had time to make this fix - it was simply a case of adding an if-isempty clause to line 100 to detect surfaces without any boundary. It's in submission now, and here's a working example of a torus that had the error you described but now works fine:

% Make a torus
a=5;
c=10;
[u,v]=meshgrid(0:10:360);
x=(c+a*cosd(v)).*cosd(u);
y=(c+a*cosd(v)).*sind(u);
z=a*sind(v);
% Get quad faces
figure, t = surf(x,y,z); p = surf2patch(t); close(gcf)
% Triangulate faces (removing coincident vertices)
tri = cat(1, p.faces(:, [1 2 3]), p.faces(:, [1 3 4]));
[unqV, ~, unqI] = unique(p.vertices,'rows');
pTri = struct('vertices',unqV,'faces',unqI(tri));
% Solidify thin surface
pSol = surf2solid(pTri,'Thickness',1)
% Show the result
figure, patch(pSol,'FaceColor','g','FaceAlpha',0.2)

Comment only
19 Nov 2013 Sven

### Sven (view profile)

Hi Daniel,
That sounds like the type of thing that surf2solid should handle but I never used it as a test case. I think it should be manageable to work out what to do when "edge" faces are empty. I'll try to put something in, but it will be a week or so... I'm travelling right now.

Comment only
18 Nov 2013 Daniel

### Daniel (view profile)

Thanks for the m-file! I am generally pleased with what I see.

I would like to use this file to thicken surfaces generated from implicit equations. Such an example is a torus. I have a coarse set of faces which describe the surface, and want to pass it through the thickener for printing, but I am getting an error at and beyond line 99 (getting boundVerts), because there are no bounding vertices (the surface is closed!)... Do you have a workaround? It is not immediately clear to me how to correct for this.
Thanks again!

05 Oct 2013 Elad

### Elad (view profile)

Awesome work!
here is a link to an excellent blog post (written by Sven) with examples of how to use surf2solid function:
http://imageprocessingblog.com/surf2solid-a-tool-for-3d-printing/

17 Sep 2013 Phalgun Lolur

### Phalgun Lolur (view profile)

What I meant to say was, I use the hold on command to add new objects to my axis. But how do I create an stl file from that? My objective is to print a multi-layered 3D file. But I'm not quite sure how to do that.

Comment only
17 Sep 2013 Sven

### Sven (view profile)

Hi Phalgun,
I don't quite know what you mean by "multi-layered data". As far as I can tell, the "hold on" command will simply let you add new objects to your current plot axes... nothing about multi-layers and nothing about printing there. What is the "multi-layered 3d image file" type that your 3d printer accepts, and how do you create one of these files normally?

Comment only
16 Sep 2013 Phalgun Lolur

### Phalgun Lolur (view profile)

Dear Sven,

The file worked wonderfully well. But if I needed to use it for printing multi-layered data, how would I do it? I usually use the "hold on" command to generate these multi layered 3d image files in matlab. But I was wondering how to create an stl file from it.

30 Jul 2013 Paul Kassebaum

### Paul Kassebaum (view profile)

Love it!

30 Jul 2013 mathgirl

### mathgirl (view profile)

The function is amazing. It works fast and efficiently, and is very easy to use. The resulting stl has high resolution and reasonable size.

Thank you Sven!
Really appreciate your work.

31 Jul 2013 1.1

Set other-faces as opposite norm direction to input faces
Ensured optional per-node thickness input is accepted

15 Aug 2013 1.2

Added per-node elevation and thickness, minimal-flat-base file size, and default face orientation "out".

02 Dec 2013 1.3

Added ability to solidify self-enclosing surfaces without boundary edges

10 Feb 2014 1.5

Added optional normal direction input