相关文章推荐
/* * \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.
*
* See:
* - [Online README](https://github.com/jlblancoc/nanoflann)
* - [C++ API documentation](https://jlblancoc.github.io/nanoflann/)
*/
# pragma once
# include < algorithm >
# include < array >
# include < atomic >
# include < cassert >
# include < cmath > // for abs()
# include < cstdint >
# include < cstdlib > // for abs()
# include < functional > // std::reference_wrapper
# include < future >
# include < istream >
# include < limits > // std::numeric_limits
# include < ostream >
# include < stdexcept >
# include < unordered_set >
# include < vector >
/* * 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))
# define NOMINMAX
# ifdef max
# undef max
# undef min
# endif
# endif
// Avoid conflicts with X11 headers
# ifdef None
# undef None
# endif
namespace nanoflann
{
/* * @addtogroup nanoflann_grp nanoflann C++ library for KD-trees
* @{ */
/* * the PI constant (required to avoid MSVC missing symbols) */
template < typename T>
T pi_const ()
{
return static_cast <T>( 3.14159265358979323846 );
}
/* *
* Traits if object is resizable and assignable (typically has a resize | assign
* method)
*/
template < typename T, typename = int >
struct has_resize : std::false_type
{
};
template < typename T>
struct has_resize <T, decltype(( void )std::declval<T>().resize( 1 ), 0 )>
: std::true_type
{
};
template < typename T, typename = int >
struct has_assign : std::false_type
{
};
template < typename T>
struct has_assign <T, decltype(( void )std::declval<T>().assign( 1 , 0 ), 0 )>
: std::true_type
{
};
/* *
* 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)
{
c. resize (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() */
struct IndexDist_Sorter
{
/* * 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
* languages.
* See: https://github.com/jlblancoc/nanoflann/issues/166
*/
template < typename IndexType = size_t , typename DistanceType = double >
struct ResultItem
{
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) */
template <
typename _DistanceType, typename _IndexType = size_t ,
typename _CountType = size_t >
class KNNResultSet
{
public:
using DistanceType = _DistanceType;
using IndexType = _IndexType;
using CountType = _CountType;
private:
IndexType* indices;
DistanceType* dists;
CountType capacity;
CountType count;
public:
explicit KNNResultSet (CountType capacity_)
: indices( nullptr ), dists( nullptr ), capacity(capacity_), count( 0 )
{
}
void init (IndexType* indices_, DistanceType* dists_)
{
indices = indices_;
dists = dists_;
count = 0 ;
if (capacity)
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
* sufficient
*/
bool addPoint (DistanceType dist, IndexType index)
{
CountType i;
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 )))
{
# else
if (dists[i - 1 ] > dist)
{
#endif
if (i < capacity)
{
dists[i] = dists[i - 1 ];
indices[i] = indices[i - 1 ];
}
}
else
break ;
}
if (i < capacity)
{
dists[i] = dist;
indices[i] = index ;
}
if (count < capacity) count++;
// tell caller that the search shall continue
return true ;
}
DistanceType worstDist () const { return dists[capacity - 1 ]; }
void sort ()
{
// already sorted
}
};
/* * Result set for RKNN searches (N-closest neighbors with a maximum radius) */
template <
typename _DistanceType, typename _IndexType = size_t ,
typename _CountType = size_t >
class RKNNResultSet
{
public:
using DistanceType = _DistanceType;
using IndexType = _IndexType;
using CountType = _CountType;
private:
IndexType* indices;
DistanceType* dists;
CountType capacity;
CountType count;
DistanceType maximumSearchDistanceSquared;
public:
explicit RKNNResultSet (
CountType capacity_, DistanceType maximumSearchDistanceSquared_)
: indices( nullptr ),
dists( nullptr ),
capacity(capacity_),
count( 0 ),
maximumSearchDistanceSquared(maximumSearchDistanceSquared_)
{
}
void init (IndexType* indices_, DistanceType* dists_)
{
indices = indices_;
dists = dists_;
count = 0 ;
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
* sufficient
*/
bool addPoint (DistanceType dist, IndexType index)
{
CountType i;
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 )))
{
# else
if (dists[i - 1 ] > dist)
{
#endif
if (i < capacity)
{
dists[i] = dists[i - 1 ];
indices[i] = indices[i - 1 ];
}
}
else
break ;
}
if (i < capacity)
{
dists[i] = dist;
indices[i] = index ;
}
if (count < capacity) count++;
// tell caller that the search shall continue
return true ;
}
DistanceType worstDist () const { return dists[capacity - 1 ]; }
void sort ()
{
// already sorted
}
};
/* *
* A result-set class used when performing a radius based search.
*/
template < typename _DistanceType, typename _IndexType = size_t >
class RadiusResultSet
{
public:
using DistanceType = _DistanceType;
using IndexType = _IndexType;
public:
const DistanceType radius;
std::vector<ResultItem<IndexType, DistanceType>>& m_indices_dists;
explicit RadiusResultSet (
DistanceType radius_,
std::vector<ResultItem<IndexType, DistanceType>>& indices_dists)
: radius(radius_), m_indices_dists(indices_dists)
{
init ();
}
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
* sufficient
*/
bool addPoint (DistanceType dist, IndexType index)
{
if (dist < radius) m_indices_dists. emplace_back ( index , dist);
return true ;
}
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 ());
return *it;
}
void sort ()
{
std::sort (
m_indices_dists. begin (), m_indices_dists. end (), IndexDist_Sorter ());
}
};
/* * @} */
/* * @addtogroup loadsave_grp Load/save auxiliary functions
* @{ */
template < typename T>
void save_value (std::ostream& stream, const T& value)
{
stream. write ( reinterpret_cast < const char *>(&value), sizeof (T));
}
template < typename 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);
}
template < typename T>
void load_value (std::istream& stream, T& value)
{
stream. read ( reinterpret_cast < char *>(&value), sizeof (T));
}
template < typename T>
void load_value (std::istream& stream, std::vector<T>& value)
{
size_t size;
stream. read ( reinterpret_cast < char *>(&size), sizeof ( size_t ));
value. resize (size);
stream. read ( reinterpret_cast < char *>(value. data ()), sizeof (T) * size);
}
/* * @} */
/* * @addtogroup metric_grp Metric (distance) classes
* @{ */
struct Metric
{
};
/* * Manhattan distance functor (generic version, optimized for
* high-dimensionality data sets). Corresponding distance traits:
* nanoflann::metric_L1
*
* \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*)
*/
template <
class T , class DataSource , typename _DistanceType = T,
typename IndexType = uint32_t >
struct L1_Adaptor
{
using ElementType = 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 ;
size_t d = 0 ;
/* Process 4 items with each loop for efficiency. */
while (a < lastgroup)
{
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;
a += 4 ;
if ((worst_dist > 0 ) && (result > worst_dist)) { return result; }
}
/* Process last 0-3 components. Not needed for standard vector lengths.
*/
while (a < last)
{
result += std::abs (*a++ - data_source. kdtree_get_pt (b_idx, d++));
}
return result;
}
template < typename U, typename V>
DistanceType accum_dist ( const U a, const V b, const size_t ) const
{
return std::abs (a - b);
}
};
/* * **Squared** Euclidean distance functor (generic version, optimized for
* high-dimensionality data sets). Corresponding distance traits:
* nanoflann::metric_L2
*
* \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*)
*/
template <
class T , class DataSource , typename _DistanceType = T,
typename IndexType = uint32_t >
struct L2_Adaptor
{
using ElementType = 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 ;
size_t d = 0 ;
/* Process 4 items with each loop for efficiency. */
while (a < lastgroup)
{
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++);
result +=
diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
a += 4 ;
if ((worst_dist > 0 ) && (result > worst_dist)) { return result; }
}
/* Process last 0-3 components. Not needed for standard vector lengths.
*/
while (a < last)
{
const DistanceType diff0 =
*a++ - data_source. kdtree_get_pt (b_idx, d++);
result += diff0 * diff0;
}
return result;
}
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*)
*/
template <
class T , class DataSource , typename _DistanceType = T,
typename IndexType = uint32_t >
struct L2_Simple_Adaptor
{
using ElementType = 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);
result += diff * diff;
}
return result;
}
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*)
*/
template <
class T , class DataSource , typename _DistanceType = T,
typename IndexType = uint32_t >
struct SO2_Adaptor
{
using ElementType = 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
{
return accum_dist (
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>();
result = b - a;
if (result > PI)
result -= 2 * PI;
else if (result < -PI)
result += 2 * PI;
return result;
}
};
/* * 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.
* float, double)
* \tparam IndexType Type of the arguments with which the data can be
* accessed (e.g. float, double, int64_t, T*)
*/
template <
class T , class DataSource , typename _DistanceType = T,
typename IndexType = uint32_t >
struct SO3_Adaptor
{
using ElementType = T;
using DistanceType = _DistanceType;
L2_Simple_Adaptor<T, DataSource, DistanceType, IndexType>
distance_L2_Simple;
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 >
struct traits
{
using distance_t = L1_Adaptor<T, DataSource, T, IndexType>;
};
};
/* * Metaprogramming helper traits class for the L2 (Euclidean) **squared**
* distance metric */
struct metric_L2 : public Metric
{
template < class T , class DataSource , typename IndexType = uint32_t >
struct traits
{
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 >
struct traits
{
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 >
struct traits
{
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 >
struct traits
{
using distance_t = SO3_Adaptor<T, DataSource, T, IndexType>;
};
};
/* * @} */
/* * @addtogroup param_grp Parameter structs
* @{ */
enum class KDTreeSingleIndexAdaptorFlags
{
None = 0 ,
SkipInitialBuildIndex = 1
};
inline std::underlying_type<KDTreeSingleIndexAdaptorFlags>::type operator &(
KDTreeSingleIndexAdaptorFlags lhs, KDTreeSingleIndexAdaptorFlags rhs)
{
using underlying =
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),
flags (_flags),
n_thread_build(_n_thread_build)
{
}
size_t leaf_max_size;
KDTreeSingleIndexAdaptorFlags flags;
unsigned int n_thread_build;
};
/* * Search options for KDTreeSingleIndexAdaptor::findNeighbors() */
struct SearchParameters
{
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.
*
*/
class PooledAllocator
{
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. */
using Size = size_t ;
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
void internal_init ()
{
remaining_ = 0 ;
base_ = nullptr ;
usedMemory = 0 ;
wastedMemory = 0 ;
}
public:
Size usedMemory = 0 ;
Size wastedMemory = 0 ;
/* *
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 */
void free_all ()
{
while (base_ != nullptr )
{
// Get pointer to prev block
void * prev = *( static_cast < void **>(base_));
::free (base_);
base_ = prev;
}
internal_init ();
}
/* *
* 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.
*/
if (size > remaining_)
{
wastedMemory += remaining_;
/* Allocate new storage. */
const Size blocksize =
size > BLOCKSIZE ? size + WORDSIZE : BLOCKSIZE + WORDSIZE;
// use the standard C malloc to allocate memory
void * m = :: malloc (blocksize);
if (!m)
{
fprintf (stderr, " Failed to allocate memory. \n " );
throw std::bad_alloc ();
}
/* Fill first word of new block with pointer to previous block. */
static_cast < void **>(m)[ 0 ] = base_;
base_ = m;
remaining_ = blocksize - WORDSIZE;
loc_ = static_cast < char *>(m) + WORDSIZE;
}
void * rloc = loc_;
loc_ = static_cast < char *>(loc_) + size;
remaining_ -= size;
usedMemory += size;
return rloc;
}
/* *
* Allocates (using this pool) a generic type T.
*
* Params:
* count = number of instances to allocate.
* Returns: pointer (of type T*) to memory buffer
*/
template < typename T>
T* allocate ( const size_t count = 1 )
{
T* mem = static_cast <T*>( this -> malloc ( sizeof (T) * count));
return mem;
}
};
/* * @} */
/* * @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>
struct array_or_vector
{
using type = std::array<T, DIM>;
};
/* * Dynamic size version */
template < typename T>
struct array_or_vector <- 1 , T>
{
using type = std::vector<T>;
};
/* * @} */
/* * kd-tree base-class
*
* 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
* from nanoflann::Metric
* \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*)
*/
template <
class Derived , typename Distance, class DatasetAdaptor , int32_t DIM = - 1 ,
typename index_t = uint32_t >
class KDTreeBaseClass
 
推荐文章