在使用补丁的Matlab的3d圆环

时间:2014-12-27 14:48:53

标签: matlab

我想在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的不同组合,但仍无法找到解决方案。

2 个答案:

答案 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') ;

渲染: your patch

然后我创建了一个基本的横截面:

%% // 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)

呈现: the first cross section

现在我们只需要复制包裹在主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

现在,您在XYZ处有您定义的配置文件周围的点坐标,可以在一个图形对象中绘制:

%% // Plot the final surface
hs = surf(X,Y,Z) ;
set(hs,'FaceColor',[.7 .7 .7],'FaceAlpha',0.5,'EdgeAlpha',0.2)
view(155,26)

呈现: the full surface


关于这种方法的2个好处是:

  • 只能处理一个图形对象(但仍然是多功能的,CData允许多种可能性)
  • 横截面可以是 任何 ,只需定义一次,然后重复该方法。

为了说明上面的第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 ;

剩下的代码是一样的,你会得到你的甜甜圈: the doughnut

我还是把它包括在内,因为这是我的第一个答案,直到我从评论中意识到你想要一个气缸!

答案 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);

Cylinder