Depending on how you look at the task, here are two different approaches
Minimum Distance to Each Row in Second Matrix
Two ways to look at this: (1) closest point in A
for each point in B
, or (2) closest point in B
for each point in A
.
Closest point in A
For each point in B
you can find the closest point in A
(e.g. Euclidean distance), as requested in comments:
% Calculate all MxN high-dimensional (3D space) distances at once
distances = squeeze(sum(bsxfun(@minus,B,permute(A,[3 2 1])).^2,2));
% Find closest row in A for each point in B
[~,ik] = min(distances,[],2)
Make an array the size of B
containing these closest points in A
:
Anew = A(ik,:)
This will implicitly throw out any points in A
that are too far from points in B
, as long as each point in B
does have a match in A
. If each point in B
does not necessarily have a "match" (point at an acceptable distance) in A
, then it is necessary to actively reject points based on distances
, resulting in an output that would be shorter than B
. This solution seems out of scope.
Closest point in B
Compute the Euclidenan distance from each point (row) in A
to each point in B
and identify the closest point in B
:
distances = squeeze(sum(bsxfun(@minus,A,permute(B,[3 2 1])).^2,2));
[~,ik] = min(distances,[],2)
Make an array the size of A
containing these closest points in B
:
Anew = B(ik,:)
The size of Anew
in this approach is the same as A
.
Merging Similar Points in First Matrix
Another approach is to use the undocumented _mergesimpts
function.
Consider this test data:
>> B = randi(5,4,3)
B =
1 4 4
2 3 4
1 3 4
3 4 5
>> tol = 0.001;
>> A = repmat(B,3,1) + tol * rand(size(B,1)*3,3)
A =
1.0004 4.0005 4.0000
2.0004 3.0005 4.0008
1.0004 3.0009 4.0002
3.0008 4.0005 5.0004
1.0006 4.0004 4.0007
2.0008 3.0007 4.0004
1.0009 3.0007 4.0007
3.0010 4.0005 5.0004
1.0002 4.0003 4.0007
2.0001 3.0001 4.0007
1.0007 3.0006 4.0004
3.0001 4.0003 5.0000
Merge similar rows in A
according to a specified tolerance, tol
:
>> builtin('_mergesimpts',A,tol,'average')
ans =
1.0004 4.0004 4.0005
1.0007 3.0007 4.0005
2.0005 3.0005 4.0006
3.0006 4.0004 5.0003
Merge similar rows, using B
to get expected numbers
>> builtin('_mergesimpts',[A; B],tol,'first')
ans =
1 3 4
1 4 4
2 3 4
3 4 5