Can't write isosurface to stl file
3 ビュー (過去 30 日間)
古いコメントを表示
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 件のコメント
採用された回答
Dyuman Joshi
2023 年 10 月 14 日
編集済み: Dyuman Joshi
2023 年 10 月 14 日
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 件のコメント
DGM
2025 年 6 月 26 日
編集済み: DGM
2025 年 6 月 26 日
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.
その他の回答 (0 件)
参考
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!