我想在matlab中制作一个3d环。以下是类似于我的观点:
t = linspace(0,2*pi);
rin = 0.1;
rout = 0.25;
xin = 0.5 + rin*cos(t);% 0.5 is the center of the ring
xout = 0.5 + rout*cos(t);
yin = 0.5 + rin*sin(t);
yout = 0.5 + rout*sin(t);
% Make patch
hp = patch([xout,xin],[yout,yin],'g','linestyle','none','facealpha',0.25);
现在,我想将此扩展到3d案例。我想给这个戒指增加高度。但是当我尝试添加向量[z1,z2]
时
z1=0.5*ones(size(xin));
z2=z1;
我尝试过Z1和Z2的不同组合,但仍无法找到解决方案。
答案 0 :(得分:5)
我倾向于将patch
用于对象的2D表面,这些表面是真正刻面的,如果你需要控制每个面的属性,否则对于你想要的卷surf
来说很多更容易处理的对象。
下面的示例显示了如何使用一个surface
进行此操作,但如果您确实需要使用patch
,则可轻松进行调整。
要逐步解释,我先从您创建的补丁开始。我计算中心线的坐标(在代码中称为ring
),然后显示它(突出显示起点)
%% // Ring properties
ring.x0 = 0.5 ; %// Center of ring
ring.y0 = 0.5 ; %// Center of ring
ring.radius = (0.25+0.1)/2 ; %// Radius of core circle profile
ring.nDiv = 37 ; %// number of divisions for the core circle profile
ring.theta = linspace(0,2*pi,ring.nDiv) ;
ring.X = cos(ring.theta) * ring.radius + ring.x0 ;
ring.Y = sin(ring.theta) * ring.radius + ring.y0 ;
%// plot (optional, just for intermediate visualisation)
hold on ; plot(ring.X,ring.Y) ; plot(ring.X(1),ring.Y(1),'ok')
view(18,72) ; xlabel('X') ; ylabel('Y') ; zlabel('Z') ;
渲染:
然后我创建了一个基本的横截面:
%% // Create a base SQUARE cross section
Npts = 4 ;
cs.width = 0.25-0.1 ; %// width of each cross section square
cs.height = 0.25 ; %// height of each cross section square
%// first cross section is the the XZ plane
csY0 = zeros(1,Npts) ; %// will be used as base for rotating cross sections
csX = [-cs.width/2 cs.width/2 cs.width/2 -cs.width/2 ] ;
csZ = [-cs.height/2 -cs.height/2 cs.height/2 cs.height/2] ;
这定义了一个悬挂在原点周围空间的基本方形,我将第一个方位置放在原位,只是为了说明:
%% // plot (optional, just for intermediate visualisation)
hp0 = patch(csX+ring.X(1),csY0+ring.Y(1),csZ,'r','FaceAlpha',0.5) ;
view(164,38)
呈现:
现在我们只需要复制包裹在主ring
周围的横截面:
%% Generate coordinates for each cross section and merge them
nCS = length(ring.X) ; %// number of cross sections composing the surface
%// pre-allocation is always good
X = zeros( nCS , Npts ) ;
Y = zeros( nCS , Npts ) ;
Z = zeros( nCS , Npts ) ;
for ip = 1:nCS
%// rotate the cross section (around Z axis, around origin)
Rmat = [ cos(ring.theta(ip)) -sin(ring.theta(ip)) ; ...
sin(ring.theta(ip)) cos(ring.theta(ip)) ] ;
csTemp = Rmat * [csX ; csY0] ;
%// translate the coordinates of cross section to final position and store with others
X(ip,:) = csTemp(1,:) + ring.X(ip) ;
Y(ip,:) = csTemp(2,:) + ring.Y(ip) ;
Z(ip,:) = csZ ;
end
现在,您在X
,Y
和Z
处有您定义的配置文件周围的点坐标,可以在一个图形对象中绘制:
%% // Plot the final surface
hs = surf(X,Y,Z) ;
set(hs,'FaceColor',[.7 .7 .7],'FaceAlpha',0.5,'EdgeAlpha',0.2)
view(155,26)
呈现:
关于这种方法的2个好处是:
为了说明上面的第2点,只需用这个圆形横截面替换代码段%% // Create a base square cross section
:
%% // Create a base CIRCULAR cross section
cs.Ndiv = 13 ; %
cs.radius = (0.25-0.1)/2 ; %// Radius of each cross section circle
cs.rout = 0.25;
cs.theta = linspace(0,2*pi,cs.Ndiv) ;
Npts = length(cs.theta) ;
%// first cross section is the the XZ plane
csY0 = zeros(1,Npts) ; %// will be used as base for rotating cross sections
csX = sin(cs.theta) * cs.radius ;
csZ = cos(cs.theta) * cs.radius ;
剩下的代码是一样的,你会得到你的甜甜圈:
我还是把它包括在内,因为这是我的第一个答案,直到我从评论中意识到你想要一个气缸!
答案 1 :(得分:4)
复制你的环并增加两个气缸我得到:
%% Config
t = linspace(0,2*pi);
rin = 0.1;
rout = 0.25;
center = [1, 0.5];
xin = rin*cos(t);
xout = rout*cos(t);
yin = rin*sin(t);
yout = rout*sin(t);
z1 = 0;
z2 = 0.24;
%% Plot
clf;
hold on;
bottom = patch(center(1)+[xout,xin], ...
center(2)+[yout,yin], ...
z1*ones(1,2*length(xout)),'');
top = patch(center(1)+[xout,xin], ...
center(2)+[yout,yin], ...
z2*ones(1,2*length(xout)),'');
[X,Y,Z] = cylinder(1,length(xin));
outer = surf(rout*X+center(1), ...
rout*Y+center(2), ...
Z*(z2-z1)+z1);
inner = surf(rin*X+center(1), ...
rin*Y+center(2), ...
Z*(z2-z1)+z1);
set([bottom, top, outer, inner], ...
'FaceColor', [0 1 0], ...
'FaceAlpha', 0.99, ...
'linestyle', 'none', ...
'SpecularStrength', 0.7);
light('Position',[1 3 2]);
light('Position',[-3 -1 3]);
axis vis3d; axis equal; view(3);