Convert multiple 3D shapes into stl file (CAD).

6 views (last 30 days)
Karl Yau
Karl Yau on 24 Jul 2018
Commented: DGM on 17 Jul 2025
So the following script produces several randomly placed spheres and attempts to convert it into an stl file. At the moment, only one sphere is saved in the file. Is there a way to convert all the spheres produced into a single CAD file?
if true
for i = 1:100
[x,y,z] = sphere;
r = 1;
a = (-7.5 + (7.5+7.5).*rand(1)); % x,y,z coords randomly generated between axis
b = (-50 + (50+50).*rand(1));
c = (-7.5 + (7.5+7.5).*rand(1));
x1 = (r*x)+a; % change sphere radius and coordinate
y1 = (r*y)+b;
z1 = (r*z)+c;
surf(x1,y1,z1)
hold on
end
box on
xlim([-7.5 7.5])
ylim([-50 50])
zlim([-7.5 7.5])
axis equal
surf2stl('test.stl',x2,y2,z2);
end

Answers (1)

DGM
DGM on 3 Apr 2025
Edited: DGM on 3 Apr 2025
The given code has two obvious problems. For one, the xyz data is being discarded for every loop iteration, so only the last set is left once the loop exits. The second is that the code is writing x2,y2,z2, which do not exist (within the scope of the given code).
The easiest way to fix this is to triangulate the data in the loop and just accumulate all of it. It could be done in a roundabout way using surf2stl(), but mesh2tri() was available, and can output the F,V data directly.
% we're going to need arrays for storing face/vertex data
% if we know the mesh sizes, we could preallocate the required array sizes
% but i'm going to assume that we don't necessarily know that.
F = [];
V = [];
for i = 1:10
[x,y,z] = sphere;
r = 1;
a = (-7.5 + (7.5+7.5).*rand(1)); % x,y,z coords randomly generated between axis
b = (-50 + (50+50).*rand(1));
c = (-7.5 + (7.5+7.5).*rand(1));
x1 = (r*x)+a; % change sphere radius and coordinate
y1 = (r*y)+b;
z1 = (r*z)+c;
surf(x1,y1,z1)
hold on
% triangulate the gridded data and collect the F,V data
% the indices in F need to be offset, since we're changing the size of V
[thisF,thisV] = mesh2tri(x1,y1,z1,'f'); % available on the FEX circa 2010
F = [F; thisF+size(V,1)]; %#ok<*AGROW>
V = [V; thisV];
end
box on
xlim([-7.5 7.5])
ylim([-50 50])
zlim([-7.5 7.5])
axis equal
% before stlwrite() was in the base toolbox (R2018b),
% Sven Holcombe's tools were on the File Exchange
fname = 'test.stl';
%stlwrite(triangulation(F,V),fname) % R2018b+
stlWrite(fname,F,V) % on the FEX
% read the STL back and see what's inside
% T = stlread(fname); % R2018b+
% F = T.ConnectivityList;
% V = T.Points;
[V F] = stlRead(fname); % also on the FEX
% display it using patch()
figure
patch('faces',F,'vertices',V,'facecolor','w','edgecolor','none');
view(3); camlight
axis equal; grid on
xlabel('X'); ylabel('Y'); zlabel('Z')
Bear in mind that this does not do any CSG (i.e. a union of the surfaces). As a result, if spheres intersect, there will be no new vertices or edges created on their intersection curve, and the resulting object will have interior faces.
The tools I used:
The STL IO tools were only used here to be period-correct. In current versions, they aren't strictly necessary. Examples are included based on stlread() and stlwrite() which are now in the base toolbox.

Community Treasure Hunt

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

Start Hunting!