Changing from 2D plot to 3D plot and to STL file

5 visualizaciones (últimos 30 días)
Anh Phan Viet
Anh Phan Viet el 14 de Mzo. de 2020
Editada: DGM el 29 de Jun. de 2025
Hello everyone, I have these following codes: All of them creates a 2D plot, now I really want to create a 3D plot with Z: the thickness of plot XY. Then I want to convert it to STL file.
clc;
clear all;
close all;
% Input
R0 = 0.15;
a = 25*pi/180;
theta = 0:pi/1000:3*pi;
theta2 = theta + pi;
delta = pi/2;
%% Curl 1
R1 = R0*exp(a*(theta-delta));
X1 = R1.*cos(theta-delta);
Y1 = R1.*sin(theta-delta);
%% Curl 2
R2 = R0*exp(a*(theta-delta));
X2 = R2.*cos(theta);
Y2 = R2.*sin(theta);
%% Curl 3
R3 = R0*exp(a*(theta2-delta));
X3 = R1.*cos(theta2-delta);
Y3 = R1.*sin(theta2-delta);
%% Curl 4
R4 = R0*exp(a*(theta2 - delta));
X4 = R2.*cos(theta2);
Y4 = R2.*sin(theta2);
%% Extra plot (arc)
radius = R0*exp(a*(3*pi-pi/2));
a1 = pi/2;
b1 = pi;
h = 0;
k = 0;
t1 = linspace(a1,b1,3001);
X_arc1 = radius*cos(t1) + h;
Y_arc1 = radius*sin(t1) + k;
a2 = -pi/2;
b2 = 0;
t2 = linspace(a2,b2,3001);
X_arc2 = radius*cos(t2) + h;
Y_arc2 = radius*sin(t2) + k;
R5 = 0.05;
X5 = R5.*cos(theta);
Y5 = R5.*sin(theta);
%% Plot
figure(1);
plot(X1,Y1, 'k', 'LineWidth', 3); hold on
plot(X2,Y2, 'k', 'LineWidth', 3); hold on
P1 = plot(X_arc1, Y_arc1, 'k');
set(P1,'linewidth',3);
axis([h-radius-1 h+radius+1 k-radius-1 k+radius+1])
axis square; hold on;
plot(X3,Y3, 'k', 'LineWidth', 3);hold on
plot(X4,Y4, 'k', 'LineWidth', 3);hold on
plot(X5,Y5, 'k', 'LineWidth', 3); hold on
P2 = plot(X_arc2, Y_arc2, 'k');
set(P2,'linewidth',3);
axis('equal');
title('Two-arm equiangular spiral antenna', 'fontsize',14, 'fontweight','bold');
hold on
%% Filling with black color
patch([X1; flipud(X2)], [Y1; flipud(Y2)],'k');
patch([X3; flipud(X4)], [Y3; flipud(Y4)],'k');
X_arc1_bonus = horzcat(X_arc1, -4, -2.2, -2, -1, -0.3);
Y_arc1_bonus = horzcat(Y_arc1, 0.8, 2.2, 2.6, 3, 3.2);
fill(X_arc1_bonus, Y_arc1_bonus,'k');
X_arc2_bonus = horzcat(X_arc2, 4, 2.2, 2, 1, 0.3);
Y_arc2_bonus = horzcat(Y_arc2, -0.8, -2.2, -2.6, -3, -3.2);
fill(X_arc2_bonus, Y_arc2_bonus,'k');

Respuestas (2)

Deepak
Deepak el 2 de Dic. de 2024
To create a 3D plot with thickness by extruding 2D shapes into the third dimension, we can use "fill3" function in MATLAB.
Initially, the 2D shapes are defined by their X and Y coordinates. These shapes are then duplicated along the Z-axis to form both the bottom (Z = 0) and top (Z = thickness) surfaces, effectively giving them volume. The "fill3" function is used to plot these surfaces by specifying the X, Y, and Z coordinates for each shape. To complete the 3D model, side walls are created by connecting corresponding points on the top and bottom surfaces, forming vertical quadrilateral patches. This process results in a solid 3D object with defined thickness, visualized in a 3D space using plotting capabilities of MATLAB.
Below is a sample MATLAB to achieve the same:
% Input parameters
R0 = 0.15;
a = 25*pi/180;
theta = 0:pi/1000:3*pi;
theta2 = theta + pi;
delta = pi/2;
thickness = 0.05; % Thickness for the 3D extrusion
% Curl 1
R1 = R0*exp(a*(theta-delta));
X1 = R1.*cos(theta-delta);
Y1 = R1.*sin(theta-delta);
% Curl 2
R2 = R0*exp(a*(theta-delta));
X2 = R2.*cos(theta);
Y2 = R2.*sin(theta);
% Curl 3
R3 = R0*exp(a*(theta2-delta));
X3 = R1.*cos(theta2-delta);
Y3 = R1.*sin(theta2-delta);
% Curl 4
R4 = R0*exp(a*(theta2 - delta));
X4 = R2.*cos(theta2);
Y4 = R2.*sin(theta2);
% Extra plot (arc)
radius = R0*exp(a*(3*pi-pi/2));
a1 = pi/2;
b1 = pi;
h = 0;
k = 0;
t1 = linspace(a1,b1,3001);
X_arc1 = radius*cos(t1) + h;
Y_arc1 = radius*sin(t1) + k;
a2 = -pi/2;
b2 = 0;
t2 = linspace(a2,b2,3001);
X_arc2 = radius*cos(t2) + h;
Y_arc2 = radius*sin(t2) + k;
% Create a 3D plot with thickness
figure;
hold on;
% Extrude each 2D shape into 3D
fill3([X1; flipud(X2)], [Y1; flipud(Y2)], zeros(size([X1; flipud(X2)])), 'k');
fill3([X1; flipud(X2)], [Y1; flipud(Y2)], thickness * ones(size([X1; flipud(X2)])), 'k');
fill3([X3; flipud(X4)], [Y3; flipud(Y4)], zeros(size([X3; flipud(X4)])), 'k');
fill3([X3; flipud(X4)], [Y3; flipud(Y4)], thickness * ones(size([X3; flipud(X4)])), 'k');
% Extrude arcs
fill3(X_arc1, Y_arc1, zeros(size(X_arc1)), 'k');
fill3(X_arc1, Y_arc1, thickness * ones(size(X_arc1)), 'k');
fill3(X_arc2, Y_arc2, zeros(size(X_arc2)), 'k');
fill3(X_arc2, Y_arc2, thickness * ones(size(X_arc2)), 'k');
% Connect top and bottom faces to create side walls
for i = 1:length(X1)-1
fill3([X1(i), X1(i+1), X1(i+1), X1(i)], [Y1(i), Y1(i+1), Y1(i+1), Y1(i)], [0, 0, thickness, thickness], 'k');
end
% Repeat similarly for other parts...
axis equal;
view(3);
title('3D Model of Two-arm Equiangular Spiral Antenna');
Please find attached documentation of funcitons used for reference:
I hope this helps in resolving the issue.
  1 comentario
DGM
DGM el 29 de Jun. de 2025
Editada: DGM el 29 de Jun. de 2025
This doesn't actually work. To be more specific:
  • It doesn't fix the fill-boundary intersection mistake in the original code
  • It doesn't fix the detached feedpoint geometry
  • It doesn't fix the open boundary curves
  • Almost all patch objects are set up so that they have zero area
  • This doesn't get us any closer to creating a 2D triangulation, let alone solid geometry
OP was misconfiguring patch() such that instead of filling the given area, it roughly "painted" over the area with a zig-zag line. This does the exact same incorrect thing, but using 15000 patch objects instead of 11.
Here. I'm going to comment out a bunch of this, because there's no point in trying to extrude into 3D if none of the geometry works in 2D to begin with. I'm also reducing the resolution so that it's obvious what's going on.
% Input parameters
R0 = 0.15;
a = 25*pi/180;
theta = 0:pi/25:3*pi; % stop trying to paint with lines
theta2 = theta + pi;
delta = pi/2;
thickness = 0.05; % Thickness for the 3D extrusion
% Curl 1
R1 = R0*exp(a*(theta-delta));
X1 = R1.*cos(theta-delta);
Y1 = R1.*sin(theta-delta);
% Curl 2
R2 = R0*exp(a*(theta-delta));
X2 = R2.*cos(theta);
Y2 = R2.*sin(theta);
% Curl 3
R3 = R0*exp(a*(theta2-delta));
X3 = R1.*cos(theta2-delta);
Y3 = R1.*sin(theta2-delta);
% Curl 4
R4 = R0*exp(a*(theta2 - delta));
X4 = R2.*cos(theta2);
Y4 = R2.*sin(theta2);
% Extra plot (arc)
radius = R0*exp(a*(3*pi-pi/2));
a1 = pi/2;
b1 = pi;
h = 0;
k = 0;
t1 = linspace(a1,b1,3001);
X_arc1 = radius*cos(t1) + h;
Y_arc1 = radius*sin(t1) + k;
a2 = -pi/2;
b2 = 0;
t2 = linspace(a2,b2,3001);
X_arc2 = radius*cos(t2) + h;
Y_arc2 = radius*sin(t2) + k;
% Create a 3D plot with thickness
%figure;
hold on;
% Extrude each 2D shape into 3D
fill3([X1; flipud(X2)], [Y1; flipud(Y2)], zeros(size([X1; flipud(X2)])), 'k');
%fill3([X1; flipud(X2)], [Y1; flipud(Y2)], thickness * ones(size([X1; flipud(X2)])), 'k');
fill3([X3; flipud(X4)], [Y3; flipud(Y4)], zeros(size([X3; flipud(X4)])), 'k');
%fill3([X3; flipud(X4)], [Y3; flipud(Y4)], thickness * ones(size([X3; flipud(X4)])), 'k');
% Extrude arcs
fill3(X_arc1, Y_arc1, zeros(size(X_arc1)), 'k');
%fill3(X_arc1, Y_arc1, thickness * ones(size(X_arc1)), 'k');
fill3(X_arc2, Y_arc2, zeros(size(X_arc2)), 'k');
%fill3(X_arc2, Y_arc2, thickness * ones(size(X_arc2)), 'k');
% Connect top and bottom faces to create side walls
% for i = 1:length(X1)-1
% fill3([X1(i), X1(i+1), X1(i+1), X1(i)], [Y1(i), Y1(i+1), Y1(i+1), Y1(i)], [0, 0, thickness, thickness], 'k');
% end
% Repeat similarly for other parts...
% now show where the actual boundaries are
% these are the only boundaries being drawn
plot(X1,Y1,'y','linewidth',2);
plot(X2,Y2,'y','linewidth',2);
axis equal;
%view(3);
title('3D Model of Two-arm Equiangular Spiral Antenna');
hfn = copyfig(gcf); % from the FEX
axis([-0.5 0.5 -0.5 0.5])
title('same thing, but zoomed in');
The patch objects created in order to "fill" the shape have no area because of the way they're set up, but we don't need to fix that. Note that they cross the shape's perimeter on its concave side. I imagine the intent was originally to zipper-triangulate the area (or the same with quads), but simple periodic fill like that isn't generally going to work for non-convex shapes. This is what tends to happen instead.
The arms of the shape are not filled, closed, or connected to each other. Out of 15008 patch objects, only 4 are not degenerate.

Iniciar sesión para comentar.


DGM
DGM el 29 de Jun. de 2025
Editada: DGM el 29 de Jun. de 2025
Oof. I spent way too much time on trying to get the triangulation to work on this, especially considering that nobody needs it anyway. Oh well. Here goes.
I'm ignoring the [h k] offset since it's not used consistently. It can't be set to anything other than [0 0] without breaking everything. If you want to shift the part, do that on the final vertex data.
It's not clear whether X5,Y5 is a hole (e.g. a via) or part of the solid. It's not connected to anything, and the arm boundary isn't closed either. The misuse of theta for this curve also means it's overdefined (it's self-overlapping). I'm going to assume it's a via and needs a pad defined around it. Did I guess wrong? I don't care. I'm just going to slap some arcs on there to create a pad. Depending on the parameters, the acute part of the boundary at the root won't be practically achievable by either etching or milling. I'm not going to fix that either.
We need to define a closed boundary curve (or set of closed curves if there are holes). We don't have that. Scribbling a zig-zag line over the plot doesn't fill the area. Making the line thicker doesn't change anything. Notice that it actually intersects with the boundary curve near the extreme ends of the arms. I doubt that's correct either. Define a closed boundary curve and do a constrained triangulation.
In order for the triangulation to work, we need to come up with the boundary constraints (an edge list). We shouldn't have any duplicate points in the list. That's a bit of a complication. We can't just generate the arcs, concatenate them, and then use unique(V,'rows') to get rid of the duplicate points that are created where the arcs meet. The fact that the arcs are calculated independently means that floating point error keeps the points from being exactly equal. We can either use uniquetol() or something else. I opted to just generate each arc in the appropriate direction, such that the last point is excluded. That way they can be simply concatenated.
% parameters
npl = 200; % resolution of large arcs
nps = 20; % resolution of small arcs
r0 = 0.15; % basis of the root radius
rvia = 0.05; % radius of feedpoint via
a = 25*pi/180;
delta = pi/2; % arm width
thswing = 3*pi; % how far the arms rotate
thickness = 0.2; % not realistic, but easier to see
% arm side (outward)
theta = linsegment(0,thswing,npl).';
Rb = r0*exp(a*(theta-delta));
X1 = Rb.*cos(theta-delta);
Y1 = Rb.*sin(theta-delta);
% outer closure arc (ccw)
th0 = mod(thswing,2*pi);
th = linsegment(th0 - delta,th0,npl/2).';
rmax = r0*exp(a*(thswing-delta));
Xc = rmax*cos(th);
Yc = rmax*sin(th);
% arm side (inward)
theta = linsegment(thswing,0,npl).';
Rb = r0*exp(a*(theta-delta));
X2 = Rb.*cos(theta);
Y2 = Rb.*sin(theta);
% pad closure arc (ccw)
th = linsegment(0,pi-delta,nps/2).';
rpad = r0*exp(a*(-delta));
X4 = rpad*cos(th); % pad
Y4 = rpad*sin(th);
% feedpoint via
th = linsegment(0,2*pi,nps).';
Xv = rvia.*cos(th); % via
Yv = rvia.*sin(th);
% assemble the outer boundary
V = [X1 Y1;
Xc Yc;
X2 Y2;
X4 Y4];
V = [V; -V]; % a rotated copy
% assemble all boundaries into a cell array
% we'll need this to generate the edge list
% for the constrained triangulation
% X3,Y3 need to be flipped, since it's a hole
Vc = [{V}; {flipud([Xv Yv])}];
% consolidate the complete vertex list (referenced by E)
V = cell2mat(Vc);
% plot the boundary curve
plot(V(:,1),V(:,2), 'k')
axis([-rmax-1 rmax+1 -rmax-1 rmax+1])
axis equal; hold on;
title('Two-arm equiangular spiral antenna', 'fontsize',14, 'fontweight','bold')
% construct the edge lists in the same direction
% the vertex lists in Vc don't need to be the same length
sz = cellfun(@(x) size(x,1),Vc); % length of each vertex list
szc = [0; cumsum(sz)];
E = zeros(0,2);
for k = 1:numel(Vc)
v = 1+szc(k):szc(k+1);
thisE = [v; circshift(v,-1)].';
E = [E; thisE]; %#ok<AGROW>
end
% TRIANGULATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% do a constrained triangulation to generate the triangles
T = delaunayTriangulation(V,E);
F = T.ConnectivityList(isInterior(T),:);
V = T.Points;
% or better yet, use mesh2D (FEX #25555)
%[V,~,F,~] = refine2(V,E);
% plot the triangulated area
figure
patch('faces',F,'vertices',V, ...
'facecolor','w','edgecolor','k');
axis equal; grid on
% EXTRUSION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% extrude the part into 3D
[F V] = extrude(F,V,thickness);
% write to file
stlwrite(triangulation(F,V),'testfile.stl')
% display it using patch()
figure
patch('faces',F,'vertices',V, ...
'facecolor','w','edgecolor','none');
view(3); camlight; view(10,33)
axis equal; grid on
xlabel('X'); ylabel('Y'); zlabel('Z')
As the comment suggests, if the goal is to use this for FEA, then this triangulation probably won't be great unless you have a way to retriangulate it. If you use refine2() instead, you'll get something that might be more useful. This is with the default parameters, but it has many options.
See also:

Categorías

Más información sobre Volume Visualization en Help Center y File Exchange.

Etiquetas

Community Treasure Hunt

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

Start Hunting!

Translated by