Finite Element - Plotting with stresses in triangle mesh - matlab

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

Related

Plotting a graph - Different line styles for different edges

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

Single boxplot for multiple group comparison

Here is the sample code that i used to compare two groups with random mean and standard deviation. However, i want to plot both groups in a single box in the box plot as shown in the attached figure where x-axis is group 1 and y-axis is group 2. I could not find any code doing this. Can some one please help me with this?
clc
clear
x=[rand(1,10) rand(1,10) rand(1,10) rand(1,10) rand(1,10) rand(1,10)];
n=10 ; xx=([1:6])'; % example
r=repmat(xx,1,n)';
g=r(:)';
positions = [1 2 3 4 5 6 ];
h=boxplot(x,g, 'positions', positions);
set(h,'linewidth',2)
set(gca,'xtick',[mean(positions(1:2)) mean(positions(3:4)) mean(positions(5:6)) ])
set(gca,'xticklabel',{'exp1','exp2','exp3'},'Fontsize',28)
color = ['c', 'y', 'c', 'y','c', 'y'];
h = findobj(gca,'Tag','Box');
for j=1:length(h)
patch(get(h(j),'XData'),get(h(j),'YData'),color(j),'FaceAlpha',.5);
end
now i want yellow and blue for exp1 in one box as shown below.. similarly for exp2 and exp3 so on.. so 3 boxes in one boxplot..Ideally this should work for any number of experiments.
For a single two-sided boxplot, we can use the 'Orientation' property, and overlay 2 boxplots one above the other:
x = [1 2 3 4 5 6 7 1 2 3 4 5 6 7];
group = [1,1,1,1,1,1,1,2,2,2,2,2,2,2];
% we need the precntiles of the groups so the boxes will overlap.
% on each boxplot we set the width to the other boxplot hight:
p1 = prctile(x(group==1),[25 75]);
p2 = prctile(x(group==2),[25 75]);
ax = axes;
% first group is vertical:
boxplot(x(group==2),'Positions',mean(x(group==1)),...
'Orientation','vertical','Widths',p1(2)-p1(1),'Colors','r');
lims1 = axis;
hold on
% secound group is horizontal:
boxplot(x(group==1),'Positions',mean(x(group==2)),...
'Orientation','horizontal','Widths',p2(2)-p2(1),'Colors','k');
% the values of the axis are no longer relevant, since they have two
% different meanings, depend on the group. So we hide them.
ax.XAxis.Visible = 'off';
ax.YAxis.Visible = 'off';
hold off
lims2 = axis;
% because each axis represent to different things, we make sure we see
% everything:
axis([max(lims1(1),lims2(1)),...
min(lims1(2),lims2(2)),...
min(lims1(3),lims2(3)),...
max(lims1(4),lims2(4))])
To create multiple two-sided box-plots you need to use an axes for each experiment:
x = rand(10,6);
nsp = floor(size(x,2)/2); % the number of subplots
meanx = mean(x);
% we need the precntiles of the groups so the boxes will overlap.
% on each boxplot we set the width to the other boxplot hight:
width = range(prctile(x,[25; 75]));
main_ax = axes; % create a tmporary axes
% we get the measurements of the ploting area:
pos = main_ax.Position;
% and divide it to our data:
axwidth = pos(3)/nsp; % the width of each group
% the bottom left corner of each group:
corner = linspace(pos(1),pos(3)+pos(1),nsp+1);
clf % clear the area!
% now we plot each pair of boxplot on a different subplot:
for k = 1:2:size(x,2)
ax = axes('Position',[corner((k+1)/2) pos(2) axwidth pos(4)]);
hold on
% first group is vertical:
boxplot(x(:,k),'Positions',meanx(k+1),...
'Orientation','vertical','Widths',width(k+1),'Colors','r');
% secound group is horizontal:
boxplot(x(:,k+1),'Positions',meanx(k),...
'Orientation','horizontal','Widths',width(k),'Colors','k');
% the values of the y-axis are no longer relevant, since they have two
% different meanings, depend on the group. So we hide them.
ax.YAxis.Visible = 'off';
% we use the x-axis to label the pairs of boxplots:
ax.XAxis.TickLabels = ['Exp ' num2str((k+1)/2)];
% because each axis represent to different things, we make sure we see
% everything:
minx = min(min(x(:,k:k+1)))*0.1;
maxx = max(max(x(:,k:k+1)))*1.1;
axis ([minx maxx minx maxx])
hold off
box off
% set the locations to the exact same place:
bx = findobj(ax,'tag','Box'); % get the boxes
posXdif = bx(2).XData(1)-bx(1).XData(1); % get the horizontal difference
posYdif = bx(2).YData(1)-bx(1).YData(1); % get the vertical difference
bx2Xdata = get(ax.Children(2).Children,{'XData'}); % get all X-data of box 2
bx2Ydata = get(ax.Children(2).Children,{'YData'}); % get all Y-data of box 2
% substruct horizontal difference X-data:
set(ax.Children(2).Children,{'XData'},...
cellfun(#(x) x-posXdif,bx2Xdata,'UniformOutput',false))
% substruct vertical difference Y-data:
set(ax.Children(2).Children,{'YData'},...
cellfun(#(y) y-posYdif,bx2Ydata,'UniformOutput',false))
end

hist3 plot with additional z axis

The following code creates a 2D stacked histogram for two 2D distributions:
%%first dataset
x1 = 200 + 300.*rand(1000,1)'; %rand values between 0 and 200
y1 = 100 + 250.*rand(1000,1)'; %rand values between 100 and 500
%%secnd dataset
x2 = 100 + 200.*rand(1000,1)'; %rand values between 0 and 200
y2 = 200 + 400.*rand(1000,1)'; %rand values between 100 and 500
one = linspace(100,400,20);
two = linspace(100,500,20);
EDGES = {one, two}; %edges
[n1,c1] = hist3([x1' y1'],'Edges',EDGES);%first dataset
[n2,c2] = hist3([x2' y2'],'Edges',EDGES);%second dataset
figure('Color','w');
% plot the first data set
bh=bar3(n1);
% Loop through each row and shift bars upwards
for ii=1:length(bh)
zz = get(bh(ii),'Zdata');
kk = 1;
% Bars are defined by 6 faces(?), adding values from data2 will
% shift the bars upwards accordingly, I'm sure this could be made
% better!
for jj = 0:6:(6*length(bh)-6)
zz(jj+1:jj+6,:)=zz(jj+1:jj+6,:)+n2(kk,ii);
kk=kk+1;
end
%erase zero height bars
%# get the ZData matrix of the current group
Z = get(bh(ii), 'ZData');
%# row-indices of Z matrix. Columns correspond to each rectangular bar
rowsInd = reshape(1:size(Z,1), 6,[]);
%# find bars with zero height
barsIdx = all([Z(2:6:end,2:3) Z(3:6:end,2:3)]==0, 2);
%# replace their values with NaN for those bars
Z(rowsInd(:,barsIdx),:) = NaN;
%# update the ZData
set(bh(ii), 'ZData',Z)
end
% Set face colour to blue for data1
set(bh,'FaceColor',[0 0 1]);
% Apply hold so that data2 can be plotted
hold on;
% Plot data2
bh=bar3(n2);
%erase zero height bars
for ii=1:numel(bh)
%# get the ZData matrix of the current group
Z = get(bh(ii), 'ZData');
%# row-indices of Z matrix. Columns correspond to each rectangular bar
rowsInd = reshape(1:size(Z,1), 6,[]);
%# find bars with zero height
barsIdx = all([Z(2:6:end,2:3) Z(3:6:end,2:3)]==0, 2);
%# replace their values with NaN for those bars
Z(rowsInd(:,barsIdx),:) = NaN;
%# update the ZData
set(bh(ii), 'ZData',Z)
end
% Set face color to red
set(bh,'FaceColor',[1 0 0]);
%set ticks
set(gca,'XTick',1:6:numel(one),'XTickLabel',one(1:6:end))
set(gca,'YTick',1:6:numel(one),'YTickLabel',one(1:6:end))
view(20,40)
%labels
xlabel('x')
ylabel('y')
zlabel('z')
%set transparency
set(gcf,'renderer','opengl');
set(get(gca,'child'),'FaceAlpha',0.8);
set(get(gca,'child'),'EdgeAlpha',0.3);
A first issue is the transparency (but I think it is a problem of my matlab version 2014a, so I am not bothered by that). It just makes all blurry.
My question is how to add a mesh plot on the same picture. The code creating the meshes is the following:
%create surface I want to plot
[X,Y] = meshgrid(one,two);
inds1=find(X(:).*Y(:)<.3e5);%condition
inds2=find(X(:).*Y(:)>.3e5);
I=Y./X.^2;%first surface
I(inds1)=NaN;%second surface
figure('Color','w');hold on
mesh(X,Y,I,'FaceColor',[0 0 1],'EdgeColor','none')
I(:,:)=NaN;
I(inds1)=Y(inds1)./X(inds1);%second surface
mesh(X,Y,I,'FaceColor',[1 0 0],'EdgeColor','none')
alpha(.5)
grid on
view(20,40)
%labels
xlabel('x')
ylabel('y')
zlabel('z')
The domain of the histograms and the meshes are the same. So I just need to add an extra z-axis on the first figure.
I tried substituting figure('Color','w');hold on in the second code with AxesH = axes('NextPlot', 'add');, but I was really wrong about that:
That just overlayed the two figures..
I also tried something along the lines of:
%add axis
axesPosition = get(gca,'Position'); %# Get the current axes position
hNewAxes = axes('Position',axesPosition,... %# Place a new axes on top...
'Color','none',... %# ... with no background color
'ZLim',[0 400],... %# ... and a different scale
'ZAxisLocation','right',... %# ... located on the right
'XTick',[],... %# ... with no x tick marks
'YTick',[],... %# ... with no y tick marks
'Box','off');
but it is not feasible because the property ZAxisLocation does not exist.
Does anyone know how to add the z-axis?
Also, if you have other comments on how to ameliorate the code, they're welcome!
acknowledgements
2d stacked histogram:https://stackoverflow.com/a/17477348/3751931
erasing the zero values in the hist plot: https://stackoverflow.com/a/17477348/3751931
I now think that this is not yet possible (http://www.mathworks.com/matlabcentral/answers/95949-is-there-a-function-to-include-two-3-d-plots-with-different-z-axes-on-the-same-plot-area-similar-to).
So I just added a fake axis:
[X,Y] = meshgrid(one,two);
inds1=find(X(:).*Y(:)<.3e5);%condition
inds2=find(X(:).*Y(:)>.3e5);
s=Y./X.^2;%first surface
s(inds1)=NaN;%second surface
%mesh(X,Y,I,'FaceColor',[0 0 1],'EdgeColor','none')
mesh((X-min(min(X)))/max(max(X-min(min(X))))*20,(Y-min(min(Y)))/max(max(Y-min(min(Y))))*20,...
s/max(max(s))*max(max(n1))+max(max(n1)),'FaceColor','g','EdgeColor','none','facealpha',.5)
s(:,:)=NaN;
s(inds1)=Y(inds1)./X(inds1);%second surface
%mesh(X,Y,I,'FaceColor',[1 0 0],'EdgeColor','none')
mesh((X-min(min(X)))/max(max(X-min(min(X))))*20,(Y-min(min(Y)))/max(max(Y-min(min(Y))))*20,...
s/max(max(s))*max(max(n1))+max(max(n1)),'FaceColor','y','EdgeColor','none','facealpha',.5)
alpha(.5)
grid on
%add fake z axis
line([20 20],[1 1],[max(max(n1))-min(min(s)) 20],...
'color','g','linewidth',2)
% text(20*ones(1,5),zeros(1,5),linspace(max(max(n1))-min(min(I)),20,5),...
% num2str(linspace(0,max(max(I)),5)),'color','g')
z=linspace(max(max(n1))-min(min(s)),20,5);
txto=linspace(0,max(max(s)),5);
for ii=1:5
line([20 20.3],[1 1],[z(ii) z(ii)],'color','g')%ticks
text(20,0,z(ii),num2str(txto(ii)),'color','g')%ticklabel
end
text(19.8,1,21,'s','color','g')%label
Over all the code is quite ugly and needs a lot of tuning..

Plotting a zplot using Matlab

I am trying to plot a zplot in Matlab that displays a unit circle, centered at 0 along with the poles and zeros of the plot. I am not allowed to use any other matlab function such as zplane or pzplot to do this. So far I am able to plot a unit circle just fine but I am having trouble getting my plot to display more of the axis without warping my circle. I also am having a heard time finding the poles and zeros of my function and also how to display the poles as little x's and the zeros as little o's on my plot. Any help would be greatly appreciated! My assignment looks like this and must correctly handle cases such as
zplot([0 1 1], [0 1]);
zplot([0 1 1], [0 0 1]);
function zplot(b, a)
% ZPLOT Plot a zero-pole plot.
-1 -nb
B(z) b(1) + b(2)z + .... + b(nb+1)z
H(z) = ---- = ---------------------------------
-1 -na
A(z) a(1) + a(2)z + .... + a(na+1)z
% zplot(b, a) plots the zeros and poles which determined by vectors b and a
% The plot includes the unit circle and axes for reference, plotted in black.
% Each zero is represented with a blue 'o' and each pole with a red 'x' on the
%plot.
xmin;
xmax;
ymin;
ymax;
% vector of angles at which points are drawn
angle = 0:2*pi/100:2*pi;
% Unit radius
R = 1;
% Coordinates of the circle
x = R*cos(angle);
y = R*sin(angle);
% Plot the circle
plot(x,y);
axis ([xmin, xmax, ymin, ymax]);
grid on;
end
If you can't use pzplot() it is not hard. Here is a hint:
num = [1 4 1];%numerator coefficients of transfer function
den = [1 2 1];%denominator coefficients
z = roots(num)%zeros
p = roots(den)%poles
angle = 0:2*pi/100:2*pi;
xp = cos(angle);
yp = sin(angle);
figure(1)
scatter(z,zeros(length(z),1),'o');
hold on
scatter(p,zeros(length(p),1),'x');
plot(xp,yp);
axis equal
The output
Note that I haven't dealt with imaginary poles/zeros in this example. You'll need to calculate the proper x,y coordinates for a given imaginary pole or zero. (all the poles/zeros in this example are real, not imaginary)
Given a transfer function G, you can use the pzplot() command and add a circle to it.
G = tf([1 4 1],[1 2 1]);
angle = [0:0.1:2*pi+0.1];
xp = cos(angle);
yp = sin(angle);
figure(1)
hold on
pzplot(G);
plot(xp,yp);
axis equal;
This should give you the pole-zero plot with x's for poles, o's for zeros, and the unit circle.
Here is the result.

Most efficient way to draw a bunch of 3d lines in matlab

I need to plot a list of 3d lines in matlab. What is the quickest way to do that?
I am currently doing something like
%edges is a MX2 matrix, holding the list of edges
%points are the vertices' coordinates
hold on; %so all the lines will be saved
for i=1:size(edges,1)
a=edges(i,1); %get first point's index
b=edges(i,2); %get second point's index
p=[points(:,a) points(:,b)]; %construct a 3X2 matrix out of the 2 points
plot3(p(1,:),p(2,:),p(3,:)); %plot a line
end
But this is not only slow during the actual loop, but also at the end, the resulting plot is very slow and irresponsive when I try to, for instance, rotate it using the drag & rotate tool.
I know the same plot using opengl etc would run much faster...
You can use the LINE low-level function, using NaN to plot as separate segments:
%# sample graph vertices and edges (similar to your data)
[adj,XYZ] = bucky;
[r c] = find(adj);
edges = [r c]; %# M-by-2 matrix holding the vertex indices
points = XYZ'; %# 3-by-N matrix of points X/Y/Z coordinates
%# build a list of separated lines
e = edges';
e(end+1,:) = 1;
e = e(:);
p = points(:,e);
p(:,3:3:end) = NaN;
figure
h = line(p(1,:), p(2,:), p(3,:));
view(3)
This is very efficient as it creates a single line object. Now you can customize the line, but it is restricted to have one color for the entire thing:
set(h, 'Color',[.4 .4 1], 'Marker','.', 'MarkerSize',10, ...
'MarkerFaceColor','g', 'MarkerEdgeColor','g')
According to the comments, if you want to have each edge in your graph in a specified color, consider the following code instead. It involves using the SURFACE function:
p = p'; %'# transpose the above p for convenience
clr = (1:size(p,1))'; %'# for each edge, color index in current colormap
figure
surface(p(:,[1 1]), p(:,[2 2]), p(:,[3 3]), [clr clr], ...
'EdgeColor','flat', 'FaceColor','none')
colormap( hsv(numel(clr)) ) %# specify your colormap here
view(3)
I think you can do something like this (caution - brain compiled code...)
figure;
patch('faces', edges, 'vertices', points, 'edgecolor', 'b');
axis equal;
Where edges should be an Nx2 matrix of indices and points should be an Mx3 matrix of coordinates (the transpose of your points array).
From my experience, calling patch directly can be significantly faster than repeated calls to plot.
To give some idea, the times to generate 1000 randomly generated line segments, using my (admittedly old!) MATLAB 7.1 are as follows:
Calling patch: 0.03 seconds.
Calling plot: 0.5 seconds.
EDIT: One way to get the edge colour behaving as you want (specifying a single colour per edge) is to introduce duplicate vertices as follows:
This works-around the issue that the edge colour can only be specified indirectly via vertex colour data. If we were to rely only on the vertex colours then all edges sharing a common vertex might end up with the colour assigned to that vertex - check out the 'flat 'edgecolour description here.
%% a "star" shape, so that we can really see what's going on
%% with the edge colours!!
pp = [0,0,0; 1,-1,0; 1,1,0; -1,1,0; -1,-1,0];
ee = [1,2; 1,3; 1,4; 1,5];
%% important - only 1 colour known per edge, not per vertex!!
cc = (1:size(ee,1))';
%% setup a new set of vertices/edges/colours with duplicate vertices
%% so that each edge gets it's correct colour
nnum = 0;
pnew = zeros(2 * size(ee, 1), 3); %% new vertices
enew = zeros(1 * size(ee, 1), 2); %% new edge indices
cnew = zeros(2 * size(ee, 1), 1); %% new edge colours - via vertices
for j = 1 : size(ee, 1)
n1 = ee(j, 1); %% old edge indices
n2 = ee(j, 2);
enew(j, 1) = nnum + 1; %% new edge indicies into pnew
enew(j, 2) = nnum + 2;
pnew(nnum + 1, :) = pp(n1, :); %% create duplicate vertices
pnew(nnum + 2, :) = pp(n2, :);
cnew(nnum + 1) = cc(j); %% map single edge colour onto both vertices
cnew(nnum + 2) = cc(j);
nnum = nnum + 2;
end
%% Draw the set efficiently via patch
tic
figure;
hold on;
patch('faces', enew, 'vertices', pnew, 'facevertexcdata', cnew, ...
'edgecolor', 'flat', 'facecolor', 'none');
plot(pnew(:,1), pnew(:,2), 'b.');
axis equal;
toc
It would be nicer if MATLAB allowed you to directly specify the edge colour data - but it doesn't seem to support that...
Hope this helps.