234 void getCurrent(IndexType *branch_index,IndexType *nparticles);
235 unsigned long getNbranches();
238 void moveToChild(
int child);
239 void attachChildToCurrent(IndexType *branch_index,IndexType nparticles
240 ,D boundary_p1[],D boundary_p2[]
242 void attachChildToCurrent(BranchV &data,
int child);
243 bool TreeWalkStep(
bool allowDescent);
245 inline bool atLeaf(){
246 return (current->child1_ptr ==
nullptr)*(current->child2_ptr ==
nullptr);
248 inline bool inbox(
const D* center,D *p1,D *p2){
250 for(
int i=0;i<
Ndimensions;++i) tt *= (center[i]>=p1[i]);
257 int cutbox(
const D *center,D *p1,D *p2,
float rmax);
285template <
typename T,
typename D>
291 ,std::list <unsigned long> &neighborlist
296 if(rmax < rmin){
float tmp = rmax; rmax=rmin; rmin=tmp;}
298 if(rmax <=0.0 || rmin <= 0.0){ neighborlist.clear();
return; }
301 PointsWithinCircle(ray,rmax,neighborlist);
306 for( std::list<unsigned long>::iterator it = neighborlist.begin();it != neighborlist.end();){
307 x = points[*it][0]*cs - points[*it][1]*sn;
308 y = points[*it][0]*sn + points[*it][1]*cs;
309 if( ( pow(x/rmax,2) + pow(y/rmin,2) ) > 1) it = neighborlist.erase(it);
315template <
typename T,
typename D>
319 ,std::list <unsigned long> &neighborlist
322 neighborlist.clear();
326 for(
int j=0 ; j<Ndimensions ; ++j) realray[j]=ray[j];
330 if( inbox(ray,current->boundary_p1,current->boundary_p2) == 0 ){
332 for(
int i=0 ; i<Ndimensions ; ++i){
333 ray[i] = (ray[i] > current->boundary_p1[i]) ? ray[i] : current->boundary_p1[i];
334 ray[i] = (ray[i] < current->boundary_p2[i]) ? ray[i] : current->boundary_p2[i];
340 _PointsWithin(ray,&rmax,neighborlist);
349template <
typename T,
typename D>
359 if( inbox(ray,current->boundary_p1,current->boundary_p2) ){
374 for(
int j=0;j<Ndimensions;++j) ray[j]=realray[j];
377 for(i=0;i<current->nparticles;++i){
378 for(j=0,radius=0.0;j<2;++j) radius+=pow(position(points[current->branch_index[i]])[j]-ray[j],2);
379 if( radius < *rmax**rmax ){
380 neighborlist.push_back(current->branch_index[i]);
386 for(i=0;i<current->nparticles;++i){
387 neighborlist.push_back(current->branch_index[i]);
396 if(current->child1_ptr !=
nullptr){
398 _PointsWithin(ray,rmax,neighborlist);
404 if(current->child2_ptr !=
nullptr){
406 _PointsWithin(ray,rmax,neighborlist);
411 if( (incell2==1) && (incell==0) ){
412 if(current->child1_ptr !=
nullptr){
414 _PointsWithin(ray,rmax,neighborlist);
423 pass = cutbox(ray,current->boundary_p1,current->boundary_p2,*rmax);
429 for(i=0;i<current->nparticles;++i){
430 for(j=0,radius=0.0;j<2;++j) radius+=pow(position(points[current->branch_index[i]])[j]-ray[j],2);
431 if( radius < *rmax**rmax ){
432 neighborlist.push_back(current->branch_index[i]);
441 if(current->child1_ptr !=
nullptr){
443 _PointsWithin(ray,rmax,neighborlist);
447 if(current->child2_ptr !=
nullptr){
449 _PointsWithin(ray,rmax,neighborlist);
463template <
typename T,
typename D>
467 ,std::vector<D> &radii
468 ,std::vector<IndexType> &neighbors
474 if(top_ptr->nparticles <= Nneighbors){
476 std::vector<D> tmp(Nparticles);
477 std::vector<size_t> sort_index(Nparticles);
478 for(
int i = 0 ; i< Nparticles ; ++i){
479 tmp[i] = pow(position(points[i])[0]-ray[0],2) + pow(position(points[i])[1]-ray[1],2);
483 std::sort(sort_index.begin(),sort_index.end(),[&tmp](
size_t i,
size_t j){return tmp[i] < tmp[j];});
485 radii.resize(Nparticles);
486 neighbors.resize(Nparticles);
488 for(
int i = 0 ; i< Nparticles ; ++i){
489 neighbors[i] = index[sort_index[i]];
490 radii[i] = tmp[sort_index[i]];
496 radii.resize(Nneighbors+Nbucket);
497 neighbors.resize(Nneighbors+Nbucket);
501 for(i=0;i<Nbucket+Nneighbors;++i){
502 radii[i] = (10*(top_ptr->boundary_p2[0]-top_ptr->boundary_p1[0]));
506 for(
int j=0;j<Ndimensions;++j) realray[j]=ray[j];
509 if( inbox(ray,current->boundary_p1,current->boundary_p2) == 0 ){
512 for(j=0;j<Ndimensions;++j){
513 ray[j] = (ray[j] > current->boundary_p1[j]) ? ray[j] : current->boundary_p1[j];
514 ray[j] = (ray[j] < current->boundary_p2[j]) ? ray[j] : current->boundary_p2[j];
519 _NearestNeighbors(ray,Nneighbors,neighbors.data(),radii.data());
521 neighbors.resize(Nneighbors);
522 radii.resize(Nneighbors);
530template <
typename T,
typename D>
540 D rneighbors[1+Nbucket];
541 IndexType neighbors[1+Nbucket];
543 if(top_ptr->nparticles < 1){
545 printf(
"ERROR: in NearestNeighbors, number of neighbors > total number of particles\n");
546 throw std::runtime_error(
"Asked for too many neighbors");
550 for(i=0;i<Nbucket+1;++i){
551 rneighbors[i] = (10*(top_ptr->boundary_p2[0]-top_ptr->boundary_p1[0]));
555 for(
int j=0;j<Ndimensions;++j) realray.x[j]=ray[j];
558 if( inbox(ray,current->boundary_p1,current->boundary_p2) == 0 ){
561 for(
int j=0;j<Ndimensions;++j){
562 ray[j] = (ray[j] > current->boundary_p1[j]) ? ray[j] : current->boundary_p1[j];
563 ray[j] = (ray[j] < current->boundary_p2[j]) ? ray[j] : current->boundary_p2[j];
568 _NearestNeighbors(ray,1,neighbors,rneighbors);
570 neighbor = neighbors[0];
571 radius = rneighbors[0];
576template <
typename T,
typename D>
585 if( inbox(ray,current->boundary_p1,current->boundary_p2) ){
588 if( current->nparticles <= Nneighbors+Nbucket ){
590 for(j=0;j<Ndimensions;++j) ray[j]=realray[j];
593 for(i=0;i<current->nparticles;++i){
594 for(j=0,rneighbors[i]=0.0;j<Ndimensions;++j){
595 rneighbors[i] += pow(position(points[current->branch_index[i]])[j]-ray[j],2);
597 rneighbors[i]=sqrt( rneighbors[i] );
599 neighbors[i]=current->branch_index[i];
602 Utilities::quicksort(neighbors,rneighbors,current->nparticles);
606 if(current->child1_ptr !=
nullptr){
608 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
615 if(current->child2_ptr !=
nullptr){
618 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
624 if( (incellNB2==1) && (incell==0) ){
625 if(current->child1_ptr !=
nullptr){
627 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
635 if( cutbox(ray,current->boundary_p1,current->boundary_p2,rneighbors[Nneighbors-1]) ){
637 if( (current->child1_ptr ==
nullptr)*(current->child2_ptr ==
nullptr)){
640 for(i=Nneighbors;i<(current->nparticles+Nneighbors);++i){
641 for(j=0,rneighbors[i]=0.0;j<Ndimensions;++j){
642 rneighbors[i]+=pow(position(points[current->branch_index[i-Nneighbors]])[j]-ray[j],2);
644 rneighbors[i]=sqrt( rneighbors[i] );
646 neighbors[i]=current->branch_index[i-Nneighbors];
649 Utilities::quicksort(neighbors,rneighbors,Nneighbors+Nbucket);
653 if(current->child1_ptr !=
nullptr){
655 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
659 if(current->child2_ptr !=
nullptr){
661 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
670template <
typename T,
typename D>
674 std::vector<D> p1(Ndimensions),p2(Ndimensions);
677 for(j=0;j<Ndimensions;++j){
678 p1[j] = position(points[0])[j];
679 p2[j] = position(points[0])[j];
682 for(i=0;i<Nparticles;++i){
683 for(j=0;j<Ndimensions;++j){
684 if(position(points[i])[j] < p1[j] ) p1[j] = position(points[i])[j];
685 if(position(points[i])[j] > p2[j] ) p2[j] = position(points[i])[j];
690 top_ptr.reset(
new BranchV(Ndimensions,index.data(),Nparticles,p1.data(),p2.data(),0,0));
694 ERROR_MESSAGE(); fprintf(stderr,
"allocation failure in NewTree()\n");
700 workspace.resize(Nparticles);
701 _BuildTree(Nparticles,index.data());
703 workspace.shrink_to_fit();
706 for(j=0;j<Ndimensions;++j){
711 top_ptr.reset(
new BranchV(Ndimensions,index.data(),0,p1.data(),p2.data(),0,0));
715 ERROR_MESSAGE(); fprintf(stderr,
"allocation failure in NewTree()\n");
725template <
typename T,
typename D>
727 IndexType i,cut,dimension;
728 BranchV branch1(*current),branch2(*current);
730 std::shared_ptr<BranchV> cbranch;
735 if(cbranch->nparticles <= Nbucket){
743 dimension=(cbranch->level % Ndimensions);
746 D *x = workspace.data();
747 for(i=0;i<cbranch->nparticles;++i) x[i] = position(points[tmp_index[i]])[dimension];
750 Utilities::quicksort(tmp_index,x,cbranch->nparticles);
752 cut=(cbranch->nparticles)/2;
753 branch1.boundary_p2[dimension]=x[cut];
754 branch2.boundary_p1[dimension]=x[cut];
756 xcut=(cbranch->boundary_p1[dimension]+cbranch->boundary_p2[dimension])/2;
757 branch1.boundary_p2[dimension]=xcut;
758 branch2.boundary_p1[dimension]=xcut;
760 Utilities::quickPartition(xcut,&cut,tmp_index
761 ,x,cbranch->nparticles);
765 branch1.prev_ptr = cbranch;
766 branch1.nparticles=cut;
768 branch2.prev_ptr = cbranch;
769 branch2.nparticles=cbranch->nparticles - cut;
770 if(cut < (cbranch->nparticles) )
771 branch2.branch_index = &tmp_index[cut];
772 else branch2.branch_index=
nullptr;
774 if(branch1.nparticles > 0) attachChildToCurrent(branch1,1);
775 if(branch2.nparticles > 0) attachChildToCurrent(branch2,2);
778 if( (cbranch->child1_ptr !=
nullptr) && (cbranch->child2_ptr !=
nullptr) ){
779 cbranch->child1_ptr->brother_ptr = cbranch->child2_ptr;
780 cbranch->child2_ptr->brother_ptr = cbranch->brother_ptr;
782 if( (cbranch->child1_ptr ==
nullptr) && (cbranch->child2_ptr !=
nullptr) )
783 cbranch->child2_ptr->brother_ptr = cbranch->brother_ptr;
784 if( (cbranch->child1_ptr !=
nullptr) && (cbranch->child2_ptr ==
nullptr) )
785 cbranch->child1_ptr->brother_ptr = cbranch->brother_ptr;
788 if( branch1.nparticles > 0 ){
790 _BuildTree(branch1.nparticles,branch1.branch_index);
794 if(branch2.nparticles > 0 ){
796 _BuildTree(branch2.nparticles,branch2.branch_index);
804template <
typename T,
typename D>