我正在使用MATLAB创建一些图表来解释我的研究,并坚持以下问题。我已经创建了一个围绕x轴旋转的半椭圆体,但我想展示椭圆体内的一些内部结构,它将围绕x轴和y轴旋转。这大致如下图所示,我将椭圆体细分为四个部分(我的画笔技能不好)。
如何使用围绕x轴和y轴的不同旋转平面将椭球细分为多个部分?我可以创建椭球和相交的平面,但从那里我不知道如何划分椭圆并改变面颜色。
我已经在下面添加了一些基本代码来开始工作。我原本以为我可以掩盖部分椭圆体坐标,就像我将椭圆体切成两半一样,但这不起作用。我猜我需要制作某种网格,但我不知道如何组合交叉曲面和椭球的网格。
figure
x = 0; y = 0; z = 0;
tl = 10; tw = 4; td = 2;
% Create ellipsoid
[ex,ey,ez] = ellipsoid(x, y, z, tl, tw, td,40);
ex = ex(1:ceil(length(ez)/2),:); % Remove top half
ey = ey(1:ceil(length(ez)/2),:); % of ellipsoid
ez = ez(1:ceil(length(ez)/2),:);
% Make some planes
[ySL,zSL] = meshgrid([-10:10],[-2:0.2:2]);
xSL1 = zeros(size(ySL, 1)); % Generate z data
hSL1 = surf(xSL1,ySL,zSL);
hold on
[ySL,zSL] = meshgrid([-10:10],[-3:0.2:1]);
xSL2 = ones(size(ySL, 1)); % Generate z data
hSL2 = surf(xSL2,ySL,zSL);
% rotate(hSL,[1 0 0],5);
rotate([hSL1 hSL2],[0 1 0],-70);
hSurf1 = surf(ex,ey,ez);
set([hSurf1 hSL1 hSL2],'facecolor','blue','facealpha',.2,...
'edgecolor','none')
% Plot settings
daspect([1 1 0.3]);
hold off
view(-10,6)
非常感谢任何帮助,
答案 0 :(得分:1)
这是一个有趣的问题。因此,这里有一个解决方案:1)绘制椭圆内部的三维点,由两个平面限定,以及2)将这些点绘制成平滑的补丁表示。
我的基本想法是构建一个网格,覆盖整个X-Y-Z空间(尽可能密集)。然后我做的是在参数形式ax+by+cz+d=0
中定义两个planes。这些是绘制数据的平面。使用平面的法向矢量,以及每个平面上的点的信息,我可以使用点积来推断XYZ网格中的每个点是在平面之上还是之下:如果点积小于零,则点在平面上方,如果大于零,则在平面上方。
使用logical indexing然后我找到网格上的哪些点满足条件1)在平面1,2下方的平面2,以及3)椭球内部和 - 可选 - 4){{1 }}
最后,我绘制了椭圆体和平面,以及符合上述标准的点。
在这种情况下,我定义了两个平面,但我想你可以为任意数量的平面做这个。代码快速而且肮脏,但希望能为您提供前进的方法!
Z=0
所以,现在我们准备绘制一些数据了!首先,让我们尝试绘制网格以获得一种离散的可视化,其中显示了各个数据点:
% Define the ellipse
x = 0; y = 0; z = 0;
tl = 10; tw = 4; td = 2;
% Create ellipsoid
[ex,ey,ez] = ellipsoid(x, y, z, tl, tw, td,40);
ex = ex(1:ceil(length(ez)/2),:); % Remove top half
ey = ey(1:ceil(length(ez)/2),:); % of ellipsoid
ez = ez(1:ceil(length(ez)/2),:);
% Define a 3D grid over area of interest
xx = linspace(min(ex(:)),max(ex(:)),50);
yy = linspace(min(ey(:)),max(ey(:)),50);
zz = linspace(min(ez(:)),max(ez(:)),50);
[X, Y, Z] = meshgrid(xx, yy, zz);
V = [X(:) Y(:) Z(:)]; % rearrange
% Define two planes (ax + bx + cz + d = 0)
a = [0; 0];
b = [-1; 1];
c = [-1; 1];
d = [-1; -1];
% Normal vectors of the planes
n = [a b c];
n(1,:) = n(1,:) / norm(n(1,:));
n(2,:) = n(2,:) / norm(n(2,:));
% Find a point (0,0,z) on each plane
zp = [zeros(2) (d- a * 0 - b * 0)./c];
% Define the area of interest.
% Dot product to test if grid points are below or above the planes
% We want: above plane 1, below plane 2.
V1 = sum(bsxfun(@times, bsxfun(@minus, V, -zp(1,:)), n(1,:)),2);
V2 = sum(bsxfun(@times, bsxfun(@minus, V, -zp(2,:)), n(2,:)),2);
between_planes = (V1 < 0) & (V2 < 0);
% ...and the points have to be inside the ellipsoid
in_ellipse = ((X(:) - x)/tl).^2 + ((Y(:)-y)/tw).^2 + ((Z(:)-z)/td).^2 < 1;
% Final AOI
aoi = between_planes & in_ellipse;
% Add this if you want to also have only values with Z < 0
aoi = aoi & (V(:,3) < 0);
figure;
surf(ex, ey, ez, 'facecolor','blue','facealpha',.2,...
'edgecolor','none')
...只是为了看它的工作原理,让我们将之前定义的平面添加到可视化中。这可能是你最终想要摆脱的。
hold on;
plot3(V(aoi,1), V(aoi, 2), V(aoi, 3), 'r.')
好吧,最后,如果我们想要显示一些平滑的数据,我们可以使用alphaShape
从我们拥有的那些数据点中提取多面体。我们可以使用% Draw the planes
[X,Y] = meshgrid(xx,yy);
Z = cell(2,1);
clr = {'r', 'g'};
for k = 1:2
Z{k} = (a(k) * X + b(k) * Y + d(k))/ (-c(k));
hs(k) = surf(xx, yy, Z{k},'facecolor',clr{k}, 'facealpha',.2, 'edgecolor','none');
drawnow;
end
view([-115 10])
legend(hs, 'Plane 1 (above)', 'Plane 2 (below');
将多面体可视化为patch
对象。最后,我们可以为贴片中的每个顶点指定我们想要的任何颜色,通过设置plot
属性设置对可视化颜色的平滑更改,并通过将'Facecolor'
设置为删除令人讨厌的顶点边缘'EdgeColor'
:
'none'
这就是它。剩下的就是用适合您数据的任何内容替换顶点颜色值。此外,如果您不希望这些数据点显示在修补程序的显示中,请记得先跳过% Moving on to smooth representation...
shp = alphaShape(V(aoi,1), V(aoi, 2), V(aoi, 3),1);
hs = plot(shp);
% Create a colormap to use for the patch (color of each vertex)
cmap = jet(size(hs.Vertices,1));
set(hs, 'FaceVertexCData', cmap);
set(hs, 'FaceColor', 'interp'); % smooth interp coloring
set(hs, 'EdgeColor', 'none'); % Remove ugly edges
部分。