Calculate distance matrix for 3D points

Viewed 301

I have the lists xA, yA, zA and the lists xB, yB, zB in Matlab. The contain the the x,y and z coordinates of points of type A and type B. There may be different numbers of type A and type B points.

I would like to calculate a matrix containing the Euclidean distances between points of type A and type B. Of course, I only need to calculate one half of the matrix, since the other half contains duplicate data.

What is the most efficient way to do that?

When I'm done with that, I want to find the points of type B that are closest to one point of type A. How do I then find the coordinates the closest, second closest, third closest and so on points of type B?

1 Answers

Given a matrix A of size [N,3] and a matrix B of size [M,3], you can use the pdist2 function to get a matrix of size [M,N] containing all the pairwise distances.

If you want to order the points from B by their distance to the rth point in A then you can sort the rth row of the pairwise distance matrix.

% generate some example data
N = 4
M = 7

A = randn(N,3)
B = randn(M,3)

% compute N x M matrix containing pairwise distances
D = pdist2(A, B, 'euclidean')

% sort points in B by their distance to the rth point in A
r = 3
[~, b_idx] = sort(D(r,:))

Then b_idx will contain the indices of the points in B sorted by their distance to the rth point in A. So the actual points in B ordered by b_idx can be obtained with B(b_idx,:), which has the same size as B.

If you want to do this for all r you could use

[~, B_idx] = sort(D, 1)

to sort all the rows of D at the same time. Then the rth row of B_idx will contain b_idx.


If your only objective is to find the closest k points in B for each point in A (for some positive integer k which is less than M), then we would not generally want to compute all the pairwise distances. This is because space-partitioning data structures like K-D-trees can be used to improve the efficiency of searching without explicitly computing all the pairwise distances.

Matlab provides a knnsearch function that uses K-D-trees for this exact purpose. For example, if we do

k = 2
B_kidx = knnsearch(B, A, 'K', k)

then B_kidx will be the first two columns of B_idx, i.e. for each point in A the indices of the nearest two points in B. Also, note that this is only going to be more efficient than the pdist2 method when k is relatively small. If k is too large then knnsearch will automatically use the explicit method from before instead of the K-D-tree approach.

Related