#include "knn.h" #include "sort.h" #include "parallel_for.h" #include #include #include #include namespace igl { template IGL_INLINE void knn(const Eigen::MatrixBase& P, size_t k, const std::vector > & point_indices, const Eigen::MatrixBase& CH, const Eigen::MatrixBase& CN, const Eigen::MatrixBase& W, Eigen::PlainObjectBase & I) { knn(P,P,k,point_indices,CH,CN,W,I); } template IGL_INLINE void knn( const Eigen::MatrixBase& P, const Eigen::MatrixBase& V, size_t k, const std::vector > & point_indices, const Eigen::MatrixBase& CH, const Eigen::MatrixBase& CN, const Eigen::MatrixBase& W, Eigen::PlainObjectBase & I) { typedef typename DerivedCN::Scalar CentersType; typedef typename DerivedW::Scalar WidthsType; using Scalar = typename DerivedP::Scalar; typedef Eigen::Matrix RowVector3PType; const size_t Psize = P.rows(); const size_t Vsize = V.rows(); if(Vsize <= k) { I.resize(Psize,Vsize); for(size_t i = 0; i < Psize; ++i) { Eigen::Matrix D = (V.rowwise() - P.row(i)).rowwise().norm(); Eigen::Matrix S; Eigen::VectorXi R; igl::sort(D,1,true,S,R); I.row(i) = R.transpose(); } return; } I.resize(Psize,k); auto distance_to_width_one_cube = [](const RowVector3PType& point) -> Scalar { return std::sqrt(std::pow(std::max(std::abs(point(0))-1,0.0),2) + std::pow(std::max(std::abs(point(1))-1,0.0),2) + std::pow(std::max(std::abs(point(2))-1,0.0),2)); }; auto distance_to_cube = [&distance_to_width_one_cube] (const RowVector3PType& point, Eigen::Matrix cube_center, WidthsType cube_width) -> Scalar { RowVector3PType transformed_point = (point-cube_center)/cube_width; return cube_width*distance_to_width_one_cube(transformed_point); }; igl::parallel_for(Psize,[&](size_t i) { int points_found = 0; RowVector3PType point_of_interest = P.row(i); //To make my priority queue take both points and octree cells, //I use the indices 0 to n-1 for the n points, // and the indices n to n+m-1 for the m octree cells // Using lambda to compare elements. auto cmp = [&point_of_interest, &V, &CN, &W, Vsize, &distance_to_cube](int left, int right) { Scalar leftdistance, rightdistance; if(left < Vsize){ //left is a point index leftdistance = (V.row(left) - point_of_interest).norm(); } else { //left is an octree cell leftdistance = distance_to_cube(point_of_interest, CN.row(left-Vsize), W(left-Vsize)); } if(right < Vsize){ //left is a point index rightdistance = (V.row(right) - point_of_interest).norm(); } else { //left is an octree cell rightdistance = distance_to_cube(point_of_interest, CN.row(right-Vsize), W(right-Vsize)); } return leftdistance > rightdistance; }; std::priority_queue, decltype(cmp)> queue(cmp); queue.push(Vsize); //This is the 0th octree cell (ie the root) while(points_found < k){ IndexType curr_cell_or_point = queue.top(); queue.pop(); if(curr_cell_or_point < Vsize){ //current index is for is a point I(i,points_found) = curr_cell_or_point; points_found++; } else { IndexType curr_cell = curr_cell_or_point - Vsize; if(CH(curr_cell,0) == -1){ //In the case of a leaf if(point_indices.at(curr_cell).size() > 0){ //Assumption: Leaves either have one point, or none queue.push(point_indices.at(curr_cell).at(0)); } } else { //Not a leaf for(int j = 0; j < 8; j++){ //+n to adjust for the octree cells queue.push(CH(curr_cell,j)+Vsize); } } } } },1000); } } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh template void igl::knn, Eigen::Matrix, int, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, unsigned long, std::vector >, std::allocator > > > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::knn, int, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, unsigned long, std::vector >, std::allocator > > > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #ifdef WIN32 template void igl::knn,int,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix >(Eigen::MatrixBase > const &,unsigned __int64,std::vector >,std::allocator > > > const &,Eigen::MatrixBase > const &,Eigen::MatrixBase > const &,Eigen::MatrixBase > const &,Eigen::PlainObjectBase > &); template void igl::knn,Eigen::Matrix,int,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix >(Eigen::MatrixBase > const &,Eigen::MatrixBase > const &,unsigned __int64,std::vector >,std::allocator > > > const &,Eigen::MatrixBase > const &,Eigen::MatrixBase > const &,Eigen::MatrixBase > const &,Eigen::PlainObjectBase > &); #endif #endif