Jeanne
Jeanne

Reputation: 13

How can I add increasing values to an increasing number of neighbours in an array in Matlab?

I have a geometry that consists of vertices and triangles. I have a matrix of size 3102x3 of which each row represents one triangle, and the columns contain the indices of the triangles that are directly neighbouring. For example:

2     6     9
1     3    13
2     4    15
3     5    17
4     6    21

So the neighbours of triangle 1 are triangle 2,6 and 9, etc. Now I want to determine how many 'rows' away every triangle is from one triangle that I am interested in, for example triangle 4. I want an array that has value 0 on index 4, value 1 on its neighbours (indices 3, 5 and 17), then the neighbouring triangles of 3,5 and 17 (so 9 in total) should be 2, and so on.

How can I implement this in an easy way?

Upvotes: 0

Views: 50

Answers (1)

Wolfie
Wolfie

Reputation: 30047

You can do this with a graph. Let's imagine each triangle as a point, then we have 3 neighbours for this triangle, as detailed by your matrix.

We can create an adjacency matrix from your input, then use graph to create the graph from the adj. matrix, and distances to compute the shortest path between every pair of nodes.

I kept the code generic, so if you progressed to squares / pentagons / whatever by adding more columns, then this should still work.

Here is the full code:

T = [2     6     9
     1     3    13
     2     4    15
     3     5    17
     4     6    21];

% Create graph values.
% Column 1 is triangle number (row number), column 2 is a neighbouring triangle 
% So there are 3 rows per triangle, one for each neighbour
B = [ repmat( (1:size(T,1)).', size(T,2), 1 ), T(:) ];
% Make the relationship symmetric (i.e. if Tri3 is neighbour of Tri15, then 
% Tri15 is neighbour of Tri3. This is necessary because T is incomplete.     
% Use unique so we don't get duplicates if already specified
B = unique( [ B; fliplr(B) ], 'rows' ); 

% Create adjacency matrix from B
A = full( sparse( B(:,1), B(:,2), ones(size(B,1),1) ) );

% Create graph
G = graph( A );

% Get distances
D = G.distances;

Now D(i,j) is the minimum distance from triangle i to triangle j, where i and j are rows in the original matrix T.

So if you're interested in triangle 2, you can do

>> distances = D(2,:);
distances = 
 [2, 0, 2, 4, 4, 3, Inf, Inf, 3, Inf, Inf, Inf, 1, Inf, 3, Inf, 5, Inf, Inf, Inf, 5]

Distances of Inf show the triangles are never connected through each other. If you wanted this in an easier to read form, you could do

distances = D(:,2); % want the column version, same values as D(2,:);
idx = ~isinf( distances );
result = [ find( idx ), distances( idx ) ];

Output for distances to triangle 2 (first column is triangle num, second is distance):

>> result
result = 
 1     1
 2     0
 3     1
 4     2
 5     3
 6     2
 9     2
13     1
15     2
17     3
21     4

Upvotes: 3

Related Questions