Return Unique Element with a Tolerance

With R2015a, this question finally has a simple answer (see my other answer to this question for details). For releases prior to R2015a, there is such a built-in (undocumented) function: _mergesimpts. A safe guess at the composition of the name is “merge similar points”.

The function is called with the following syntax:

xMerged = builtin('_mergesimpts',x,tol,[type])

The data array x is N-by-D, where N is the number of points, and D is the number of dimensions. The tolerances for each dimension are specified by a D-element row vector, tol. The optional input argument type is a string ('first' (default) or 'average') indicating how to merge similar elements.

The output xMerged will be M-by-D, where M<=N. It is sorted.

Examples, 1D data:

>> x = [1; 1.1; 1.05];             % elements need not be sorted
>> builtin('_mergesimpts',x,eps)   % but the output is sorted
ans =
    1.0000
    1.0500
    1.1000

Merge types:

>> builtin('_mergesimpts',x,0.1,'first')
ans =
    1.0000  % first of [1, 1.05] since abs(1 - 1.05) < 0.1
    1.1000
>> builtin('_mergesimpts',x,0.1,'average')
ans =
    1.0250  % average of [1, 1.05]
    1.1000
>> builtin('_mergesimpts',x,0.2,'average')
ans =
    1.0500  % average of [1, 1.1, 1.05]

Examples, 2D data:

>> x = [1 2; 1.06 2; 1.1 2; 1.1 2.03]
x =
    1.0000    2.0000
    1.0600    2.0000
    1.1000    2.0000
    1.1000    2.0300

All 2D points unique to machine precision:

>> xMerged = builtin('_mergesimpts',x,[eps eps],'first')
xMerged =
    1.0000    2.0000
    1.0600    2.0000
    1.1000    2.0000
    1.1000    2.0300

Merge based on second dimension tolerance:

>> xMerged = builtin('_mergesimpts',x,[eps 0.1],'first')
xMerged =
    1.0000    2.0000
    1.0600    2.0000
    1.1000    2.0000   % first of rows 3 and 4
>> xMerged = builtin('_mergesimpts',x,[eps 0.1],'average')
xMerged =
    1.0000    2.0000
    1.0600    2.0000
    1.1000    2.0150   % average of rows 3 and 4

Merge based on first dimension tolerance:

>> xMerged = builtin('_mergesimpts',x,[0.2 eps],'average')
xMerged =
    1.0533    2.0000   % average of rows 1 to 3
    1.1000    2.0300
>> xMerged = builtin('_mergesimpts',x,[0.05 eps],'average')
xMerged =
    1.0000    2.0000
    1.0800    2.0000   % average of rows 2 and 3
    1.1000    2.0300   % row 4 not merged because of second dimension

Merge based on both dimensions:

>> xMerged = builtin('_mergesimpts',x,[0.05 .1],'average')
xMerged =
    1.0000    2.0000
    1.0867    2.0100   % average of rows 2 to 4

Leave a Comment