Can't write isosurface to stl file
3 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Sarinya
el 14 de Oct. de 2023
I've created an isosurface of a TPMS structure (Primitive, to be exact), but I'm having trouble writing it to an STL file. I've followed the example in this documentation practically to the letter:
extractIsosurface
However I keep running into two problems: First of all, trimesh(T) comes out looking like this:

And I can't figure out how to remove the lines. Second of all, I keep getting the error:
Error using fileparts
Input must be a row vector of characters, or a string scalar, or a cellstr, or a string matrix.
path = fileparts(filename);
Even though I used the exact same input format as the example. Am I missing something super obvious? Please help, my professor will rip my head off if I can't get this.
This is my code by the way
%% Input Parameters
unitcellsize = 5; % Cell size [mm]
length_x = 15; % Samplesize in x direction [mm]
length_y = 15; % Samplesize in y direction [mm]
length_z = 15; % Samplesize in z direction [mm]
step = 0.1; % To control the resolution [the smaller the better]
isovalue = 0.1;
%% Lactice Equation
syms x y z
f = @(x,y,z) cos((2.*pi.*x)./unitcellsize) + cos((2.*pi.*y)./unitcellsize) + cos((2.*pi.*z)./unitcellsize);
% ------------------ Sample Size -------------------
a = -length_x/2:step:length_x/2;
b = -length_y/2:step:length_y/2;
c = -length_z/2:step:length_z/2;
[X,Y,Z] = meshgrid(a,b,c);
%% Getting Coordinates
V = f(X,Y,Z);
co = isosurface(a,b,c,V,isovalue);
[faces1,verts1] = extractIsosurface(V,isovalue);
%% Gradient Plot
hold on
p = patch(co1);
isonormals(X,Y,Z,V,p)
view(3)
daspect([1 1 1])
colorbar
axis tight
camlight
lighting gouraud
box on
T = triangulation(double(faces1),double(verts1));
figure
trimesh(T)
%Export surface to .stl
stlwrite(T,'test.stl');
0 comentarios
Respuesta aceptada
Dyuman Joshi
el 14 de Oct. de 2023
Editada: Dyuman Joshi
el 14 de Oct. de 2023
I am not familiar with the extractIsosurface function or the Medical Imaging Toolbox the function is part of, so I can not provide any suggestions to make your method work.
However, I can offer a workaround method. Use this file from the FEX - stlwrite. I have renamed the function to stl_write() to not overload the built-in stlwrite() function, and so should you.
I have executed the code with the FEX submission and removed the file. (Copyrighted material
%% Input Parameters
unitcellsize = 5; % Cell size [mm]
length_x = 15; % Samplesize in x direction [mm]
length_y = 15; % Samplesize in y direction [mm]
length_z = 15; % Samplesize in z direction [mm]
step = 0.1; % To control the resolution [the smaller the better]
isovalue = 0.1;
%% Lactice Equation
%% This line is not needed
% syms x y z
f = @(x,y,z) cos((2.*pi.*x)./unitcellsize) + cos((2.*pi.*y)./unitcellsize) + cos((2.*pi.*z)./unitcellsize);
% ------------------ Sample Size -------------------
a = -length_x/2:step:length_x/2;
b = -length_y/2:step:length_y/2;
c = -length_z/2:step:length_z/2;
[X,Y,Z] = meshgrid(a,b,c);
%% Getting Coordinates
V = f(X,Y,Z);
co = isosurface(a,b,c,V,isovalue);
%Write the data to stl file
stl_write('test.stl', co);
%Read the stl file to visualize the output
TO = stlread('test.stl');
trimesh(TO)
1 comentario
DGM
el 26 de Jun. de 2025
Editada: DGM
el 26 de Jun. de 2025
I think the core lesson is that extractIsosurface() was simply unnecessary. The user already had the isosurface data from the prior call to isosurface(). They just needed to use it as you showed.
FEX #20922 is often convenient, as it accepts inputs formatted in different ways, but it's not strictly needed. When using isosurface(), the outputs can either be a FV struct (co in the given example), or individual F and V lists. While #20922 can accept either directly, the built-in stlwrite() needs a triangulation object. If we wanted to stick with base tools, we can create a triangulation object as needed.
% Input Parameters
unitcellsize = 5; % Cell size [mm]
length_x = 15; % Samplesize in x direction [mm]
length_y = 15; % Samplesize in y direction [mm]
length_z = 15; % Samplesize in z direction [mm]
resolution = 100; % To control the resolution
isovalue = 0.1;
% Lactice Equation
f = @(x,y,z) cos((2.*pi.*x)./unitcellsize) ...
+ cos((2.*pi.*y)./unitcellsize) ...
+ cos((2.*pi.*z)./unitcellsize);
% Mesh setup
a = linspace(-length_x/2,length_x/2,resolution);
b = linspace(-length_y/2,length_y/2,resolution);
c = linspace(-length_z/2,length_z/2,resolution);
[X,Y,Z] = meshgrid(a,b,c);
% Getting Coordinates
v = f(X,Y,Z);
[F,V] = isosurface(a,b,c,v,isovalue); % returns either an FV struct or F,V lists
%Write the data to stl file
T = triangulation(F,V); % convert F,V to a triangulation object
stlwrite(T,'test.stl');
%Read the stl file to visualize the output
T0 = stlread('test.stl');
patch('faces',T0.ConnectivityList,'vertices',T0.Points,'facecolor','m','edgecolor','none');
view(3); camlight; view(75,44);
axis equal; grid on
xlabel('X'); ylabel('Y'); zlabel('Z')
Two other notes:
I changed the grid generation to avoid the use of stepsize and the colon operator. Parameterizing things using a fixed step size instead of a decimation factor means that the user needs to always pick both an interval and step size such that the given interval is integer-divisible by the step size. Otherwise, the model will end up being lopsided due to truncation.
Second, note that while we have the STL, it's a surface of zero thickness, not a solid volume. Whether that's appropriate depends what we need to do with it.
Más respuestas (0)
Ver también
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!