Plotting a graph - Different line styles for different edges - matlab

I have a graph of nodes and edges that I am plotting against (x, y, z) coordinates for each node.
I would like to use a dotted line for the "inner" edges, and a straight line for the "outer" edges.
LineStyle may help me, but I think that will make all of my edges dotted lines. I would like to specify which edges are dotted.
Here is the code I am using to plot the graph: (G is a graph)
plot(G, 'XData', A(1,:), 'YData', A(2,:), 'ZData', A(3,:))
Any help is much appreciated!
I have a function to create the graph, it gives this output:
G =
graph with properties:
Edges: [11×1 table]
Nodes: [6×0 table]
And a coordinate system similar to this:
A =
0 1 0 -1 0 0
0 1 3 2 1 2
1 1 1 1 1 1
Using the plot function above, this provides this output:

Ok you didn't really put enough effort in making your question easy to answer for everybody but I was curious about a method and it seem to work so I'll post it anyway.
The classic trick for these cases where a sub-group of points/lines have to be plotted differently than the whole group is to:
Plot the whole group
Plot the sub-group on top with different line properties
In your case, it means you have to find the points and edges which are part of the boundary. I'll explain one method below. Be aware that this method will only work for convex boundaries (see the difference with a concave set where the method wouldn't work: concave vs. convex hull ).
First I need to get to the state of your question, so let's consider:
%% Initial data
A =[ 0 1 0 -1 0 0
0 1 3 2 1 2
1 1 1 1 1 1 ];
G = graph ;
G = addedge(G,[1 1 1 1 1 2 2 2 3 4 4],[2 3 4 5 6 3 5 6 4 5 6]) ;
plot(G, 'XData', A(1,:), 'YData', A(2,:) , 'LineStyle','--')
grid on ; hold on
np = size(A,2) ; % Number of points/nodes
This will produce a figure exactly like yours, with only one linestyle, which was set to dashed lines for the full graph. The exercise is now to plot a contour with a solid line.
To find the contour (at least in 2D cases like yours), the method used is:
find one point of the contour (initial point), the lowest x
possible.
calculate the angle between unit vector ux=[1,0,0] and
all the other vectors (formed by the initial point and all the other
points of the matrix).
Assign the next point of the contour (it is the one which vector has
the minimum angle) . You now have a current vector vec (between
point 1 and 2), and a current point pt2.
Calculate the angle between vec and all the other vectors (formed
by the current point pt2 and all the other points of the matrix)
the next point of the contour is the one which vector has the
minimum angle.
Repeat (3) and (4) until the next point of the contour is the
starting point.
Translated in code:
%% find a point on the edge
% (I chose to start with the lowest point on Y axis)
[~,idxNext] = min(A(2,:)) ;
%% initialise counters
isOnEdge = false(np,1) ; % this will hold a logical register of contour points
idxEdge = idxNext ; % this will hold the points of the contour, in order
%% setup start conditions
isOnEdge(idxNext) = true ; % initial point
p = A(:,idxNext) ; % initial point
v = [1;0;0] ; % initial vector (start with unit vector oriented Ox)
%% search for contour
isRunning = true ;
iter = 0 ;
while isRunning
iter = iter + 1 ; % make sure we're not stuck in infinite loop
angs = find_angles(v,p,A) ; % find angles between initial vector and all other points
angs(idxNext) = Inf ; % Exclude current point
if numel(idxEdge) > 1 % Exclude last point (if not at first iteration)
angs(idxEdge(end-1)) = Inf ;
end
[~,idxNext] = min(angs) ; % find the index of the minimum angle
if isOnEdge(idxNext)
% we've completed the close profile, bail out
isRunning = false ;
else
% move on to next point/vector
idxEdge = [idxEdge idxNext] ; %#ok<AGROW>
isOnEdge(idxNext) = true ;
p = A(:,idxNext) ;
v = A(:,idxNext) - A(:,idxEdge(end-1)) ;
end
if iter > np
break % make sure we're not stuck in infinite loop
end
end
%% present results
if isRunning
fprintf('Could''t find a closed profile\n')
else
fprintf('Found points defining a closed profile:\n')
disp(idxEdge)
end
%% Plot on top of graph
% create a matrix conataining only the contour points, close the contour by
% replicating the first point in last position
C = [A(:,idxEdge) , A(:,idxEdge(1))] ;
% plot
plot3( C(1,:) , C(2,:) , C(3,:) ,'b', 'LineWidth',2)
view(2)
Which will yield:
In the script above I am using the function find_angles.m. The code for it:
function angs = find_angles(Uin,p,M)
% find angle between Uin vector and the vectors formed between p and
% all the points in M
np = size(M,2) ;
angs = zeros(np,1) ;
for iv=1:np
vec = M(:,iv) - p ;
c = cross(Uin,vec) ;
d = dot(Uin,vec) ;
angs(iv) = rad2deg( atan2( norm(c) , d ) ) * sign( c(3) ) ;
% take care of an edge case
if c(3)==0 && d==-1 ; angs(iv) = 180 ; end
% give [0 360] degree results
if angs(iv) < 0 ; angs(iv) = 180 + (180+angs(iv) ) ; end
end

Related

how to do 3D number-density scatter plot using given data?

I have a cubic box with the size of, lets say 300 in each direction. I have some data (contains X,Y,Z coordinates) which represent the distribution of nearly 1 million data-points within this box. I want to specify a color to their Number density (its an intensive quantity used to describe the degree of concentration of countable objects in this case data-points). In another word, Using color to illustrate which part is more condensed in terms of data-points rather than the other parts. The index for the color-bar in the final image should represent the percentage of data-points specified with that color.
I have tried to do it by dividing the whole space in cubic box to 1 million smaller cube (each cube has a length of 3 in all direction). By counting the number of particles within those cube, I will know how they distributed in the box and the number of existed data-points within. Then I can specify a color to them which I wasn’t successful in counting and specifying. Any suggestion is appreciated.
%reading the files
[FileName,PathName,FilterIndex] = uigetfile('H:\*.txt','MultiSelect','on');
numfiles = size(FileName,2);%('C:\final1.txt');
j=1;
X=linspace(0,300,100);
for ii = 1:numfiles
FileName{ii}
entirefile = fullfile(PathName,FileName{ii});
a = importdata(entirefile);
x = a(:,2);
y = a(:,3);
z = a(:,4);
%% I DON'T KNOW HOW TO CREAT THIS LOOP TO COUNT FOR THE NUMBER OF PARTICLES WITHIN EACH DEFINED CUBE %%
for jj = 2:size(X,2)
%for kk=1:m
if x(:)<X(jj) & y(:)<X(jj) & z(:)<X(jj)
x;
end
%end
end
h=figure(j);
scatter3(x, y, z, 'filled', 'MarkerSize', 20);
cb = colorbar();
cb.Label.String = 'Probability density estimate';
end
I need to get a similar result like the following image. but I need the percentage of data-point specified by each color. Thanks in advance.
Here is a link to a sampled data.
Here is a way to count the 3D density of a point cloud. Although I am affraid the sample data you provided do not yield the same 3D distribution than on your example image.
To count the density, the approach is broken down in several steps:
Calculate a 2D density in the [X,Y] plane: This counts the number of points laying in each (x,y) bin. However, at this stage this number of point incorporates all the Z column for a given bin.
For each non-empty (x,y) bin, calculate the distribution along the Z column. We now have the number of point falling in each (x,y,z) bin. Counting the density/percentage is simply done by dividing each count by the total number of points.
Now for each non-empty (x,y,z) bin, we identify the linear indices of the points belonging to this bin. We then assign the bin value (color, percentage, or any value associated to this bin) to all the identified points.
display the results.
In code, it goes like this:
%% Import sample data
entirefile = '1565015520323.txt' ;
a = importdata(entirefile);
x = a(:,1);
y = a(:,2);
z = a(:,3);
npt = numel(x) ; % Total Number of Points
%% Define domain and grid parameters
nbins = 100 ;
maxDim = 300 ;
binEdges = linspace(0,maxDim,nbins+1) ;
%% Count density
% we start counting density along in the [X,Y] plane (Z axis aglomerated)
[Nz,binEdges,~,binX,binY] = histcounts2(y,x,binEdges,binEdges) ;
% preallocate 3D containers
N3d = zeros(nbins,nbins,nbins) ; % 3D matrix containing the counts
Npc = zeros(nbins,nbins,nbins) ; % 3D matrix containing the percentages
colorpc = zeros(npt,1) ; % 1D vector containing the percentages
% we do not want to loop on every block of the domain because:
% - depending on the grid size there can be many
% - a large number of them can be empty
% So we first find the [X,Y] blocks which are not empty, we'll only loop on
% these blocks.
validbins = find(Nz) ; % find the indices of non-empty blocks
[xbins,ybins] = ind2sub([nbins,nbins],validbins) ; % convert linear indices to 2d indices
nv = numel(xbins) ; % number of block to process
% Now for each [X,Y] block, we get the distribution over a [Z] column and
% assign the results to the full 3D matrices
for k=1:nv
% this block coordinates
xbin = xbins(k) ;
ybin = ybins(k) ;
% find linear indices of the `x` and `y` values which are located into this block
idx = find( binX==xbin & binY==ybin ) ;
% make a subset with the corresponding 'z' value
subZ = z(idx) ;
% find the distribution and assign to 3D matrices
[Nz,~,zbins] = histcounts( subZ , binEdges ) ;
N3d(xbin,ybin,:) = Nz ; % total counts for this block
Npc(xbin,ybin,:) = Nz ./ npt ; % density % for this block
% Now we have to assign this value (color or percentage) to all the points
% which were found in the blocks
vzbins = find(Nz) ;
for kz=1:numel(vzbins)
thisColorpc = Nz(vzbins(kz)) ./ npt * 100 ;
idz = find( zbins==vzbins(kz) ) ;
idx3d = idx(idz) ;
colorpc(idx3d) = thisColorpc ;
end
end
assert( sum(sum(sum(N3d))) == npt ) % double check we counted everything
%% Display final result
h=figure;
hs=scatter3(x, y, z, 3 , colorpc ,'filled' );
xlabel('X'),ylabel('Y'),zlabel('Z')
cb = colorbar ;
cb.Label.String = 'Probability density estimate';
As I said at the beginning, the result is slightly different than your example image. This sample set yields the following distribution:
If you want a way to "double check" that the results are not garbage, you can look at the 2D density results on each axis, and check that it matches the apparent distribution of your points:
%% Verify on 3 axis:
Nz = histcounts2(y,x,binEdges,binEdges) ./ npt *100 ;
Nx = histcounts2(z,y,binEdges,binEdges) ./ npt *100 ;
Ny = histcounts2(x,z,binEdges,binEdges) ./ npt *100 ;
figure
ax1=subplot(1,3,1) ; bz = plotDensity(Nz,ax1) ; xlabel('X'),ylabel('Y') ;
ax2=subplot(1,3,2) ; bx = plotDensity(Nx,ax2) ; xlabel('Y'),ylabel('Z') ;
ax3=subplot(1,3,3) ; by = plotDensity(Ny,ax3) ; xlabel('Z'),ylabel('X') ;
Click on the image to see it larger:
The code for plotDensity.m:
function hp = plotDensity(Ndist,hax)
if nargin<2 ; hax = axes ; end
hp = bar3(Ndist,'Parent',hax) ;
for k = 1:length(hp)
zdata = hp(k).ZData;
hp(k).CData = zdata;
hp(k).FaceColor = 'interp';
end
shading interp

Creating graphs that show the distribution in space of a large number of 2D Random Walks at three different time points

So essentially I have this code here that I can use to generate a 2D Random Walk discretely along N number of steps with M number of walkers. I can plot them all on the same graph here.
clc;
clearvars;
N = 500; % Length of the x-axis, also known as the length of the random walks.
M = 3; % The amount of random walks.
x_t(1) = 0;
y_t(1) = 0;
for m=1:M
for n = 1:N % Looping all values of N into x_t(n).
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
x_t(n+1) = x_t(n) + A;
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
y_t(n+1) = y_t(n) + A;
end
plot(x_t, y_t);
hold on
end
grid on;
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'Outerposition', [0, 0.05, 1, 0.95]);
axis square;
Now, I want to be able to Create graphs that show the distribution in space of the positions of a large number
(e.g. n = 1000) random walkers, at three different time points (e.g. t = 100, 200 and 300 or any three time points really).
I'm not sure how to go about this, I need to turn this into a function and iterate it through itself three different times and store the coordinates? I have a rough idea but iffy on actually implementing. I'd assume the safest and least messy way would be to use subplot() to create all three plots together in the same figure.
Appreciate any assistance!
You can use cumsum to linearize the process. Basically you only want to cumsum a random matrix composed of [-1 and 1].
clc;
close all;
M = 50; % The amount of random walks.
steps = [10,200,1000]; % here we analyse the step 10,200 and 1000
cc = hsv(length(steps)); % manage the color of the plot
%generation of each random walk
x = sign(randn(max(steps),M));
y = sign(randn(max(steps),M));
xs = cumsum(x);
xval = xs(steps,:);
ys = cumsum(y);
yval = ys(steps,:);
hold on
for n=1:length(steps)
plot(xval(n,:),yval(n,:),'o','markersize',1,'color',cc(n,:),'MarkerFaceColor',cc(n,:));
end
legend('10','200','1000')
axis square
grid on;
Results:
EDIT:
Thanks to #LuisMendo that answered my question here, you can use a binomial distribution to get the same result:
steps = [10,200,10000];
cc = hsv(length(steps)); % manage the color of the plot
M = 50;
DV = [-1 1];
p = .5; % probability of DV(2)
% Using the #LuisMendo binomial solution:
for ii = 1:length(steps)
SDUDx(ii,:) = (DV(2)-DV(1))*binornd(steps(ii), p, M, 1)+DV(1)*steps(ii);
SDUDy(ii,:) = (DV(2)-DV(1))*binornd(steps(ii), p, M, 1)+DV(1)*steps(ii);
end
hold on
for n=1:length(steps)
plot(SDUDx(n,:),SDUDy(n,:),'o','markersize',1,'color',cc(n,:),'MarkerFaceColor',cc(n,:));
end
legend('10','200','1000')
axis square
grid on;
What is the advantage ? Even if you have a big number of steps, let's say 1000000, matlab can handle it. Because in the first solution you have a bruteforce solution, and in the second case a statistical solution.
If you want to show the distribution of a large number, say 1000, of these points, I would say the most suitable way of plotting is as a 'point cloud' using scatter. Then you create an array of N points for both the x and the y coordinate, and let it compute the coordinate in a loop for i = 1:Nt, where Nt will be 100, 200, or 300 as you describe. Something along the lines of the following:
N = 500;
x_t = zeros(N,1);
y_t = zeros(N,1);
Nt = 100;
for tidx = 1:Nt
x_t = x_t + sign(randn(N,1));
y_t = y_t + sign(randn(N,1));
end
scatter(x_t,y_t,'k*');
This will give you N x and y coordinates generated in the same way as in the sample you provided.
One thing to keep in mind is that sign(0)=0, so I suppose there is a chance (admittedly a small one) of not altering the coordinate. I am not sure if you intended this behaviour to be possible (a walker standing still)?
I will demonstrate the 1-dimensional case for clarity; you only need to implement this for each dimension you add.
Model N steps for M walkers using an NxM matrix.
>> N = 5;
>> M = 4;
>> steps = sign(randn(N,M));
steps =
1 1 1 1
-1 1 -1 1
1 -1 -1 -1
1 1 -1 1
1 -1 -1 -1
For plotting, it is useful to make a second NxM matrix s containing the updated positions after each step, where s(N,M) gives the position of walker M after N steps.
Use cumsum to vectorize instead of looping.
>> s = cumsum(steps)
s =
1 1 1 1
0 2 0 2
1 1 -1 1
2 2 -2 2
3 1 -3 1
To prevent plot redraw after each new line, use hold on.
>> figure; hold on
>> plot(1:N, s(1:N, 1:M), 'marker', '.', 'markersize', 20, 'linewidth', 3)
>> xlabel('Number of steps'); ylabel('Position')
The output plot looks like this: picture
This method scales very well to 2- and 3-dimensional random walks.

Change color of 2D plot line depending on 3rd value

I have a data set that looks like this
140400 70.7850 1
140401 70.7923 2
140402 70.7993 3
140403 70.8067 4
140404 70.8139 5
140405 70.8212 3
Where the first column corresponds to time (one second intervals between data points) and will be on the x axis, the second column corresponds with distance and will be on the y axis. The third column is a number (one through five) that is a qualification of the movement.
I want to make a plot that changes the color of the line between two points depending on what the number of the previous data point was. For example, I want the line to be red between the first and second data points because the qualification value was 1.
I've seen a lot of posts about making a sliding scale of colors depending on an intensity value, but I just want 5 colors: (red, orange, yellow, green, and blue) respectively.
I tried doing something like this:
plot(x,y,{'r','o','y','g','b'})
But with no luck.
Any ideas of how to approach this? Without looping if possible.
You can also do it with a trick which works with Matlab version anterior to 2014b (as far back as 2009a at least).
However, is will never be as simple as you expected (unless you write a wrapper for one of the solution here you can forget about plot(x,y,{'r','o','y','g','b'})).
The trick is to use a surface instead of a line object. Surfaces benefit from their CData properties and a lot of useful features to exploit color maps and texture.
Matlab surf does not handle 1D data, it needs a matrix as input so we are going to give it by just duplicating each coordinate set (for example xx=[x,x]).
Don't worry though, the surface will stay as thin as a line, so the end result is not ugly.
%% // your data
M=[140400 70.7850 1
140401 70.7923 2
140402 70.7993 3
140403 70.8067 4
140404 70.8139 5
140405 70.8212 3];
x = M(:,1) ; %// extract "X" column
y = M(:,2) ; %// same for "Y"
c = M(:,3) ; %// extract color index for the custom colormap
%% // define your custom colormap
custom_colormap = [
1 0 0 ; ... %// red
1 .5 0 ; ... %// orange
1 1 0 ; ... %// yellow
0 1 0 ; ... %// green
0 0 1 ; ... %// blue
] ;
%% // Prepare matrix data
xx=[x x]; %// create a 2D matrix based on "X" column
yy=[y y]; %// same for Y
zz=zeros(size(xx)); %// everything in the Z=0 plane
cc =[c c] ; %// matrix for "CData"
%// draw the surface (actually a line)
hs=surf(xx,yy,zz,cc,'EdgeColor','interp','FaceColor','none','Marker','o') ;
colormap(custom_colormap) ; %// assign the colormap
shading flat %// so each line segment has a plain color
view(2) %// view(0,90) %// set view in X-Y plane
colorbar
will get you:
As an example of a more general case:
x=linspace(0,2*pi);
y=sin(x) ;
xx=[x;x];
yy=[y;y];
zz=zeros(size(xx));
hs=surf(xx,yy,zz,yy,'EdgeColor','interp') %// color binded to "y" values
colormap('hsv')
view(2) %// view(0,90)
will give you a sine wave with the color associated to the y value:
Do you have Matlab R2014b or higher?
Then you could use some undocumented features introduced by Yair Altman:
n = 100;
x = linspace(-10,10,n); y = x.^2;
p = plot(x,y,'r', 'LineWidth',5);
%// modified jet-colormap
cd = [uint8(jet(n)*255) uint8(ones(n,1))].' %'
drawnow
set(p.Edge, 'ColorBinding','interpolated', 'ColorData',cd)
My desired effect was achieved below (simplified):
indices(1).index = find( data( 1 : end - 1, 3) == 1);
indices(1).color = [1 0 0];
indices(2).index = find( data( 1 : end - 1, 3) == 2 | ...
data( 1 : end - 1, 3) == 3);
indices(2).color = [1 1 0];
indices(3).index = find( data( 1 : end - 1, 3) == 4 | ...
data( 1 : end - 1, 3) == 5);
indices(3).color = [0 1 0];
indices(4).index = find( data( 1 : end - 1, 3) == 10);
indices(4).color = [0 0 0];
indices(5).index = find( data( 1 : end - 1, 3) == 15);
indices(5).color = [0 0 1];
% Loop through the locations of the values and plot their data points
% together (This will save time vs. plotting each line segment
% individually.)
for iii = 1 : size(indices,2)
% Store locations of the value we are looking to plot
curindex = indices(iii).index;
% Get color that corresponds to that value
color = indices(iii).color;
% Create X and Y that will go into plot, This will make the line
% segment from P1 to P2 have the color that corresponds with P1
x = [data(curindex, 1), data(curindex + 1, 1)]';
y = [data(curindex, 2), data(curindex + 1, 2)]';
% Plot the line segments
hold on
plot(x,y,'Color',color,'LineWidth',lineWidth1)
end
When the result figure of two variables plotted is a circle, will be necessary to add the time in z axes.
For example the figure of induction machine rotor velocity vs electric torque in one laboratory test is: 2d plot figure
In the last figure the direction of the time point plotting could be clockwise or counter clockwise. For the last reason will be added time in z axis.
% Wr vs Te
x = logsout.getElement( 'Wr' ).Values.Data;
y = logsout.getElement( '<Te>' ).Values.Data;
z = logsout.getElement( '<Te>' ).Values.Time;
% % adapt variables for use surf function
xx = zeros( length( x ) ,2 );
yy = zeros( length( y ) ,2 );
zz = zeros( length( z ) ,2 );
xx (:,1) = x; xx (:,2) = x;
yy (:,1) = y; yy (:,2) = y;
zz (:,1) = z; zz (:,2) = z;
% % figure(1) 2D plot
figure (1)
hs = surf(xx,yy,zz,yy,'EdgeColor','interp') %// color binded to "y" values
colormap('hsv')
view(2)
% %
figure(2)
hs = surf(xx,yy,zz,yy,'EdgeColor','interp') %// color binded to "y" values
colormap('hsv')
view(3)
Finally we can view the 3d form and detect that counterwise is the real direction of the time plotting is: 3d plot
Scatter can plot the color according to the value and shows the colormap of the range of values. It's hard to interpolate the color though if you want continuous curves.
Try:
figure
i = 1:20;
t = 1:20;
c = rand(1, 20) * 10;
scatter(i, t, [], c, 's', 'filled')
colormap(jet)
The figure looks like

3D B-Spline approximation

B-Spline in 3D can be extended to produce a scalar function of three parameters:
The B-Spline is defined by 64 control points (the data values within a 4X4X4 voxel neighborhood), and evaluated inside the unit cube bounded by the eight central voxels, with t, s and r representing distances in the x, y and z direction respectively.
based on above notes I wrote my function in Matlab:
function [TO]=bspline_matrixform(I,valr,vals,valt,i,j,k)
% I : Input
% i : Index of grid point in x direction
% j : Index of grid point in y direction
% k : Index of grid point in z direction
r = valr; % Val r value in the grid
s = vals; % Val s value in the grid
t = valt; % Val t value in the grid
M = 1/6*[-1 3 -3 1;3 -6 3 0;-3 0 3 0;1 4 1 0];
R = [ r^3 r^2 r 1]; % 0<=r<=1
S = [ s^3 s^2 s 1]; % 0<=s<=1
T = [ t^3 t^2 t 1]; % 0<=w<=1
index = 1;
QK = zeros(4,1);
for ki= k-1:k+2
Q = QCalculation(I,i,j,ki);
QK(index) = S*M*Q*M'*T';
index = index+1;
end
TO = R*M*[QK(1) QK(2) QK(3) QK(4)]';
end
function Q = QCalculation (I,i,j,k)
Q = [I(i-1,j-1,k) I(i,j-1,k) I(i+1,j-1,k) I(i+2,j-1,k)
I(i-1,j,k) I(i,j,k) I(i+1,j,k) I(i+2,j,k)
I(i-1,j+1,k) I(i,j+1,k) I(i+1,j+1,k) I(i+2,j+1,k)
I(i-1,j+2,k) I(i,j+2,k) I(i+1,j+2,k) I(i+2,j+2,k)];
end
if my function is true, how should I call my function now? I dont know how should i calculate r,s and t.
P.S: to run this function, i have control points and ngrid in 3D, E.g from X-Y point of view, my control point( blue) and grid(red) are like this:
based on above notes, s,r and t are distances values between control points and the grid in above picture?
Anybody can help me to find out am I going through the right way and understanding? any alternative way or example code that can help im in 3D Bspline?
P.S: I am doing image registration (3d MRI), and my control points are my motion fields of registration result. I need to apply B-Spline to make my registration more smooth.
Thanks a lot

Finite Element - Plotting with stresses in triangle mesh

I'm making program where I need to plot some area which has been split up in many triangles. I have calculated strains in each node / each corner of the triangle. Now I need to plot the triangle with the strains.
Now I have three ways of plotting the triangles. But in one of them I fill each triangle with the average of it's corners strains. What I want to do is...
Put the strain on the corner and get a plot that looks like contour or contourf. - I don't really understand how they work.
Can anyone help me?
clear; clc;
TC = [ 1 2 3 ; 2 3 4 ] ; % Triangles node Connection.
NC = [ 0,0 ; 0,1 ; 1,0 ; 1,1 ] ; % Node Coordinates.
strain = [ 300 , 400 , 500 ; 400 , 500 , 600]; % Strains in each node.;
[ne,np] = size(TC); % Just finding how many elements.
element = zeros([3 2 ne]); % Creating a matrix for each element.
% My first and second plot...
for i=1:ne
no1 = TC(i,1); no2 = TC(i,2); no3 = TC(i,3);
element(:,:,i) = [ NC(no1,1),NC(no1,2);
NC(no2,1),NC(no2,2);
NC(no3,1),NC(no3,2);]; % Defining each element for each loop.
% Node 1 Node 2 Node 3
xe = [element(1,1,i),element(2,1,i),element(3,1,i)]; % Defining coordinates to plot.
ye = [element(1,2,i),element(2,2,i),element(3,2,i)];
subplot(3,1,1)
plot([xe, xe(1)],[ye, ye(1)]) % ATTEMPT ONE % Only plotting the triangles. Using first value also last to close the triangle.
xlim([-1 2]); ylim([-1 2])
hold on
subplot(3,1,2)
fill(xe,ye,mean(strain(i,:))) % ATTEMPT TWO % Fill triangles with average strain.
hold on
xlim([-1 2]); ylim([-1 2])
end
% ATTEMPT 3
subplot(3,1,3)
TR = triangulation(TC,NC);
triplot(TR)
hold on
xlim([-1 2]); ylim([-1 2])
Thanks in advance.
You can use the fill function to get the shading that you desire. With a little bit of customization for your application I believe the following code will work, although some vectorization may be in order if the for loop slows your program too much.
X = zeros(3,size(TC,1));
Y = zeros(3,size(TC,1));
C = zeros(3,size(TC,1));
for i = 1:size(TC,1) % for all triangle connection definitions
for j = 1:3 % for all nodes in a triangle
X(j,i) = NC(TC(i,j),1)'; % format X points
Y(j,i) = NC(TC(i,j),2)'; % format Y points
C(:,i) = strain(i,:)'; % format color based on strain value
end
end
fill(X,Y,C)
The result:
You may want to check this documentation for further details on how X,Y and C are interpreted