12 #ifndef MFEM_KDTREE_HPP 13 #define MFEM_KDTREE_HPP 29 template <
typename T
float,
int ndim>
35 for (
int i=1; i<ndim; i++)
44 template<
typename T
float,
int ndim>
51 for (
int i=1; i<ndim; i++)
60 template<
typename T
float,
int ndim>
66 if (xx[0]<Tfloat(0.0)) { tm=-xx[0];}
68 for (
int i=1; i<ndim; i++)
70 if (xx[i]<Tfloat(0.0))
72 if (tm<(-xx[i])) {tm=-xx[i];}
76 if (tm<xx[i]) {tm=xx[i];}
96 template <
typename Tindex,
typename Tfloat,
size_t ndim=3,
97 typename Tnorm=KDTreeNorms::Norm_l2<Tfloat,ndim> >
135 typedef typename std::vector<NodeND>::iterator
iterator;
165 SortInPlace(data.begin(),data.end(),0);
181 for (
size_t i=0; i<ndim; i++)
192 PointS best_candidate;
193 best_candidate.sp=pt;
195 best_candidate.pos =0;
196 best_candidate.dist=Dist(data[0].pt, best_candidate.sp);
197 best_candidate.level=0;
198 PSearch(data.begin(), data.end(), 0, best_candidate);
199 return data[best_candidate.pos].ind;
205 PointS best_candidate;
206 best_candidate.sp=pt;
208 best_candidate.pos =0;
209 best_candidate.dist=Dist(data[0].pt, best_candidate.sp);
210 best_candidate.level=0;
211 PSearch(data.begin(), data.end(), 0, best_candidate);
213 clp=data[best_candidate.pos].pt;
214 return data[best_candidate.pos].ind;
228 PointS best_candidate;
229 best_candidate.sp=pt;
231 best_candidate.pos =0;
232 best_candidate.dist=Dist(data[0].pt, best_candidate.sp);
233 best_candidate.level=0;
234 PSearch(data.begin(), data.end(), 0, best_candidate);
236 ind=data[best_candidate.pos].ind;
237 dist=best_candidate.dist;
238 clp=data[best_candidate.pos].pt;
245 PointS best_candidate;
246 best_candidate.sp=pt;
248 best_candidate.pos =0;
249 best_candidate.dist=Dist(data[0].pt, best_candidate.sp);
251 for (
auto iti=data.begin()+1; iti!=data.end(); iti++)
253 dd=Dist(iti->pt, best_candidate.sp);
254 if (dd<best_candidate.dist)
256 best_candidate.pos=iti-data.begin();
257 best_candidate.dist=dd;
261 ind=data[best_candidate.pos].ind;
262 dist=best_candidate.dist;
268 std::vector<Tfloat> & dist)
282 std::vector<Tfloat> & dist)
285 for (
auto iti=data.begin(); iti!=data.end(); iti++)
287 dd=Dist(iti->pt, pt);
290 res.push_back(iti->ind);
300 for (
auto iti=data.begin(); iti!=data.end(); iti++)
302 dd=Dist(iti->pt, pt);
305 res.push_back(iti->ind);
320 CompN(std::uint8_t dd):
dim(dd) {}
323 bool operator() (
const PointND& p1,
const PointND& p2)
325 return p1.xx[
dim]<p2.xx[
dim];
329 bool operator() (
const NodeND& n1,
const NodeND& n2)
331 return n1.pt.xx[
dim]<n2.pt.xx[
dim];
340 Tfloat Dist(
const PointND& pt1,
const PointND& pt2)
342 for (
size_t i=0; i<ndim; i++)
344 tp.xx[i]=pt1.xx[i]-pt2.xx[i];
350 std::vector<NodeND> data;
354 Tfloat FindMedian(
typename std::vector<NodeND>::iterator itb,
355 typename std::vector<NodeND>::iterator ite,
359 std::nth_element(itb, itb+siz/2, ite, CompN(cdim));
360 return itb->pt.xx[cdim];
364 void SortInPlace(
typename std::vector<NodeND>::iterator itb,
365 typename std::vector<NodeND>::iterator ite,
368 std::uint8_t cdim=(std::uint8_t)(level%ndim);
372 std::nth_element(itb, itb+siz/2, ite, CompN(cdim));
374 SortInPlace(itb, itb+siz/2, level);
375 SortInPlace(itb+siz/2+1,ite, level);
390 void PSearch(
typename std::vector<NodeND>::iterator itb,
391 typename std::vector<NodeND>::iterator ite,
392 size_t level, PointS& bc)
394 std::uint8_t
dim=(std::uint8_t) (level%ndim);
396 typename std::vector<NodeND>::iterator mtb=itb+siz/2;
401 if ((bc.sp.xx[
dim]-bc.dist)>mtb->pt.xx[
dim])
403 PSearch(itb+siz/2+1, ite, level, bc);
405 else if ((bc.sp.xx[
dim]+bc.dist)<mtb->pt.xx[
dim])
407 PSearch(itb,itb+siz/2, level, bc);
411 if (bc.sp.xx[
dim]<mtb->pt.xx[
dim])
414 PSearch(itb,itb+siz/2, level, bc);
416 if (!((bc.sp.xx[
dim]+bc.dist)<mtb->pt.xx[
dim]))
418 PSearch(itb+siz/2+1, ite, level, bc);
421 Tfloat dd=Dist(mtb->pt, bc.sp);
424 bc.dist=dd; bc.pos=mtb-data.begin(); bc.level=level;
432 PSearch(itb+siz/2+1, ite, level, bc);
434 if (!((bc.sp.xx[
dim]-bc.dist)>mtb->pt.xx[
dim]))
436 PSearch(itb, itb+siz/2, level, bc);
439 Tfloat dd=Dist(mtb->pt, bc.sp);
442 bc.dist=dd; bc.pos=mtb-data.begin(); bc.level=level;
453 for (
auto it=itb; it!=ite; it++)
455 dd=Dist(it->pt, bc.sp);
458 bc.pos=it-data.begin();
467 void NNS(PointND& pt,
const int& npoints,
468 typename std::vector<NodeND>::iterator itb,
469 typename std::vector<NodeND>::iterator ite,
471 std::vector< std::tuple<Tfloat,Tindex> > & res)
473 std::uint8_t
dim=(std::uint8_t) (level%ndim);
475 typename std::vector<NodeND>::iterator mtb=itb+siz/2;
480 Tfloat R=std::get<0>(res[npoints-1]);
482 Tfloat dd=Dist(mtb->pt, pt);
485 res[npoints-1]=std::make_tuple(dd,mtb->ind);
486 std::nth_element(res.begin(), res.end()-1, res.end());
487 R=std::get<0>(res[npoints-1]);
489 if ((pt.xx[
dim]-R)>mtb->pt.xx[
dim])
491 NNS(pt, npoints, itb+siz/2+1, ite, level, res);
493 else if ((pt.xx[
dim]+R)<mtb->pt.xx[
dim])
495 NNS(pt, npoints, itb, itb+siz/2, level, res);
499 NNS(pt,npoints, itb+siz/2+1, ite, level, res);
500 NNS(pt,npoints, itb, itb+siz/2, level, res);
506 for (
auto it=itb; it!=ite; it++)
509 if (dd< std::get<0>(res[npoints-1]))
511 res[npoints-1]=std::make_tuple(dd,it->ind);
512 std::nth_element(res.begin(), res.end()-1, res.end());
520 typename std::vector<NodeND>::iterator itb,
521 typename std::vector<NodeND>::iterator ite,
523 std::vector<Tindex> & res)
525 std::uint8_t
dim=(std::uint8_t) (level%ndim);
527 typename std::vector<NodeND>::iterator mtb=itb+siz/2;
532 if ((pt.xx[
dim]-R)>mtb->pt.xx[
dim])
536 else if ((pt.xx[
dim]+R)<mtb->pt.xx[
dim])
546 Tfloat dd=Dist(mtb->pt, pt);
549 res.push_back(mtb->ind);
556 for (
auto it=itb; it!=ite; it++)
561 res.push_back(it->ind);
569 typename std::vector<NodeND>::iterator itb,
570 typename std::vector<NodeND>::iterator ite,
572 std::vector<Tindex> & res, std::vector<Tfloat> & dist)
574 std::uint8_t
dim=(std::uint8_t) (level%ndim);
576 typename std::vector<NodeND>::iterator mtb=itb+siz/2;
581 if ((pt.xx[
dim]-R)>mtb->pt.xx[
dim])
585 else if ((pt.xx[
dim]+R)<mtb->pt.xx[
dim])
595 Tfloat dd=Dist(mtb->pt, pt);
598 res.push_back(mtb->ind);
606 for (
auto it=itb; it!=ite; it++)
611 res.push_back(it->ind);
630 #endif // MFEM_KDTREE_HPP
Tfloat xx[ndim]
Coordinates of the point.
Finds the max absolute value of a vector.
size_t size()
Returns the size of the point cloud.
std::vector< NodeND >::iterator iterator
Data iterator.
void AddPoint(Tfloat *xx, Tindex ii)
Adds a new node by coordinates and an associated index.
KDTree< int, double, 3 > KDTree3D
Defines KDTree in 3D.
void FindNeighborPointsSlow(PointND &pt, Tfloat R, std::vector< Tindex > &res)
Brute force search - please, use it only for debuging purposes.
KDTree< int, double, 2 > KDTree2D
Defines KDTree in 2D.
void FindClosestPoint(PointND &pt, Tindex &ind, Tfloat &dist, PointND &clp)
Returns the closest point and the distance to the input point pt.
void FindNeighborPoints(PointND &pt, Tfloat R, std::vector< Tindex > &res)
Evaluates l1 norm of a vector.
void AddPoint(PointND &pt, Tindex ii)
Adds a new node to the point cloud.
Tindex FindClosestPoint(PointND &pt, PointND &clp)
Finds the nearest neighbour index and return the clossest poitn in clp.
Structure defining a node in the KDTree.
KDTree()=default
Default constructor.
void clear()
Clears the point cloud.
Evaluates l2 norm of a vector.
Tindex ind
Defines the attached index.
iterator end()
Returns iterator to the end of the point cloud.
PointND()
Geometric point constructor.
void FindNeighborPointsSlow(PointND &pt, Tfloat R, std::vector< Tindex > &res, std::vector< Tfloat > &dist)
Brute force search - please, use it only for debuging purposes.
void FindClosestPointSlow(PointND &pt, Tindex &ind, Tfloat &dist)
Brute force search - please, use it only for debuging purposes.
void FindClosestPoint(PointND &pt, Tindex &ind, Tfloat &dist)
Returns the closest point and the distance to the input point pt.
KDTree< int, double, 1 > KDTree1D
Defines KDTree in 1D.
Tfloat operator()(const Tfloat *xx)
PointND pt
Defines a point in the ndim-dimensional space.
int SpaceDimension()
Returns the spatial dimension of the points.
Tfloat operator()(const Tfloat *xx)
void FindNeighborPoints(PointND &pt, Tfloat R, std::vector< Tindex > &res, std::vector< Tfloat > &dist)
iterator begin()
Returns iterator to beginning of the point cloud.
Tindex FindClosestPoint(PointND &pt)
Finds the nearest neighbour index.
Tfloat operator()(const Tfloat *xx)