EmanyAlpsid
EmanyAlpsid

Reputation: 11

How to create a vector of nanoflann's KDTrees in C++?

I have several sets of points and I want to quickly compute distances to these sets. In the case of only one set I have been successfully using nanoflann for the task. But when trying to define a vector of KDTree I get an error. This is a minimal example:

#include <string>
#include <nanoflann.hpp>

using std::string;
using std::vector;

template <typename T=double>
struct Point {
    T x;
    T y;
    T z;
};

template <typename T>
struct PointCloud{
    vector<Point<double>> points;
    inline size_t kdtree_get_point_count() const {
        return points.size();
    }
    inline double kdtree_get_pt(const size_t idx, int dim) const {
        switch(dim) {
            case 0:
                return points[idx].x;
            case 1:
                return points[idx].y;
            case 2:
                return points[idx].z;
            default:
                return static_cast<T>(0.0);
        }
    }
    template <class BBOX>
    bool kdtree_get_bbox(BBOX& /* bb */) const {
        return false;
    }
};

using KDTree = nanoflann::KDTreeSingleIndexAdaptor<
    nanoflann::L2_Simple_Adaptor<double, PointCloud<double>>,
    PointCloud<double>, 3>;


int main() {
    vector<Point<double>> points1 {{0.0, 0.0, 0.0}, {0.0, 1.0, 1.0}, {1.0, 0.0, -1.0}};
    vector<Point<double>> points2 {{0.3, 0.4, 0.0}, {0.0, 1.0, 1.0}, {1.0, 0.0, -1.0}};
    vector<Point<double>> points3 {{0.0, 0.8, 0.9}, {0.3, 1.0, 1.1}, {1.9, 0.3, -1.0}};
    vector<vector<Point<double>>> points_sets {points1, points2, points3};

    vector<KDTree> kdtrees;
    nanoflann::KDTreeSingleIndexAdaptorParams params{10};
    for(int index {0}; index < 3; index++) {
        PointCloud<double> pc {};
        pc.points = points_sets[index];
        KDTree kdtree(3, pc, params);
        kdtrees.push_back(kdtree);
        kdtrees.back().buildIndex();
    }
}

and I get this error message:

In file included from /usr/include/x86_64-linux-gnu/c++/11/bits/c++allocator.h:33,
                 from /usr/include/c++/11/bits/allocator.h:46,
                 from /usr/include/c++/11/string:41,
                 from src/main.cpp:1:
/usr/include/c++/11/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>; _Args = {const nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double>, double, unsigned int>, PointCloud<double>, 3, unsigned int>&}; _Tp = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>]’:
/usr/include/c++/11/bits/alloc_traits.h:516:17:   required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>; _Args = {const nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double>, double, unsigned int>, PointCloud<double>, 3, unsigned int>&}; _Tp = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3> >]’
/usr/include/c++/11/bits/stl_vector.h:1192:30:   required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>; _Alloc = std::allocator<nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3> >; std::vector<_Tp, _Alloc>::value_type = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>]’
src/main.cpp:55:26:   required from here
/usr/include/c++/11/ext/new_allocator.h:162:11: error: use of deleted function ‘nanoflann::KDTreeSingleIndexAdaptor<Distance, DatasetAdaptor, DIM, AccessorType>::KDTreeSingleIndexAdaptor(const nanoflann::KDTreeSingleIndexAdaptor<Distance, DatasetAdaptor, DIM, AccessorType>&) [with Distance = nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >; DatasetAdaptor = PointCloud<double>; int DIM = 3; AccessorType = unsigned int]’
  162 |         { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from src/main.cpp:2:
/usr/include/nanoflann.hpp:1284:5: note: declared here
 1284 |     KDTreeSingleIndexAdaptor(const KDTreeSingleIndexAdaptor<
      |     ^~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/11/vector:66,
                 from /usr/include/c++/11/functional:62,
                 from /usr/include/c++/11/pstl/glue_algorithm_defs.h:13,
                 from /usr/include/c++/11/algorithm:74,
                 from /usr/include/nanoflann.hpp:47,
                 from src/main.cpp:2:
/usr/include/c++/11/bits/stl_uninitialized.h: In instantiation of ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>*>; _ForwardIterator = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>*]’:
/usr/include/c++/11/bits/stl_uninitialized.h:333:37:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>*>; _ForwardIterator = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>*; _Tp = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>]’
/usr/include/c++/11/bits/stl_uninitialized.h:355:2:   required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>*; _ForwardIterator = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>*; _Allocator = std::allocator<nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3> >]’
/usr/include/c++/11/bits/vector.tcc:474:3:   required from ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double>, double, unsigned int>, PointCloud<double>, 3, unsigned int>&}; _Tp = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>; _Alloc = std::allocator<nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3> >; std::vector<_Tp, _Alloc>::iterator = std::vector<nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3> >::iterator]’
/usr/include/c++/11/bits/stl_vector.h:1198:21:   required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>; _Alloc = std::allocator<nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3> >; std::vector<_Tp, _Alloc>::value_type = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud<double> >, PointCloud<double>, 3>]’
src/main.cpp:55:26:   required from here
/usr/include/c++/11/bits/stl_uninitialized.h:138:72: error: static assertion failed: result type must be constructible from value type of input range
  138 |       static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
      |                                                                        ^~~~~
/usr/include/c++/11/bits/stl_uninitialized.h:138:72: note: ‘std::integral_constant<bool, false>::value’ evaluates to false

I think the problem is that the KDTree have the copy constructor deleted, so I tried using emplace_back() instead of push_back with the same parameters I would use to make a single KDTree but that doesn't work either.

Upvotes: 1

Views: 101

Answers (0)

Related Questions