# Sorting points based on comparing distances.

107 views (last 30 days)
Vance Blake on 1 Sep 2019
Edited: Bruno Luong on 9 Sep 2019
Hello, I am using matlab 2019a and I am trying to sort points based on comparing the distance between them. I use the pdist2 function to calculate the the distance between the points stored in matricies. One matrix has 2 sets of coordinates
A= [0 0, -5.52181708330649 5.78874218621840]
the other has 7 sets
B = [38.8197976955836 -29.0434116907097
-37.0532684880158 0.644925865563445
-4.49735986053992 57.3402937422674
-43.7442096431328 38.5935144262550
41.5359946082739 41.4696332098067
57.3572679057450 8.87552592324304
-29.8320366435934 -43.1286701525403]
After calculating the distance between each point in A and every point in B i end up with a 2x7 matrix C. C(1,1) is the distance between the first point in A and the first point in B while C(2,1) is the distance between point 2 in A and point 1 in B. I want to compare each of these distances between C(1,2) to C(2,2).... to the end and sort the points in B based on which point in A they are closest to. I hope to end up with a matrix of points closest to the first point in A and another matrix of points closest to the second point in A. If the code works with a variable number of points in A that would be greatly apprecitated. Thanks for the help.

Adam Danz on 1 Sep 2019
Edited: Adam Danz on 8 Sep 2019
Use the 2nd output to min() to pair the points in B to the nearest points in A. Then use splitapply to segment the points in B into nearest neighbors in A. This works for any amount of coordinates in A.
% Creat demo data
A= [0 0;
-5.52181708330649 5.78874218621840];
B = [38.8197976955836 -29.0434116907097
-37.0532684880158 0.644925865563445
-4.49735986053992 57.3402937422674
-43.7442096431328 38.5935144262550
41.5359946082739 41.4696332098067
57.3572679057450 8.87552592324304
-29.8320366435934 -43.1286701525403];
% compute distances between A, B
C = pdist2(A,B);
% or better: C = sqrt((B(:,1)-A(:,1)').^2 + (B(:,2)-A(:,2)').^2)';
% Split B into groups that are nearest to points in A
[~, minRowIdx] = min(C,[],1); %
neighborGroups = splitapply(@(x){x},B,minRowIdx(:));
neighborGroups{n} are all the coordinates in B that are closest to A(n,:).
Bruno Luong on 9 Sep 2019
Handle "name"? Exists at the creation? Not sure what you are concerned.
I show you a pseudo test code.
% Generate some dummy test data
A = rand(5,2);
B = rand(100,2);
idx = nearestNeighbor(delaunayTriangulation(A),B);
gidx = unique(idx);
ngrp = length(gidx);
h = zeros(1,ngrp); % prealloate a table of graphic handles
ColorTable = jet(ngrp);
figure
hold on
for k = 1:ngrp
Bgrp = B(idx==gidx(k),:); % filter
Color = ColorTable(k,:); % Select the color of your specific group
h(k) = plot(Bgrp(:,1), Bgrp(:,2), 'o', 'Color', Color, 'MarkerFace', Color, 'Markersize', 10);
end
h(k) is array of handles, each correspond to a plot with a group.
You know which plot contains which B from idx. The information is encoded in arrays idx, gidx, ngrp, h. You can further split idx and ngrp of cell, put them in array of structures (or table), gives it a name for each individual structure if you like.
What is the problem with those arrays, what you can't figure out with array of handles h()?

Bruno Luong on 8 Sep 2019
Edited: Bruno Luong on 8 Sep 2019
You might learn to use Delaunay triangulation that can find nearrest points much more efficiently than pdist2 or such (applicable if the number of points of A is >=3). scatteredInterpolant is based in Delaunay T.
A=rand(1000,2);
B=rand(1000,2);
% pdist2
[~,i]=min(pdist2(A,B),[],1)
% scatteredInterpolant
F=scatteredInterpolant(A(:,1),A(:,2),(1:size(A,1))','nearest');
i = F(B(:,1),B(:,2))'
% Direct call of Delaunay
i = nearestNeighbor(delaunayTriangulation(A),B)'
Vance Blake on 8 Sep 2019
@Bruno thank you for the help! I will have to read more about it and experiment with it but your suggestions have given me a new perspective about matlab's capabilities.