Reputation: 1505
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:
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:
Upvotes: 1
Views: 1960
Reputation: 11792
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:
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.
Upvotes: 2
Reputation: 513
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, e.g. 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
Upvotes: 2