简体   繁体   中英

MATLAB - 3D surface plot

I have 20 data points in 3D space. Here you can see them plotted:

clear all
close all
clc

Data = [97.4993     104.3297    0.7500  196.7021
        100.0000    105.0000    0.7500  290.9164
        100.0000    107.5000    0.7500  142.1626
        96.2569     106.4992    0.7500  143.3605
        97.5028     104.3317    1.0000  197.1111
        100.0000    105.0000    1.0000  290.4210
        100.0000    107.5000    1.0000  144.0155
        96.2530     106.4969    1.0000  144.0969
        98.7055     104.8295    0.7500  239.7734
        100.0000    106.2500    0.7500  214.6557
        98.0627     107.2455    0.7500  145.4154
        96.8781     105.4144    0.7500  161.7000
        97.5010     104.3307    0.8750  196.8880
        100.0000    105.0000    0.8750  290.6686
        100.0000    107.5000    0.8750  141.5008
        96.2549     106.4980    0.8750  144.0253
        98.7075     104.8300    1.0000  239.3455
        100.0000    106.2500    1.0000  215.2104
        98.0605     107.2449    1.0000  144.9653
        96.8779     105.4143    1.0000  161.4253];

x = Data(:,1); % x coordinates 
y = Data(:,2); % y coordinates 
z = Data(:,3); % z coordinates 
sigma = Data(:,4); % stress value at that point

for ii = 1:length(x)

    plot3(x(ii,1),y(ii,1),z(ii,1),'r*')
    hold on
    grid on
    text(x(ii,1),y(ii,1),z(ii,1),['   ' num2str(ii) '   '...
        num2str(sigma(ii))],'HorizontalAlignment','left','FontSize',12); 

end

This data represents one HEX20 element (FEM) and its 20 nodes. Each node has its Stress value (sigma) written next to it. The numbering of the nodes follows the standard procedure:

HEX20元素

I would like to plot the surfaces of that element like it is shown in the picture. Then (if possible) I would like the surfaces to be coloured based on the stress value of the nodes (colour mapping). The end result should be something like this:

在此处输入图片说明

You essentially want to turn your data into a mesh object. The x,y,z coordinates make up the Vertices or points, and you can define Faces through joining up Vertices , and then can set a single point or Vertex to have a specific colour value (in your case the stress value). To draw a mesh with vertices and faces , you can use the patch method.

The hard part here is you have vertices, but not faces. One quick method to try would be convhull which returns the convex hull of a set of points (think shrink-wrapping the points to give a surface).

So start with:

patch('Vertices',[x y z],'Faces',convhull(x,y,z),'FaceVertexCData',sigma,'FaceColor','interp');

See how that goes, and if it isn't quite what you were looking for then you could change the faces . In the line of code above, faces = convhull(x,y,z) . You could already know which vertices make up your faces, eg Face1 could be Point 2, 14, and 9 - faces(1,:) = [2,14,9] .

Also, if you wanted faces made of four points instead of triangular, your faces array would simply be N-by-4 instead of N-by-3.

Quick example result from the code you gave and the patch code above:

您提供的代码的快速示例

http://uk.mathworks.com/help/matlab/visualize/multifaceted-patches.html http://uk.mathworks.com/help/matlab/ref/convhull.html

Here's another way of building patches. You specify a structure with the points (vertices), then the faces (which points do they include), then a vector of color (your sigma values), then you send the lot to the patch function which will take care of the rest.

Then you finalise the details (transparency, edge color, plot your points and text etc ...)

fv.vertices = Data(:,1:3);
fv.faces = [...
    1  9 2 10 3 11 4 12 ;
    1  9 2 14 6 17 5 13 ;
    5 17 6 18 7 19 8 20 ;
    2 10 3 15 7 18 6 14 ;
    3 11 4 16 8 19 7 15 ;
    4 12 1 13 5 20 8 16 ...
    ] ;
fv.facevertexcdata = Data(:,4);

hold on
hp  = patch(fv,'CDataMapping','scaled','EdgeColor',[.7 .7 .7],'FaceColor','interp','FaceAlpha',1)    
hp3 = plot3(x,y,z,'ok','Markersize',6,'MarkerFaceColor','r')

for ii = 1:length(x)
    text(x(ii,1),y(ii,1),z(ii,1),{sprintf('   #%d - \\sigma:%4.1f',ii,sigma(ii))},...
        'HorizontalAlignment','left','FontSize',8,'FontWeight','bold'); 
end
view(-27,26)
axis equal
axis off
colorbar south

Will produces:

m

Edit: It is slightly more tedious than asking convhull to find the envelope, but it has the merit of respecting the actual shape of your element (not closing the inward small volume near nodes 9 & 17).


To avoid the graphic rendering glitch when the patch faces are not perfectly planar, you can define the faces so they will all be perfectly planar. It means defining more faces (we have to split all of them in 2), but it goes round the glitch and now all your faces are visible. So if you want to go that way, just replace the face definition above by:

fv.faces = [...
     1  9 11 4 12 ;
     9  2 10 3 11 ;
     1  9 17 5 13 ;
     9  2 14 6 17 ;
     2 10 18 6 14 ;
    10  3 15 7 18 ;
     3 11 19 7 15 ;
    11  4 16 8 19 ;
     4 12 20 8 16 ;
    12  1 13 5 20 ;
     5 17 19 8 20 ;
    17  6 18 7 19 ] ;

There are more than one way to define the faces, just notice that each line of the faces vector, is a succession of point defining an area (the face will close itself down, no need to repeat the first point in the end to close the surface). We went from faces with 8 points to faces with 5 points ... if you want to play/refine your model, you could try using 3 points faces, it would work the same way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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