Drawing a network of nodes in circular formation with links between nodes

Here is one way you can do what you want. First, generate points on the circle that you are interested in

clear;
theta=linspace(0,2*pi,31);theta=theta(1:end-1);
[x,y]=pol2cart(theta,1);

Next, if you know the pairs of nodes that are connected, you can skip this step. But in many cases, you get a connectivity matrix from other computations, and you find the indices of the connected nodes from that. Here, I've created a Boolean matrix of connections. So, if there are N nodes, the connectivity matrix is an NxN symmetric matrix, where if the i,jth element is 1, it means you have a connection from node i to node j and 0 otherwise. You can then extract the subscripts of the non-zero pairs to get node connections (only the upper triangle is needed).

links=triu(round(rand(length(theta))));%# this is a random list of connections
[ind1,ind2]=ind2sub(size(links),find(links(:)));

This is the connectivity matrix I generated with the code above.

enter image description here

Now we just need to plot the connections, one at a time

h=figure(1);clf(h);
plot(x,y,'.k','markersize',20);hold on
arrayfun(@(p,q)line([x(p),x(q)],[y(p),y(q)]),ind1,ind2);
axis equal off

which will give you a figure similar to your examples

enter image description here


Inspired by the latest blog post by Cleve Moler, you could also use the gplot function to draw a graph given an adjacency matrix and node coordinates.

Here is an example using bucky; a demo function part of MATLAB that generates the graph of a truncated icosahedron (looks like a soccer ball). We will only use its adjacency matrix for this example since we are laying out the vertices in a circular shape:

%# 60-by-60 sparse adjacency matrix
A = bucky();
N = length(A);

%# x/y coordinates of nodes in a circular layout
r =  1;
theta = linspace(0,2*pi,N+1)'; theta(end) = [];
xy = r .* [cos(theta) sin(theta)];

%# labels of nodes
txt = cellstr(num2str((1:N)','%02d'));

%# show nodes and edges
line(xy(:,1), xy(:,2), 'LineStyle','none', ...
    'Marker','.', 'MarkerSize',15, 'Color','g')
hold on
gplot(A, xy, 'b-')
axis([-1 1 -1 1]); axis equal off
hold off

%# show node labels
h = text(xy(:,1).*1.05, xy(:,2).*1.05, txt, 'FontSize',8);
set(h, {'Rotation'},num2cell(theta*180/pi))

circular_graph


We can take this a step further and try to minimize edge crossings. That is we want to rearrange the nodes so that the edges are as close as possible to the circumference of the circle.

This can be done by finding a symmetric permutation of the matrix that minimizes its bandwidth (non-zeros are closer to the diagonal)

matrix_permutation

p = symrcm(A);
A = A(p,p);
txt = txt(p);

The result in this case:

circular_graph_permutation

Other improvements include replacing straight lines with curved splines to draw the edges, (that way you get a nicer graph similar to the second one you've shown), or using different colors to show clusters of vertices and their edges (obviously you'll need to do graph clustering). I will leave those steps to you :)