GLAMERDOC++
Gravitational Lensing Code Library
Loading...
Searching...
No Matches
simpleTreeVec.h
1
8#ifndef SIMP_TREE_V_
9#define SIMP_TREE_V_
10
11#include <memory>
12#include "standard.h"
13#include "Tree.h"
14
21template <typename T,typename D = PosType>
23public:
24
26 T *xpt
27 ,IndexType Npoints
28 ,int bucket = 5
29 ,int dimensions = 2
30 ,bool median = true
31 // ,PosType *(*Mypos)(T&) = defaultposition /// function that takes
32 ,D *(*Mypos)(T&) = [](T& in){return in.x;}
33 ):Nparticles(Npoints),median_cut(median),Nbucket(bucket),realray(dimensions),
34 points(xpt),position(Mypos),Nbranches(0),Ndimensions(dimensions)
35 {
36 index.resize(Nparticles);
37 for(IndexType ii=0;ii<Npoints;++ii) index[ii] = ii;
38
39 BuildTree();
40 }
41
42 virtual ~TreeSimpleVec()
43 {
44 //delete top_ptr;
45 //freeTree();
46 //delete[] index;
47 //assert(Nbranches == 0);
48 //return;
49 };
50
52 void PointsWithinCircle(D center[2],float radius,std::list<unsigned long> &neighborkist);
54 void PointsWithinEllipse(D center[2],float a_max,float a_min,float posangle,std::list<unsigned long> &neighborkist);
56 void NearestNeighbors(D *ray,int Nneighbors,std::vector<D> &radii
57 ,std::vector<IndexType> &neighbors);
58 void NearestNeighbor(D *ray,D &radius,IndexType &neighbor);
59
61 void pop(IndexType index_of_point){
62
63 //print();
64
65 size_t n = 0;
66 while(index[n] != index_of_point && n < Nparticles) ++n;
67 if(n == Nparticles) return; // particle not in tree
68
69 std::shared_ptr<BranchV> leaf;
70
71 //bool leaf_found = false;
72 moveTop();
73 do{
74 long p = current->branch_index - index.data();
75 if(atLeaf() && n >= p && n < p + current->nparticles ){
76 leaf=current;
77 }
78 if(p > n){
79 current->branch_index -= 1;
80 }
81 }while(TreeWalkStep(true));
82
83 assert(leaf->child1_ptr==nullptr);
84 assert(leaf->child2_ptr==nullptr);
85
86 //BranchV *tmp = leaf;
87 while(leaf != top_ptr){
88 if(leaf->nparticles > 0) leaf->nparticles -= 1;
89 leaf = leaf->prev_ptr;
90 }
91 leaf->nparticles -= 1;
92
93 // remove from index
94 for(size_t i = n ; i < Nparticles - 1 ; ++i){
95 index[i] = index[i+1];
96 }
97 --Nparticles;
98 index.pop_back();
99
100 //print();
101
102 }
103
105 std::vector<IndexType> get_index() const{
106 return index;
107 }
108
109 void print(){
110 moveTop();
111 do{
112 for(int i=0 ; i<current->level ; ++i ) std::cout << " ";
113 std::cout << current->level << " " << current->nparticles << " : ";
114 for(int i=0 ; i<current->nparticles ; ++i){
115 std::cout << *(current->branch_index+i) << " " ;
116 }
117 std::cout << std::endl;
118 }while(TreeWalkStep(true));
119 std::cout << std::endl;
120 }
121
125 struct BranchV{
126
127 int Ndim;
129 IndexType *branch_index;
130 IndexType nparticles;
132 int level;
133 unsigned long number;
135 D *boundary_p1 = nullptr;
137 D *boundary_p2 = nullptr;
138 std::vector<D> bank;
139
140 std::shared_ptr<BranchV> child1_ptr;
141 std::shared_ptr<BranchV> child2_ptr;
143 std::shared_ptr<BranchV> prev_ptr;
146 std::shared_ptr<BranchV> brother_ptr;
147
148
149 BranchV(int my_Ndim,IndexType *my_branch_index,IndexType my_nparticles
150 ,D my_boundary_p1[],D my_boundary_p2[]
151 ,int my_level,unsigned long my_BranchVnumber)
152 :Ndim(my_Ndim),branch_index(my_branch_index),nparticles(my_nparticles)
153 ,level(my_level),number(my_BranchVnumber)
154 {
155
156 bank.resize(Ndim*2);
157 boundary_p1 = bank.data();
158 boundary_p2 = bank.data() + Ndim;
159
160 for(size_t i=0;i<Ndim;++i){
161 boundary_p1[i]= my_boundary_p1[i];
162 boundary_p2[i]= my_boundary_p2[i];
163 }
164
165 child1_ptr = nullptr;
166 child2_ptr = nullptr;
167 prev_ptr = nullptr;
168 brother_ptr = nullptr;
169 };
170 BranchV(BranchV &branch){
171
172 Ndim = branch.Ndim;
173 branch_index = branch.branch_index;
174 nparticles = branch.nparticles;
175 level = branch.level;
176 number = branch.number;
177
178 bank.resize(Ndim*2);
179 boundary_p1 = bank.data();
180 boundary_p2 = bank.data() + Ndim;
181
182 for(size_t i=0;i<Ndim;++i){
183 boundary_p1[i]= branch.boundary_p1[i];
184 boundary_p2[i]= branch.boundary_p2[i];
185 }
186
187 child1_ptr = nullptr;
188 child2_ptr = nullptr;
189 prev_ptr = nullptr;
190 brother_ptr = nullptr;
191 };
192
193 ~BranchV(){
194 //delete child1_ptr;
195 //delete child2_ptr;
196 };
197 };
198
199protected:
200
201 int incell,incell2;
202 std::vector<IndexType> index;
203 IndexType Nparticles;
204 bool median_cut;
205 int Nbucket;
206 Point_nd<D> realray;
207 T *points;
208 D *(*position)(T&);
209
210 std::vector<D> workspace;
211
212 std::shared_ptr<BranchV> top_ptr;
213 std::shared_ptr<BranchV> current;
215 unsigned long Nbranches;
218
219 void BuildTree();
220
221 void _BuildTree(IndexType nparticles,IndexType *tmp_index);
222
223 void _PointsWithin(D *ray,float *rmax,std::list<unsigned long> &neighborkist);
224 void _NearestNeighbors(D *ray,int Nneighbors,unsigned long *neighbors,D *rneighbors);
225
226 void freeTree();
227
228 //short clearTree();
229 //void _freeTree(short child);
230 bool isEmpty();
231 bool atTop();
232 bool noChild();
233 bool offEnd();
234 void getCurrent(IndexType *branch_index,IndexType *nparticles);
235 unsigned long getNbranches();
236 void moveTop();
237 void moveUp();
238 void moveToChild(int child);
239 void attachChildToCurrent(IndexType *branch_index,IndexType nparticles
240 ,D boundary_p1[],D boundary_p2[]
241 ,int child);
242 void attachChildToCurrent(BranchV &data,int child);
243 bool TreeWalkStep(bool allowDescent);
244
245 inline bool atLeaf(){
246 return (current->child1_ptr == nullptr)*(current->child2_ptr == nullptr);
247 }
248 inline bool inbox(const D* center,D *p1,D *p2){
249 int tt=1;
250 for(int i=0;i<Ndimensions;++i) tt *= (center[i]>=p1[i]);
251
252 return tt;
253 // return (center[0]>=p1[0])*(center[0]<=p2[0])*(center[1]>=p1[1])*(center[1]<=p2[1]);
254 }
255
256
257 int cutbox(const D *center,D *p1,D *p2,float rmax);
258};
259/*
260template <class T>
261TreeSimpleVec<T>::TreeSimpleVec<T>(T *xpt,IndexType Npoints,int bucket,int dimensions,bool median){
262 index = new IndexType[Npoints];
263 IndexType ii;
264
265 Nbucket = bucket;
266 Ndimensions = dimensions;
267 median_cut = median;
268 Nparticles = Npoints;
269
270 points = xpt;
271
272 for(ii=0;ii<Npoints;++ii) index[ii] = ii;
273
274 BuildTree();
275};*/
276
277/************************************************************************
278 * NewBranchV
279 * Returns pointer to new BranchV struct. Initializes children pointers to nullptr,
280 * and sets data field to input. Private.
281 ************************************************************************/
282
283
284
285template <typename T,typename D>
287 D *ray
288 ,float rmax
289 ,float rmin
290 ,float posangle
291 ,std::list <unsigned long> &neighborlist
292 ){
293 D x,y,cs,sn;
294
295
296 if(rmax < rmin){float tmp = rmax; rmax=rmin; rmin=tmp;}
297
298 if(rmax <=0.0 || rmin <= 0.0){ neighborlist.clear(); return; }
299
300 // find point within a circle circumscribes the ellipse
301 PointsWithinCircle(ray,rmax,neighborlist);
302
303 cs = cos(posangle);
304 sn = sin(posangle);
305 // go through points within the circle and reject points outside the ellipse
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);
310 else ++it;
311 }
312 return;
313}
314
315template <typename T,typename D>
317 D *ray
318 ,float rmax
319 ,std::list <unsigned long> &neighborlist
320 ){
321
322 neighborlist.clear();
323
324 //realray[0]=ray[0];
325 //realray[1]=ray[1];
326 for(int j=0 ; j<Ndimensions ; ++j) realray[j]=ray[j];
327
328 //cout << "ray = " << ray[0] << " " << ray[1] << " rmax = " << rmax << endl;
329 moveTop();
330 if( inbox(ray,current->boundary_p1,current->boundary_p2) == 0 ){
331
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];
335 }
336
337 }
338 incell=1;
339
340 _PointsWithin(ray,&rmax,neighborlist);
341
342 //for(auto i : neighborlist){
343 // assert( rmax*rmax > (position(points[i])[0]-ray[0])*(position(points[i])[0]-ray[0]) + (position(points[i])[1]-ray[1])*(position(points[i])[1]-ray[1]) );
344 //}
345 return;
346}
349template <typename T,typename D>
350void TreeSimpleVec<T,D>::_PointsWithin(D *ray,float *rmax,std::list <unsigned long> &neighborlist){
351
352 int j,incell2=1;
353 unsigned long i;
354 D radius;
355 short pass;
356
357 if(incell){ // not found cell yet
358
359 if( inbox(ray,current->boundary_p1,current->boundary_p2) ){
360 //cout << " In box" << endl;
361
362 // found the box small enough
363 //if( cutbox(ray,current->boundary_p1,current->boundary_p2,*rmax)==1
364 // || atLeaf() ){
365 if( atLeaf() ){
366 //cout << " Found cell" << endl;
367
368 // whole box in circle or a leaf with ray in it
369
370 incell=0;
371
372 //ray[0]=realray[0];
373 //ray[1]=realray[1];
374 for(int j=0;j<Ndimensions;++j) ray[j]=realray[j];
375 if( atLeaf() ){
376 // if leaf calculate the distance to all the points in cell
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]);
381 //cout << "add point to list" << neighborlist.size() << endl;
382 //InsertAfterCurrentKist(neighborlist,current->branch_index[i]);
383 }
384 }
385 }else{ // put all of points in box into getCurrentKist(imagelist)
386 for(i=0;i<current->nparticles;++i){
387 neighborlist.push_back(current->branch_index[i]);
388 //InsertAfterCurrentKist(neighborlist,current->branch_index[i]);
389 //cout << "add point to list" << neighborlist.size() << endl;
390
391 }
392 }
393
394 }else{ // keep going down the tree
395
396 if(current->child1_ptr != nullptr){
397 moveToChild(1);
398 _PointsWithin(ray,rmax,neighborlist);
399 moveUp();
400
401 incell2=incell;
402 }
403
404 if(current->child2_ptr != nullptr){
405 moveToChild(2);
406 _PointsWithin(ray,rmax,neighborlist);
407 moveUp();
408 }
409
410 // if ray found in second child go back to first to search for neighbors
411 if( (incell2==1) && (incell==0) ){
412 if(current->child1_ptr != nullptr){
413 moveToChild(1);
414 _PointsWithin(ray,rmax,neighborlist);
415 moveUp();
416 }
417 }
418 }
419 } // not in the box
420
421 }else{ // found cell
422
423 pass = cutbox(ray,current->boundary_p1,current->boundary_p2,*rmax);
424 // does radius cut into the box
425 if( pass ){
426 //cout << " Cell found searching other cells" << endl;
427 if( atLeaf() ){ /* leaf case */
428
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]);
433 }
434 }
435 //}else if(pass==1){ // whole box is inside radius
436
437 // for(i=0;i<current->nparticles;++i){
438 // neighborlist.push_back(current->branch_index[i]); ?????
439 // }
440 }else{
441 if(current->child1_ptr != nullptr){
442 moveToChild(1);
443 _PointsWithin(ray,rmax,neighborlist);
444 moveUp();
445 }
446
447 if(current->child2_ptr != nullptr){
448 moveToChild(2);
449 _PointsWithin(ray,rmax,neighborlist);
450 moveUp();
451 }
452 }
453
454 }
455 }
456
457 return;
458}
459
463template <typename T,typename D>
465 D *ray
466 ,int Nneighbors
467 ,std::vector<D> &radii
468 ,std::vector<IndexType> &neighbors
469 ){
470 IndexType i;
471 short j;
472
473
474 if(top_ptr->nparticles <= Nneighbors){
475
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);
480 sort_index[i]=i;
481 }
482
483 std::sort(sort_index.begin(),sort_index.end(),[&tmp](size_t i,size_t j){return tmp[i] < tmp[j];});
484
485 radii.resize(Nparticles);
486 neighbors.resize(Nparticles);
487
488 for(int i = 0 ; i< Nparticles ; ++i){
489 neighbors[i] = index[sort_index[i]];
490 radii[i] = tmp[sort_index[i]];
491 }
492
493 return;
494 }
495
496 radii.resize(Nneighbors+Nbucket);
497 neighbors.resize(Nneighbors+Nbucket);
498
499
500 /* initalize distance to neighbors to a large number */
501 for(i=0;i<Nbucket+Nneighbors;++i){
502 radii[i] = (10*(top_ptr->boundary_p2[0]-top_ptr->boundary_p1[0]));
503 neighbors[i] = 0;
504 }
505
506 for(int j=0;j<Ndimensions;++j) realray[j]=ray[j];
507
508 moveTop();
509 if( inbox(ray,current->boundary_p1,current->boundary_p2) == 0 ){
510 //ERROR_MESSAGE();
511
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];
515 }
516 }
517 incell = 1;
518
519 _NearestNeighbors(ray,Nneighbors,neighbors.data(),radii.data());
520
521 neighbors.resize(Nneighbors);
522 radii.resize(Nneighbors);
523
524 return;
525}
526
530template <typename T,typename D>
532 D *ray
533 ,D &radius
534 ,IndexType &neighbor
535 ){
536 IndexType i;
537 //static int count=0,oldNneighbors=-1;
538 //short j;
539
540 D rneighbors[1+Nbucket];
541 IndexType neighbors[1+Nbucket];
542
543 if(top_ptr->nparticles < 1){
544 ERROR_MESSAGE();
545 printf("ERROR: in NearestNeighbors, number of neighbors > total number of particles\n");
546 throw std::runtime_error("Asked for too many neighbors");
547 }
548
549 /* initalize distance to neighbors to a large number */
550 for(i=0;i<Nbucket+1;++i){
551 rneighbors[i] = (10*(top_ptr->boundary_p2[0]-top_ptr->boundary_p1[0]));
552 neighbors[i] = 0;
553 }
554
555 for(int j=0;j<Ndimensions;++j) realray.x[j]=ray[j];
556
557 moveTop();
558 if( inbox(ray,current->boundary_p1,current->boundary_p2) == 0 ){
559 //ERROR_MESSAGE();
560
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];
564 }
565 }
566 incell = 1;
567
568 _NearestNeighbors(ray,1,neighbors,rneighbors);
569
570 neighbor = neighbors[0];
571 radius = rneighbors[0];
572
573 return;
574}
575
576template <typename T,typename D>
577void TreeSimpleVec<T,D>::_NearestNeighbors(D *ray,int Nneighbors,unsigned long *neighbors,D *rneighbors){
578
579 int incellNB2=1;
580 IndexType i;
581 short j;
582
583 if(incell){ /* not found cell yet */
584
585 if( inbox(ray,current->boundary_p1,current->boundary_p2) ){
586
587 /* found the box small enough */
588 if( current->nparticles <= Nneighbors+Nbucket ){
589 incell=0;
590 for(j=0;j<Ndimensions;++j) ray[j]=realray[j];
591
592 /* calculate the distance to all the particles in cell */
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);
596 }
597 rneighbors[i]=sqrt( rneighbors[i] );
598 //assert(rneighbors[i] < 10);
599 neighbors[i]=current->branch_index[i];
600 }
601
602 Utilities::quicksort(neighbors,rneighbors,current->nparticles);
603
604 }else{ /* keep going down the tree */
605
606 if(current->child1_ptr !=nullptr){
607 moveToChild(1);
608 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
609 /*printf("moving up from level %i\n",current->level);*/
610 moveUp();
611
612 incellNB2=incell;
613 }
614
615 if(current->child2_ptr !=nullptr){
616 /*printf("moving to child2 from level %i\n",current->level);*/
617 moveToChild(2);
618 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
619 /*printf("moving up from level %i\n",current->level);*/
620 moveUp();
621 }
622
624 if( (incellNB2==1) && (incell==0) ){
625 if(current->child1_ptr !=nullptr){
626 moveToChild(1);
627 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
628 moveUp();
629 }
630 }
631 }
632 }
633 }else{ // found cell
634 // does radius cut into the box
635 if( cutbox(ray,current->boundary_p1,current->boundary_p2,rneighbors[Nneighbors-1]) ){
636
637 if( (current->child1_ptr == nullptr)*(current->child2_ptr == nullptr)){ /* leaf case */
638
639 /* combine found neighbors with particles in box and resort */
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);
643 }
644 rneighbors[i]=sqrt( rneighbors[i] );
645 //assert(rneighbors[i] < 10);
646 neighbors[i]=current->branch_index[i-Nneighbors];
647 }
648
649 Utilities::quicksort(neighbors,rneighbors,Nneighbors+Nbucket);
650
651 }else{
652
653 if(current->child1_ptr !=nullptr){
654 moveToChild(1);
655 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
656 moveUp();
657 }
658
659 if(current->child2_ptr !=nullptr){
660 moveToChild(2);
661 _NearestNeighbors(ray,Nneighbors,neighbors,rneighbors);
662 moveUp();
663 }
664 }
665 }
666 }
667 return;
668}
669
670template <typename T,typename D>
672 IndexType i;
673 short j;
674 std::vector<D> p1(Ndimensions),p2(Ndimensions);
675
676 if(Nparticles > 0){
677 for(j=0;j<Ndimensions;++j){
678 p1[j] = position(points[0])[j];
679 p2[j] = position(points[0])[j];
680 }
681
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];
686 }
687 }
688
689 /* Initialize tree root */
690 top_ptr.reset(new BranchV(Ndimensions,index.data(),Nparticles,p1.data(),p2.data(),0,0));
691 current = top_ptr;
692 ++Nbranches;
693 if (!(top_ptr)){
694 ERROR_MESSAGE(); fprintf(stderr,"allocation failure in NewTree()\n");
695 exit(1);
696 }
697
698
699 /* build the tree */
700 workspace.resize(Nparticles);
701 _BuildTree(Nparticles,index.data());
702 workspace.clear();
703 workspace.shrink_to_fit();
704 }else{
705
706 for(j=0;j<Ndimensions;++j){
707 p1[j] *= 0;
708 p2[j] *= 0;
709 }
710
711 top_ptr.reset(new BranchV(Ndimensions,index.data(),0,p1.data(),p2.data(),0,0));
712 current = top_ptr;
713 ++Nbranches;
714 if (!(top_ptr)){
715 ERROR_MESSAGE(); fprintf(stderr,"allocation failure in NewTree()\n");
716 exit(1);
717 }
718 }
719 /* visit every branch to find center of mass and cutoff scale */
720 moveTop();
721}
722
723
724// tree must be created and first branch must be set before start
725template <typename T,typename D>
726void TreeSimpleVec<T,D>::_BuildTree(IndexType nparticles,IndexType *tmp_index){
727 IndexType i,cut,dimension;
728 BranchV branch1(*current),branch2(*current);
729 D xcut;
730 std::shared_ptr<BranchV> cbranch;
731
732 cbranch=current; // pointer to current branch
733
734 // leaf case
735 if(cbranch->nparticles <= Nbucket){
736 return;
737 }
738 //cbranch->big_particle=0;
739
740 // **** makes sure force does not require nbucket at leaf
741
742 // set dimension to cut box
743 dimension=(cbranch->level % Ndimensions);
744
745 // D *x = new D[cbranch->nparticles];
746 D *x = workspace.data();
747 for(i=0;i<cbranch->nparticles;++i) x[i] = position(points[tmp_index[i]])[dimension];
748
749 if(median_cut){
750 Utilities::quicksort(tmp_index,x,cbranch->nparticles);
751
752 cut=(cbranch->nparticles)/2;
753 branch1.boundary_p2[dimension]=x[cut];
754 branch2.boundary_p1[dimension]=x[cut];
755 }else{
756 xcut=(cbranch->boundary_p1[dimension]+cbranch->boundary_p2[dimension])/2;
757 branch1.boundary_p2[dimension]=xcut;
758 branch2.boundary_p1[dimension]=xcut;
759
760 Utilities::quickPartition(xcut,&cut,tmp_index
761 ,x,cbranch->nparticles);
762 }
763
764 // set particle numbers and pointers to my_index
765 branch1.prev_ptr = cbranch;
766 branch1.nparticles=cut;
767
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;
773
774 if(branch1.nparticles > 0) attachChildToCurrent(branch1,1);
775 if(branch2.nparticles > 0) attachChildToCurrent(branch2,2);
776
777 // work out brothers for children
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;
781 }
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;
786
787
788 if( branch1.nparticles > 0 ){
789 moveToChild(1);
790 _BuildTree(branch1.nparticles,branch1.branch_index);
791 moveUp();
792 }
793
794 if(branch2.nparticles > 0 ){
795 moveToChild(2);
796 _BuildTree(branch2.nparticles,branch2.branch_index);
797 moveUp();
798 }
799
800 return;
801}
802
804template <typename T,typename D>
806
807 //clearTree();
808 delete top_ptr;
809 Nbranches=0;
810
811 return;
812}
813
814//template <typename T,typename D>
815//short TreeSimpleVec<T,D>::clearTree(){
816//
817// moveTop();
818// _freeTree(0);
819//
820// assert(Nbranches == 1);
821//
822// return 1;
823//}
824
825//template <typename T,typename D>
826//void TreeSimpleVec<T,D>::_freeTree(short child){
827// BranchV *branch;
828//
829// assert( current);
830//
831// if(current->child1 != nullptr){
832// moveToChild(1);
833// _freeTree(1);
834// }
835//
836// if(current->child2 != nullptr){
837// moveToChild(2);
838// _freeTree(2);
839// }
840//
841// if( (current->child1 == nullptr)*(current->child2 == nullptr) ){
842//
843// if(atTop()) return;
844//
845// branch = current;
846// moveUp();
847// delete branch;
848// --Nbranches;
849//
850// /*printf("*** removing branch %i number of branches %i\n",branch->number
851// ,Nbranches-1);*/
852//
853// if(child==1) current->child1 = nullptr;
854// if(child==2) current->child2 = nullptr;
855//
856// return;
857// }
858//
859// return;
860//}
861
862/************************************************************************
863 * isEmpty
864 * Returns "true" if the Tree is empty and "false" otherwise. Exported.
865 ************************************************************************/
866template <typename T,typename D>
868 return(Nbranches == 0);
869}
870
871/************************************************************************
872 * atTop
873 * Returns "true" if current is the same as top and "false" otherwise.
874 * Exported.
875 * Pre: !isEmpty()
876 ************************************************************************/
877template <typename T,typename D>
879
880 if( isEmpty() ){
881 ERROR_MESSAGE();
882 fprintf(stderr, "Tree Error: calling atTop() on empty tree\n");
883 exit(1);
884 }
885 return(current == top_ptr);
886}
887
888/************************************************************************
889 * noChild
890 * Returns "true" if the child of the current BranchV does not exist and "false" otherwise.
891 * Exported.
892 * Pre: !isEmpty()
893 ************************************************************************/
894template <typename T,typename D>
896
897 if( isEmpty() ){
898
899 ERROR_MESSAGE(); fprintf(stderr, "Tree Error: calling atTop() on empty tree\n");
900 exit(1);
901 }
902
903 if( (current->child1 == nullptr) || (current->child2 == nullptr) ) return true;
904 return false;
905}
906
907/************************************************************************
908 * offEnd
909 * Returns "true" if current is off end and "false" otherwise. Exported.
910 ************************************************************************/
911template <typename T,typename D>
913
914 return(current == nullptr);
915}
916
917/************************************************************************
918 * getCurrent
919 * Returns the particuls of current. Exported.
920 * Pre: !offEnd()
921 ************************************************************************/
922template <typename T,typename D>
923void TreeSimpleVec<T,D>::getCurrent(IndexType *branch_index,IndexType *nparticles){
924
925 if( offEnd() ){
926
927 ERROR_MESSAGE(); fprintf(stderr, "Tree Error: calling getCurrent() when current is off end\n");
928 exit(1);
929 }
930
931 *nparticles = current->nparticles;
932 branch_index = current->branch_index;
933
934 return;
935}
936
937/************************************************************************
938 * getNbranches
939 * Returns the NBranchVes of tree. Exported.
940 ************************************************************************/
941template <typename T,typename D>
943
944 return(Nbranches);
945}
946
947/***** Manipulation procedures *****/
948
949/************************************************************************
950 * moveTop
951 * Moves current to the front of tree. Exported.
952 * Pre: !isEmpty()
953 ************************************************************************/
954template <typename T,typename D>
956
957 if( isEmpty() ){
958
959 ERROR_MESSAGE(); fprintf(stderr, "Tree Error: calling moveTop() on empty tree\n");
960 exit(1);
961 }
962
963 current = top_ptr;
964
965 return;
966}
967
968/************************************************************************
969 * movePrev
970 * Moves current to the BranchV before it in tree. This can move current
971 * off end. Exported.
972 * Pre: !offEnd()
973 ************************************************************************/
974template <typename T,typename D>
976
977 if( offEnd() ){
978 ERROR_MESSAGE(); fprintf(stderr, "Tree Error: call to moveUp() when current is off end\n");
979 exit(1);
980 }
981 if( current == top_ptr ){
982 ERROR_MESSAGE(); fprintf(stderr, "Tree Error: call to moveUp() tried to move off the top\n");
983 exit(1);
984 }
985
986 current = current->prev_ptr; /* can move off end */
987 return;
988}
989
990/************************************************************************
991 * moveToChild
992 * Moves current to child BranchV after it in tree. This can move current off
993 * end. Exported.
994 * Pre: !offEnd()
995 ************************************************************************/
996template <typename T,typename D>
997void TreeSimpleVec<T,D>::moveToChild(int child){
998
999 if( offEnd() ){
1000
1001 ERROR_MESSAGE(); fprintf(stderr, "Tree Error: calling moveChildren() when current is off end\n");
1002 exit(1);
1003 }
1004 if(child==1){
1005 if( current->child1_ptr == nullptr ){
1006 ERROR_MESSAGE(); fprintf(stderr, "Tree Error: moveToChild() typing to move to child1 when it doesn't exist\n");
1007 exit(1);
1008 }
1009 current = current->child1_ptr;
1010 }
1011 if(child==2){
1012 if( current->child2_ptr == nullptr ){
1013 ERROR_MESSAGE(); fprintf(stderr, "Tree Error: moveToChild() typing to move to child2 when it doesn't exist\n");
1014 exit(1);
1015 }
1016 current = current->child2_ptr;
1017 }
1018 return;
1019}
1020
1021/************************************************************************
1022 * insertAfterCurrent
1023 * Inserts a new BranchV after the current BranchV in the tree and sets the
1024 * data field of the new BranchV to input. Exported.
1025 * Pre: !offEnd()
1026 ************************************************************************/
1027template <typename T,typename D>
1028void TreeSimpleVec<T,D>::attachChildToCurrent(IndexType *branch_index,IndexType nparticles
1029 ,D boundary_p1[],D boundary_p2[]
1030 ,int child){
1031
1032 /*printf("attaching child%i current paricle number %i\n",child,current->nparticles);*/
1033 std::shared_ptr<BranchV> branchV(new BranchV(Ndimensions,branch_index,nparticles,boundary_p1,boundary_p2
1034 ,current->level+1,Nbranches));
1035
1036 ++Nbranches;
1037
1038
1039 if( offEnd() ){
1040
1041 ERROR_MESSAGE(); fprintf(stderr, "Tree Error: calling attachChildToCurrent() when current is off end\n");
1042 exit(1);
1043 }
1044
1045 branchV->prev_ptr = current;
1046
1047 if(child==1){
1048 if(current->child1_ptr != nullptr){
1049 ERROR_MESSAGE(); fprintf(stderr, "Tree Error: calling attachChildToCurrent() when child1 alread exists\n");
1050 exit(1);
1051 }
1052 current->child1_ptr = branchV;
1053 }
1054 if(child==2){
1055 if(current->child2_ptr != nullptr){
1056 ERROR_MESSAGE();
1057 fprintf(stderr, "Tree Error: calling attachChildToCurrent() when child2 alread exists\n current level=%i Nbranches=%li\n"
1058 ,current->level,Nbranches);
1059 exit(1);
1060 }
1061 current->child2_ptr = branchV;
1062 }
1063
1064 return;
1065}
1066
1067/* same as above but takes a BranchV structure */
1068template <typename T,typename D>
1069void TreeSimpleVec<T,D>::attachChildToCurrent(BranchV &data,int child){
1070
1071 attachChildToCurrent(data.branch_index,data.nparticles
1072 ,data.boundary_p1,data.boundary_p2,child);
1073 return;
1074}
1075
1076// step for walking tree by iteration instead of recursion
1077template <typename T,typename D>
1078bool TreeSimpleVec<T,D>::TreeWalkStep(bool allowDescent){
1079 if(allowDescent && current->child1_ptr != nullptr){
1080 moveToChild(1);
1081 return true;
1082 }
1083 if(allowDescent && current->child2_ptr != nullptr){
1084 moveToChild(2);
1085 return true;
1086 }
1087
1088 if(current->brother_ptr != nullptr){
1089 current = current->brother_ptr;
1090 return true;
1091 }
1092 return false;
1093}
1094
1095// = 0 if not possibly intersection
1096// > 0 sphere might intersect box
1097// = 2 sphere completely inside box
1098template <typename T,typename D>
1099int TreeSimpleVec<T,D>::cutbox(const D *center,D *p1,D *p2,float rmax){
1100 int intersection = 1,inside=1;
1101 for(int i=0 ; i<Ndimensions ; ++i){
1102 intersection *= ( (center[i] + rmax) > p1[i] )*( (center[i] - rmax) < p2[i] );
1103 inside *= ( (center[i] - rmax) > p1[i] )*( (center[i] + rmax) < p2[i] );
1104 }
1105
1106 return intersection + inside;
1107}
1108#endif /* SIMP_TREE_V_ */
A tree for doing quick searches in multidimensional space. A pointer to an array of objects type T is...
Definition simpleTreeVec.h:22
void NearestNeighbor(D *ray, D &radius, IndexType &neighbor)
finds the nearest neighbors in whatever dimensions tree is defined in
Definition simpleTreeVec.h:531
void _PointsWithin(D *ray, float *rmax, std::list< unsigned long > &neighborkist)
Definition simpleTreeVec.h:350
void PointsWithinEllipse(D center[2], float a_max, float a_min, float posangle, std::list< unsigned long > &neighborkist)
Finds the points within an ellipse around center and puts their index numbers in a list.
Definition simpleTreeVec.h:286
TreeSimpleVec(T *xpt, IndexType Npoints, int bucket=5, int dimensions=2, bool median=true, D *(*Mypos)(T &)=[](T &in){return in.x;})
Definition simpleTreeVec.h:25
void pop(IndexType index_of_point)
pop this point out of the tree
Definition simpleTreeVec.h:61
unsigned long Nbranches
number of branches in tree
Definition simpleTreeVec.h:215
std::vector< IndexType > get_index() const
returns the index numbers of the remaining points which are less than the original if pop() was used.
Definition simpleTreeVec.h:105
void NearestNeighbors(D *ray, int Nneighbors, std::vector< D > &radii, std::vector< IndexType > &neighbors)
Finds the nearest N neighbors and puts their index numbers in an array, also returns the distance to ...
Definition simpleTreeVec.h:464
void freeTree()
Free all the tree branches.
Definition simpleTreeVec.h:805
void _NearestNeighbors(D *ray, int Nneighbors, unsigned long *neighbors, D *rneighbors)
Definition simpleTreeVec.h:577
void PointsWithinCircle(D center[2], float radius, std::list< unsigned long > &neighborkist)
Finds the points within a circle around center and puts their index numbers in a list.
Definition simpleTreeVec.h:316
short Ndimensions
Dimension of tree, 2 or 3. This will dictate how the force is calculated.
Definition simpleTreeVec.h:217
Definition point.h:1167
Box representing a branch in a tree. It has four children. Used in TreeNBStruct which is used in Tree...
Definition simpleTreeVec.h:125
D * boundary_p2
top, right, front corner of box
Definition simpleTreeVec.h:137
D * boundary_p1
bottom, left, back corner of box
Definition simpleTreeVec.h:135
int level
level in tree
Definition simpleTreeVec.h:132
std::shared_ptr< BranchV > prev_ptr
father of branch
Definition simpleTreeVec.h:143
IndexType * branch_index
array of branch_index in BranchV
Definition simpleTreeVec.h:129
std::shared_ptr< BranchV > brother_ptr
Definition simpleTreeVec.h:146