简体   繁体   English

在 MATLAB 中细分 3D 表面

[英]Subdividing a 3D surface in MATLAB

I am using MATLAB to create some diagrams to explain my research and am stuck on the following problem.我正在使用 MATLAB 创建一些图表来解释我的研究,但遇到了以下问题。 I have created a half-ellipsoid rotated about the x-axis but I would like to demonstrate some internal structure within the ellipsoid which will be rotated around the x- and y-axes.我已经创建了一个绕 x 轴旋转的半椭球,但我想演示椭球内的一些内部结构,它将绕 x 轴和 y 轴旋转。 This is roughly shown in the figure below, where I have subdivided the ellipsoid into four parts (with my bad paint skill).这大致如下图所示,我将椭球细分为四个部分(用我糟糕的绘画技巧)。

在此处输入图片说明

How can I subdivide my ellipsoids into sections using planes of varying rotation about the x- and y-axes?如何使用围绕 x 轴和 y 轴的不同旋转平面将我的椭球细分为多个部分? I can create the ellipsoid and intersecting plane surfaces, but from there I don't know how to divide the ellipsoid up and change the face colours.我可以创建椭圆体和相交平面,但从那里我不知道如何划分椭圆体并改变面部颜色。

I have included some basic code below to get things started.我在下面包含了一些基本代码来开始工作。 I had thought I could just mask parts of the ellipsoid coordinates like I did to cut the ellipsoid in half, but this does not work.我原以为我可以像将椭圆体切成两半一样掩盖椭圆体坐标的一部分,但这不起作用。 I am guessing I need to make some kind of mesh grid,but I don't know how to combine the grid from the intersecting surface and the ellipsoid.我猜我需要制作某种网格,但我不知道如何将相交表面和椭圆体的网格组合起来。

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)

Any help is greatly appreciated,任何帮助是极大的赞赏,

This was an interesting question.这是一个有趣的问题。 So, here is a solution for 1) plotting three dimensional points inside the ellipse, bounded by the two planes, and 2) taking those points to form a smooth looking patch representation.因此,这里有一个解决方案,用于 1) 在椭圆内绘制三个以两个平面为边界的点,以及 2) 将这些点形成一个平滑的补丁表示。

My basic idea is to build a mesh that covers (as densely as required) the whole XYZ space of interest.我的基本想法是构建一个覆盖(根据需要尽可能密集)整个感兴趣的 XYZ 空间的网格。 What I then do is define the two planes in the parametric form ax+by+cz+d=0 .然后我要做的是以参数形式ax+by+cz+d=0定义两个平面 These are the planes between which the data is to be plotted.这些是要在其间绘制数据的平面。 Using the normal vector of the planes, with information about a point on each of the planes, I can deduce using the dot product whether each point in the XYZ grid is above or below the planes: if the dot product is less than zero, the point is above the plane, and if greater than zero, above the plane.使用平面的法向量,以及每个平面上的一个点的信息,我可以使用点积推断 XYZ 网格中的每个点是在平面上方还是下方:如果点积小于零,则点在平面上方,如果大于零,则在平面上方。

Using logical indexing I then find which points on the grid satisfy the conditions 1) above plane 1, 2) below plane 2, and 3) inside the ellipsoid and -- optionally -- 4) below Z=0 .使用 逻辑索引,我然后找到网格上的哪些点满足条件 1) 在平面 1 之上,2) 在平面 2 之下,和 3) 在椭球内和 -- 可选 -- 4) 在Z=0之下。

Finally, I plot the ellipsoid and the planes, along with the points that fulfil the criteria above.最后,我绘制了椭圆体和平面,以及满足上述标准的点。

In this case, I define two planes, but I guess you could do this for any number of them.在这种情况下,我定义了两个平面,但我想您可以为任意数量的平面执行此操作。 The code is quick and dirty, but hopefully will give you a way forward!代码又快又脏,但希望能给你一个前进的方向!

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

So, now we are ready to plot some data!所以,现在我们准备绘制一些数据! First up, let's try just plotting the grid to get a kind of discrete visualization with individual data points showing up:首先,让我们尝试绘制网格以获得一种显示单个数据点的离散可视化:

hold on;
plot3(V(aoi,1), V(aoi, 2), V(aoi, 3), 'r.')

...just to see it works, let's add the planes we defined earlier to the visualization. ...只是为了看看它是否有效,让我们将我们之前定义的平面添加到可视化中。 This is something you probably want to get rid of eventually.这是您最终可能想要摆脱的东西。

% 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');

Well, finally, if we want to show some smooth looking data, we can use alphaShape to extract a polyhedra from those data points we have.好吧,最后,如果我们想显示一些平滑的数据,我们可以使用alphaShape从我们拥有的这些数据点中提取多面体。 We can visualize the polyhedra as a patch object just by using plot .我们可以通过使用plot将多面体可视化为patch对象。 Finally, we can assign any color we want to each of the vertices in the patch, set a smooth change to the visualized color by setting the 'Facecolor' property, and remove the pesky vertex edges by setting 'EdgeColor' to 'none' :最后,我们可以为补丁中的每个顶点分配我们想要的任何颜色,通过设置'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

So that's it.就是这样了。 All that is left is to replace the vertex color values with whatever is appropriate for your data.剩下的就是用适合您的数据的任何值替换顶点颜色值。 Also, remember to skip the plot3 part earlier if you don't want those data points to show up in the display along the patch.此外,如果您不希望这些数据点沿着补丁显示在显示中,请记住提前跳过plot3部分。

Sample end result below, showing the two planes as well.下面的示例最终结果,也显示了两个平面。 最终结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM