/*
* \mainpage nanoflann C++ API documentation
* nanoflann is a C++ header-only library for building KD-Trees, mostly
* optimized for 2D or 3D point clouds.
* nanoflann does not require compiling or installing, just an
* #include <nanoflann.hpp> in your code.
* - [Online README](https://github.com/jlblancoc/nanoflann)
* - [C++ API documentation](https://jlblancoc.github.io/nanoflann/)
#
include
<
cmath
>
//
for abs()
#
include
<
cstdlib
>
//
for abs()
#
include
<
functional
>
//
std::reference_wrapper
#
include
<
limits
>
//
std::numeric_limits
#
include
<
unordered_set
>
/*
* Library version: 0xMmP (M=Major,m=minor,P=patch)
*/
#
define
NANOFLANN_VERSION
0x161
//
Avoid conflicting declaration of min/max macros in Windows headers
#
if
!defined(NOMINMAX) && \
(defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64))
//
Avoid conflicts with X11 headers
/*
* @addtogroup nanoflann_grp nanoflann C++ library for KD-trees
/*
* the PI constant (required to avoid MSVC missing symbols)
*/
return
static_cast
<T>(
3.14159265358979323846
);
* Traits if object is resizable and assignable (typically has a resize | assign
template
<
typename
T,
typename
=
int
>
struct
has_resize
: std::false_type
struct
has_resize
<T, decltype((
void
)std::declval<T>().resize(
1
),
0
)>
template
<
typename
T,
typename
=
int
>
struct
has_assign
: std::false_type
struct
has_assign
<T, decltype((
void
)std::declval<T>().assign(
1
,
0
),
0
)>
* Free function to resize a resizable object
template
<
typename
Container>
inline
typename
std::enable_if<has_resize<Container>::value,
void
>::type
resize
(
Container& c,
const
size_t
nElements)
* Free function that has no effects on non resizable containers (e.g.
* std::array) It raises an exception if the expected size does not match
template
<
typename
Container>
inline
typename
std::enable_if<!has_resize<Container>::value,
void
>::type
resize
(Container& c,
const
size_t
nElements)
if
(nElements != c.
size
())
throw
std::logic_error
(
"
Try to change the size of a std::array.
"
);
* Free function to assign to a container
template
<
typename
Container,
typename
T>
inline
typename
std::enable_if<has_assign<Container>::value,
void
>::type
assign
(
Container& c,
const
size_t
nElements,
const
T& value)
c.
assign
(nElements, value);
* Free function to assign to a std::array
template
<
typename
Container,
typename
T>
inline
typename
std::enable_if<!has_assign<Container>::value,
void
>::type
assign
(Container& c,
const
size_t
nElements,
const
T& value)
for
(
size_t
i =
0
; i < nElements; i++) c[i] = value;
/*
* operator "<" for std::sort()
*/
/*
* PairType will be typically: ResultItem<IndexType,DistanceType>
*/
template
<
typename
PairType>
bool
operator
()(
const
PairType& p1,
const
PairType& p2)
const
return
p1.
second
< p2.
second
;
* Each result element in RadiusResultSet. Note that distances and indices
* are named `first` and `second` to keep backward-compatibility with the
* `std::pair<>` type used in the past. In contrast, this structure is ensured
* to be `std::is_standard_layout` so it can be used in wrappers to other
* See: https://github.com/jlblancoc/nanoflann/issues/166
template
<
typename
IndexType =
size_t
,
typename
DistanceType =
double
>
ResultItem
() =
default
;
ResultItem
(
const
IndexType index,
const
DistanceType distance)
: first(index), second(distance)
IndexType first;
//
!< Index of the sample in the dataset
DistanceType second;
//
!< Distance from sample to query point
/*
* @addtogroup result_sets_grp Result set classes
/*
* Result set for KNN searches (N-closest neighbors)
*/
typename
_DistanceType,
typename
_IndexType =
size_t
,
typename
_CountType =
size_t
>
using
DistanceType = _DistanceType;
using
IndexType = _IndexType;
using
CountType = _CountType;
explicit
KNNResultSet
(CountType capacity_)
: indices(
nullptr
), dists(
nullptr
), capacity(capacity_), count(
0
)
void
init
(IndexType* indices_, DistanceType* dists_)
dists[capacity -
1
] = (std::numeric_limits<DistanceType>::max)();
CountType
size
()
const
{
return
count; }
bool
empty
()
const
{
return
count ==
0
; }
bool
full
()
const
{
return
count == capacity; }
* Called during search to add an element matching the criteria.
* @return true if the search should be continued, false if the results are
bool
addPoint
(DistanceType dist, IndexType index)
for
(i = count; i >
0
; --i)
/*
* If defined and two points have the same distance, the one with
* the lowest-index will be returned first.
*/
#
ifdef
NANOFLANN_FIRST_MATCH
if
((dists[i -
1
] > dist) ||
((dist == dists[i -
1
]) && (indices[i -
1
] >
index
)))
if
(dists[i -
1
] > dist)
dists[i] = dists[i -
1
];
indices[i] = indices[i -
1
];
if
(count < capacity) count++;
//
tell caller that the search shall continue
DistanceType
worstDist
()
const
{
return
dists[capacity -
1
]; }
/*
* Result set for RKNN searches (N-closest neighbors with a maximum radius)
*/
typename
_DistanceType,
typename
_IndexType =
size_t
,
typename
_CountType =
size_t
>
using
DistanceType = _DistanceType;
using
IndexType = _IndexType;
using
CountType = _CountType;
DistanceType maximumSearchDistanceSquared;
CountType capacity_, DistanceType maximumSearchDistanceSquared_)
maximumSearchDistanceSquared(maximumSearchDistanceSquared_)
void
init
(IndexType* indices_, DistanceType* dists_)
if
(capacity) dists[capacity -
1
] = maximumSearchDistanceSquared;
CountType
size
()
const
{
return
count; }
bool
empty
()
const
{
return
count ==
0
; }
bool
full
()
const
{
return
count == capacity; }
* Called during search to add an element matching the criteria.
* @return true if the search should be continued, false if the results are
bool
addPoint
(DistanceType dist, IndexType index)
for
(i = count; i >
0
; --i)
/*
* If defined and two points have the same distance, the one with
* the lowest-index will be returned first.
*/
#
ifdef
NANOFLANN_FIRST_MATCH
if
((dists[i -
1
] > dist) ||
((dist == dists[i -
1
]) && (indices[i -
1
] >
index
)))
if
(dists[i -
1
] > dist)
dists[i] = dists[i -
1
];
indices[i] = indices[i -
1
];
if
(count < capacity) count++;
//
tell caller that the search shall continue
DistanceType
worstDist
()
const
{
return
dists[capacity -
1
]; }
* A result-set class used when performing a radius based search.
template
<
typename
_DistanceType,
typename
_IndexType =
size_t
>
using
DistanceType = _DistanceType;
using
IndexType = _IndexType;
const
DistanceType radius;
std::vector<ResultItem<IndexType, DistanceType>>& m_indices_dists;
explicit
RadiusResultSet
(
std::vector<ResultItem<IndexType, DistanceType>>& indices_dists)
: radius(radius_), m_indices_dists(indices_dists)
void
init
() {
clear
(); }
void
clear
() { m_indices_dists.
clear
(); }
size_t
size
()
const
{
return
m_indices_dists.
size
(); }
size_t
empty
()
const
{
return
m_indices_dists.
empty
(); }
bool
full
()
const
{
return
true
; }
* Called during search to add an element matching the criteria.
* @return true if the search should be continued, false if the results are
bool
addPoint
(DistanceType dist, IndexType index)
if
(dist < radius) m_indices_dists.
emplace_back
(
index
, dist);
DistanceType
worstDist
()
const
{
return
radius; }
* Find the worst result (farthest neighbor) without copying or sorting
* Pre-conditions: size() > 0
ResultItem<IndexType, DistanceType>
worst_item
()
const
if
(m_indices_dists.
empty
())
throw
std::runtime_error
(
"
Cannot invoke RadiusResultSet::worst_item() on
"
"
an empty list of results.
"
);
auto
it =
std::max_element
(
m_indices_dists.
begin
(), m_indices_dists.
end
(),
IndexDist_Sorter
());
m_indices_dists.
begin
(), m_indices_dists.
end
(),
IndexDist_Sorter
());
/*
* @addtogroup loadsave_grp Load/save auxiliary functions
void
save_value
(std::ostream& stream,
const
T& value)
stream.
write
(
reinterpret_cast
<
const
char
*>(&value),
sizeof
(T));
void
save_value
(std::ostream& stream,
const
std::vector<T>& value)
size_t
size = value.
size
();
stream.
write
(
reinterpret_cast
<
const
char
*>(&size),
sizeof
(
size_t
));
stream.
write
(
reinterpret_cast
<
const
char
*>(value.
data
()),
sizeof
(T) * size);
void
load_value
(std::istream& stream, T& value)
stream.
read
(
reinterpret_cast
<
char
*>(&value),
sizeof
(T));
void
load_value
(std::istream& stream, std::vector<T>& value)
stream.
read
(
reinterpret_cast
<
char
*>(&size),
sizeof
(
size_t
));
stream.
read
(
reinterpret_cast
<
char
*>(value.
data
()),
sizeof
(T) * size);
/*
* @addtogroup metric_grp Metric (distance) classes
/*
* Manhattan distance functor (generic version, optimized for
* high-dimensionality data sets). Corresponding distance traits:
* \tparam T Type of the elements (e.g. double, float, uint8_t)
* \tparam DataSource Source of the data, i.e. where the vectors are stored
* \tparam _DistanceType Type of distance variables (must be signed)
* \tparam IndexType Type of the arguments with which the data can be
* accessed (e.g. float, double, int64_t, T*)
class
T
,
class
DataSource
,
typename
_DistanceType = T,
typename
IndexType =
uint32_t
>
using
DistanceType = _DistanceType;
const
DataSource& data_source;
L1_Adaptor
(
const
DataSource& _data_source) : data_source(_data_source) {}
DistanceType
evalMetric
(
const
T* a,
const
IndexType b_idx,
size_t
size,
DistanceType worst_dist = -
1
)
const
DistanceType result =
DistanceType
();
const
T* last = a + size;
const
T* lastgroup = last -
3
;
/*
Process 4 items with each loop for efficiency.
*/
const
DistanceType diff0 =
std::abs
(a[
0
] - data_source.
kdtree_get_pt
(b_idx, d++));
const
DistanceType diff1 =
std::abs
(a[
1
] - data_source.
kdtree_get_pt
(b_idx, d++));
const
DistanceType diff2 =
std::abs
(a[
2
] - data_source.
kdtree_get_pt
(b_idx, d++));
const
DistanceType diff3 =
std::abs
(a[
3
] - data_source.
kdtree_get_pt
(b_idx, d++));
result += diff0 + diff1 + diff2 + diff3;
if
((worst_dist >
0
) && (result > worst_dist)) {
return
result; }
/*
Process last 0-3 components. Not needed for standard vector lengths.
result +=
std::abs
(*a++ - data_source.
kdtree_get_pt
(b_idx, d++));
template
<
typename
U,
typename
V>
DistanceType
accum_dist
(
const
U a,
const
V b,
const
size_t
)
const
/*
* **Squared** Euclidean distance functor (generic version, optimized for
* high-dimensionality data sets). Corresponding distance traits:
* \tparam T Type of the elements (e.g. double, float, uint8_t)
* \tparam DataSource Source of the data, i.e. where the vectors are stored
* \tparam _DistanceType Type of distance variables (must be signed)
* \tparam IndexType Type of the arguments with which the data can be
* accessed (e.g. float, double, int64_t, T*)
class
T
,
class
DataSource
,
typename
_DistanceType = T,
typename
IndexType =
uint32_t
>
using
DistanceType = _DistanceType;
const
DataSource& data_source;
L2_Adaptor
(
const
DataSource& _data_source) : data_source(_data_source) {}
DistanceType
evalMetric
(
const
T* a,
const
IndexType b_idx,
size_t
size,
DistanceType worst_dist = -
1
)
const
DistanceType result =
DistanceType
();
const
T* last = a + size;
const
T* lastgroup = last -
3
;
/*
Process 4 items with each loop for efficiency.
*/
const
DistanceType diff0 =
a[
0
] - data_source.
kdtree_get_pt
(b_idx, d++);
const
DistanceType diff1 =
a[
1
] - data_source.
kdtree_get_pt
(b_idx, d++);
const
DistanceType diff2 =
a[
2
] - data_source.
kdtree_get_pt
(b_idx, d++);
const
DistanceType diff3 =
a[
3
] - data_source.
kdtree_get_pt
(b_idx, d++);
diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
if
((worst_dist >
0
) && (result > worst_dist)) {
return
result; }
/*
Process last 0-3 components. Not needed for standard vector lengths.
const
DistanceType diff0 =
*a++ - data_source.
kdtree_get_pt
(b_idx, d++);
template
<
typename
U,
typename
V>
DistanceType
accum_dist
(
const
U a,
const
V b,
const
size_t
)
const
return
(a - b) * (a - b);
/*
* **Squared** Euclidean (L2) distance functor (suitable for low-dimensionality
* datasets, like 2D or 3D point clouds) Corresponding distance traits:
* nanoflann::metric_L2_Simple
* \tparam T Type of the elements (e.g. double, float, uint8_t)
* \tparam DataSource Source of the data, i.e. where the vectors are stored
* \tparam _DistanceType Type of distance variables (must be signed)
* \tparam IndexType Type of the arguments with which the data can be
* accessed (e.g. float, double, int64_t, T*)
class
T
,
class
DataSource
,
typename
_DistanceType = T,
typename
IndexType =
uint32_t
>
using
DistanceType = _DistanceType;
const
DataSource& data_source;
L2_Simple_Adaptor
(
const
DataSource& _data_source)
: data_source(_data_source)
DistanceType
evalMetric
(
const
T* a,
const
IndexType b_idx,
size_t
size)
const
DistanceType result =
DistanceType
();
for
(
size_t
i =
0
; i < size; ++i)
const
DistanceType diff =
a[i] - data_source.
kdtree_get_pt
(b_idx, i);
template
<
typename
U,
typename
V>
DistanceType
accum_dist
(
const
U a,
const
V b,
const
size_t
)
const
return
(a - b) * (a - b);
/*
* SO2 distance functor
* Corresponding distance traits: nanoflann::metric_SO2
* \tparam T Type of the elements (e.g. double, float, uint8_t)
* \tparam DataSource Source of the data, i.e. where the vectors are stored
* \tparam _DistanceType Type of distance variables (must be signed) (e.g.
* float, double) orientation is constrained to be in [-pi, pi]
* \tparam IndexType Type of the arguments with which the data can be
* accessed (e.g. float, double, int64_t, T*)
class
T
,
class
DataSource
,
typename
_DistanceType = T,
typename
IndexType =
uint32_t
>
using
DistanceType = _DistanceType;
const
DataSource& data_source;
SO2_Adaptor
(
const
DataSource& _data_source) : data_source(_data_source) {}
DistanceType
evalMetric
(
const
T* a,
const
IndexType b_idx,
size_t
size)
const
a[size -
1
], data_source.
kdtree_get_pt
(b_idx, size -
1
), size -
1
);
/*
* Note: this assumes that input angles are already in the range [-pi,pi]
template
<
typename
U,
typename
V>
DistanceType
accum_dist
(
const
U a,
const
V b,
const
size_t
)
const
DistanceType result =
DistanceType
();
DistanceType PI = pi_const<DistanceType>();
/*
* SO3 distance functor (Uses L2_Simple)
* Corresponding distance traits: nanoflann::metric_SO3
* \tparam T Type of the elements (e.g. double, float, uint8_t)
* \tparam DataSource Source of the data, i.e. where the vectors are stored
* \tparam _DistanceType Type of distance variables (must be signed) (e.g.
* \tparam IndexType Type of the arguments with which the data can be
* accessed (e.g. float, double, int64_t, T*)
class
T
,
class
DataSource
,
typename
_DistanceType = T,
typename
IndexType =
uint32_t
>
using
DistanceType = _DistanceType;
L2_Simple_Adaptor<T, DataSource, DistanceType, IndexType>
SO3_Adaptor
(
const
DataSource& _data_source)
: distance_L2_Simple(_data_source)
DistanceType
evalMetric
(
const
T* a,
const
IndexType b_idx,
size_t
size)
const
return
distance_L2_Simple.
evalMetric
(a, b_idx, size);
template
<
typename
U,
typename
V>
DistanceType
accum_dist
(
const
U a,
const
V b,
const
size_t
idx)
const
return
distance_L2_Simple.
accum_dist
(a, b, idx);
/*
* Metaprogramming helper traits class for the L1 (Manhattan) metric
*/
struct
metric_L1
:
public
Metric
template
<
class
T
,
class
DataSource
,
typename
IndexType =
uint32_t
>
using
distance_t
= L1_Adaptor<T, DataSource, T, IndexType>;
/*
* Metaprogramming helper traits class for the L2 (Euclidean) **squared**
struct
metric_L2
:
public
Metric
template
<
class
T
,
class
DataSource
,
typename
IndexType =
uint32_t
>
using
distance_t
= L2_Adaptor<T, DataSource, T, IndexType>;
/*
* Metaprogramming helper traits class for the L2_simple (Euclidean)
* **squared** distance metric
*/
struct
metric_L2_Simple
:
public
Metric
template
<
class
T
,
class
DataSource
,
typename
IndexType =
uint32_t
>
using
distance_t
= L2_Simple_Adaptor<T, DataSource, T, IndexType>;
/*
* Metaprogramming helper traits class for the SO3_InnerProdQuat metric
*/
struct
metric_SO2
:
public
Metric
template
<
class
T
,
class
DataSource
,
typename
IndexType =
uint32_t
>
using
distance_t
= SO2_Adaptor<T, DataSource, T, IndexType>;
/*
* Metaprogramming helper traits class for the SO3_InnerProdQuat metric
*/
struct
metric_SO3
:
public
Metric
template
<
class
T
,
class
DataSource
,
typename
IndexType =
uint32_t
>
using
distance_t
= SO3_Adaptor<T, DataSource, T, IndexType>;
/*
* @addtogroup param_grp Parameter structs
enum
class
KDTreeSingleIndexAdaptorFlags
SkipInitialBuildIndex =
1
inline
std::underlying_type<KDTreeSingleIndexAdaptorFlags>::type
operator
&(
KDTreeSingleIndexAdaptorFlags lhs, KDTreeSingleIndexAdaptorFlags rhs)
typename
std::underlying_type<KDTreeSingleIndexAdaptorFlags>::type;
return
static_cast
<underlying>(lhs) &
static_cast
<underlying>(rhs);
/*
* Parameters (see README.md)
*/
struct
KDTreeSingleIndexAdaptorParams
KDTreeSingleIndexAdaptorParams
(
size_t
_leaf_max_size =
10
,
KDTreeSingleIndexAdaptorFlags _flags =
KDTreeSingleIndexAdaptorFlags::None,
unsigned
int
_n_thread_build =
1
)
: leaf_max_size(_leaf_max_size),
n_thread_build(_n_thread_build)
KDTreeSingleIndexAdaptorFlags flags;
unsigned
int
n_thread_build;
/*
* Search options for KDTreeSingleIndexAdaptor::findNeighbors()
*/
SearchParameters
(
float
eps_ =
0
,
bool
sorted_ =
true
)
: eps(eps_), sorted(sorted_)
float
eps;
//
!< search for eps-approximate neighbours (default: 0)
bool
sorted;
//
!< only for radius search, require neighbours sorted by
//
!< distance (default: true)
/*
* @addtogroup memalloc_grp Memory allocation
* Pooled storage allocator
* The following routines allow for the efficient allocation of storage in
* small chunks from a specified pool. Rather than allowing each structure
* to be freed individually, an entire pool of storage is freed at once.
* This method has two advantages over just using malloc() and free(). First,
* it is far more efficient for allocating small objects, as there is
* no overhead for remembering all the information needed to free each
* object or consolidating fragmented memory. Second, the decision about
* how long to keep an object is made at the time of allocation, and there
* is no need to track down all the objects to free them.
static
constexpr
size_t
WORDSIZE =
16
;
//
WORDSIZE must >= 8
static
constexpr
size_t
BLOCKSIZE =
8192
;
/*
We maintain memory alignment to word boundaries by requiring that all
allocations be in multiples of the machine wordsize.
*/
/*
Size of machine word in bytes. Must be power of 2.
*/
/*
Minimum number of bytes requested at a time from the system. Must be
* multiple of WORDSIZE.
*/
Size
remaining_ =
0
;
//
!< Number of bytes left in current block of storage
void
* base_ =
nullptr
;
//
!< Pointer to base of current block of storage
void
* loc_ =
nullptr
;
//
!< Current location in block to next allocate
Default constructor. Initializes a new pool.
PooledAllocator
() {
internal_init
(); }
* Destructor. Frees all the memory allocated in this pool.
~PooledAllocator
() {
free_all
(); }
/*
* Frees all allocated memory chunks
*/
while
(base_ !=
nullptr
)
//
Get pointer to prev block
void
* prev = *(
static_cast
<
void
**>(base_));
* Returns a pointer to a piece of new memory of the given size in bytes
* allocated from the pool.
void
*
malloc
(
const
size_t
req_size)
/*
Round size up to a multiple of wordsize. The following expression
only works for WORDSIZE that is a power of 2, by masking last bits
of incremented size to zero.
const
Size
size = (req_size + (WORDSIZE -
1
)) & ~(WORDSIZE -
1
);
/*
Check whether a new block must be allocated. Note that the first
word of a block is reserved for a pointer to the previous block.
wastedMemory += remaining_;
/*
Allocate new storage.
*/
size > BLOCKSIZE ? size + WORDSIZE : BLOCKSIZE + WORDSIZE;
//
use the standard C malloc to allocate memory
void
* m = ::
malloc
(blocksize);
fprintf
(stderr,
"
Failed to allocate memory.
\n
"
);
/*
Fill first word of new block with pointer to previous block.
*/
static_cast
<
void
**>(m)[
0
] = base_;
remaining_ = blocksize - WORDSIZE;
loc_ =
static_cast
<
char
*>(m) + WORDSIZE;
loc_ =
static_cast
<
char
*>(loc_) + size;
* Allocates (using this pool) a generic type T.
* count = number of instances to allocate.
* Returns: pointer (of type T*) to memory buffer
T*
allocate
(
const
size_t
count =
1
)
T* mem =
static_cast
<T*>(
this
->
malloc
(
sizeof
(T) * count));
/*
* @addtogroup nanoflann_metaprog_grp Auxiliary metaprogramming stuff
/*
* Used to declare fixed-size arrays when DIM>0, dynamically-allocated vectors
* when DIM=-1. Fixed size version for a generic DIM:
template
<
int32_t
DIM,
typename
T>
using
type = std::array<T, DIM>;
/*
* Dynamic size version
*/
struct
array_or_vector
<-
1
, T>
using
type = std::vector<T>;
* Contains the member functions common to the classes KDTreeSingleIndexAdaptor
* and KDTreeSingleIndexDynamicAdaptor_.
* \tparam Derived The name of the class which inherits this class.
* \tparam DatasetAdaptor The user-provided adaptor, which must be ensured to
* have a lifetime equal or longer than the instance of this class.
* \tparam Distance The distance metric to use, these are all classes derived
* \tparam DIM Dimensionality of data points (e.g. 3 for 3D points)
* \tparam IndexType Type of the arguments with which the data can be
* accessed (e.g. float, double, int64_t, T*)
class
Derived
,
typename
Distance,
class
DatasetAdaptor
,
int32_t
DIM = -
1
,
typename
index_t
=
uint32_t
>