|
SISCone
2.0.5
|
00001 00002 // File: protocones.cpp // 00003 // Description: source file for stable cones determination (Cstable_cones) // 00004 // This file is part of the SISCone project. // 00005 // WARNING: this is not the main SISCone trunk but // 00006 // an adaptation to spherical coordinates // 00007 // For more details, see http://projects.hepforge.org/siscone // 00008 // // 00009 // Copyright (c) 2006-2008 Gavin Salam and Gregory Soyez // 00010 // // 00011 // This program is free software; you can redistribute it and/or modify // 00012 // it under the terms of the GNU General Public License as published by // 00013 // the Free Software Foundation; either version 2 of the License, or // 00014 // (at your option) any later version. // 00015 // // 00016 // This program is distributed in the hope that it will be useful, // 00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of // 00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // 00019 // GNU General Public License for more details. // 00020 // // 00021 // You should have received a copy of the GNU General Public License // 00022 // along with this program; if not, write to the Free Software // 00023 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA // 00024 // // 00025 // $Revision:: 311 $// 00026 // $Date:: 2011-10-05 23:27:09 +0200 (Wed, 05 Oct 2011) $// 00028 00029 /******************************************************* 00030 * Introductory note: * 00031 * Since this file has many member functions, we have * 00032 * structured them in categories: * 00033 * INITIALISATION FUNCTIONS * 00034 * - ctor() * 00035 * - ctor(particle_list) * 00036 * - dtor() * 00037 * - init(particle_list) * 00038 * ALGORITHM MAIN ENTRY * 00039 * - get_stable_cone(radius) * 00040 * ALGORITHM MAIN STEPS * 00041 * - init_cone() * 00042 * - test_cone() * 00043 * - update_cone() * 00044 * - proceed_with_stability() * 00045 * ALGORITHM MAIN STEPS FOR COCIRCULAR SITUATIONS * 00046 * - cocircular_pt_less(v1, v2) * 00047 * - prepare_cocircular_list() * 00048 * - test_cone_cocircular() * 00049 * - test_stability(candidate, border_list) * 00050 * - updat_cone_cocircular() * 00051 * RECOMPUTATION OF CONE CONTENTS * 00052 * - compute_cone_contents() * 00053 * - recompute_cone_contents() * 00054 * - recompute_cone_contents_if_needed() * 00055 * VARIOUS TOOLS * 00056 * - circle_intersect() * 00057 * - is_inside() * 00058 * - abs_dangle() * 00059 *******************************************************/ 00060 00061 #include <siscone/defines.h> 00062 #include <siscone/siscone_error.h> 00063 #include <siscone/circulator.h> 00064 #include "protocones.h" 00065 #include <math.h> 00066 #include <iostream> 00067 #include <algorithm> 00068 00069 namespace siscone_spherical{ 00070 00071 using namespace std; 00072 00073 /********************************************************************** 00074 * CSphstable_cones implementation * 00075 * Computes the list of stable comes from a particle list. * 00076 * This class does the first fundamental task of te cone algorithm: * 00077 * it is used to compute the list of stable cones given a list * 00078 * of particles. * 00079 **********************************************************************/ 00080 00082 // INITIALISATION FUNCTIONS // 00083 // - ctor() // 00084 // - ctor(particle_list) // 00085 // - dtor() // 00086 // - init(particle_list) // 00088 00089 // default ctor 00090 //-------------- 00091 CSphstable_cones::CSphstable_cones(){ 00092 nb_tot = 0; 00093 hc = NULL; 00094 } 00095 00096 // ctor with initialisation 00097 //-------------------------- 00098 CSphstable_cones::CSphstable_cones(vector<CSphmomentum> &_particle_list) 00099 : CSphvicinity(_particle_list){ 00100 00101 nb_tot = 0; 00102 hc = NULL; 00103 } 00104 00105 // default dtor 00106 //-------------- 00107 CSphstable_cones::~CSphstable_cones(){ 00108 if (hc!=NULL) delete hc; 00109 } 00110 00111 /* 00112 * initialisation 00113 * - _particle_list list of particles 00114 * - _n number of particles 00115 *********************************************************************/ 00116 void CSphstable_cones::init(vector<CSphmomentum> &_particle_list){ 00117 // check already allocated mem 00118 if (hc!=NULL){ 00119 delete hc; 00120 } 00121 if (protocones.size()!=0) 00122 protocones.clear(); 00123 00124 multiple_centre_done.clear(); 00125 00126 // initialisation 00127 set_particle_list(_particle_list); 00128 } 00129 00130 00132 // ALGORITHM MAIN ENTRY // 00133 // - get_stable_cone(radius) // 00135 00136 /* 00137 * compute stable cones. 00138 * This function really does the job i.e. computes 00139 * the list of stable cones (in a seedless way) 00140 * - _radius: radius of the cones 00141 * The number of stable cones found is returned 00142 *********************************************************************/ 00143 int CSphstable_cones::get_stable_cones(double _radius){ 00144 int p_idx; 00145 00146 // check if everything is correctly initialised 00147 if (n_part==0){ 00148 return 0; 00149 } 00150 00151 R = _radius; 00152 R2 = R*R; 00153 tan2R = tan(R); 00154 tan2R *= tan2R; 00155 00156 // allow hash for cones candidates 00157 hc = new sph_hash_cones(n_part, R); 00158 00159 // browse all particles 00160 for (p_idx=0;p_idx<n_part;p_idx++){ 00161 // step 0: compute the child list CL. 00162 // Note that this automatically sets the parent P 00163 build(&plist[p_idx], 2.0*R); 00164 00165 // special case: 00166 // if the vicinity is empty, the parent particle is a 00167 // stable cone by itself. Add it to protocones list. 00168 if (vicinity_size==0){ 00169 protocones.push_back(*parent); 00170 continue; 00171 } 00172 00173 #ifdef DEBUG_STABLE_CONES 00174 cout << endl << endl; 00175 cout << "plot 'particles.dat' u 2:1 pt 1 ps 3" << endl; 00176 cout << "set label 1 'x' at " << parent->_phi << ", " << parent->_theta << endl; 00177 #endif 00178 00179 // step 1: initialise with the first cone candidate 00180 init_cone(); 00181 00182 do{ 00183 // step 2: test cone stability for that pair (P,C) 00184 test_cone(); 00185 00186 // step 3: go to the next cone child candidate C 00187 } while (!update_cone()); 00188 } 00189 00190 return proceed_with_stability(); 00191 } 00192 00193 00195 // ALGORITHM MAIN STEPS // 00196 // - init_cone() // 00197 // - test_cone() // 00198 // - update_cone() // 00199 // - proceed_with_stability() // 00201 00202 /* 00203 * initialise the cone. 00204 * We take the first particle in the angular ordering to compute 00205 * this one 00206 * return 0 on success, 1 on error 00207 *********************************************************************/ 00208 int CSphstable_cones::init_cone(){ 00209 // The previous version of the algorithm was starting the 00210 // loop around vicinity elements with the "most isolated" child. 00211 // given the nodist method to calculate the cone contents, we no 00212 // longer need to worry about which cone comes first... 00213 first_cone=0; 00214 00215 // now make sure we have lists of the cocircular particles 00216 prepare_cocircular_lists(); 00217 00218 //TODO? deal with a configuration with only degeneracies ? 00219 // The only possibility seems a regular hexagon with a parent point 00220 // in the centre. And this situation is by itself unclear. 00221 // Hence, we do nothing here ! 00222 00223 // init set child C 00224 centre = vicinity[first_cone]; 00225 child = centre->v; 00226 centre_idx = first_cone; 00227 00228 // build the initial cone (nodist: avoids calculating distances -- 00229 // just deduces contents by circulating around all in/out operations) 00230 // this function also sets the list of included particles 00231 compute_cone_contents(); 00232 00233 return 0; 00234 } 00235 00236 00237 /* 00238 * test cones. 00239 * We check if the cone(s) built with the present parent and child 00240 * are stable 00241 * return 0 on success 1 on error 00242 *********************************************************************/ 00243 int CSphstable_cones::test_cone(){ 00244 siscone::Creference weighted_cone_ref; 00245 00246 // depending on the side we are taking the child particle, 00247 // we test different configuration. 00248 // Each time, two configurations are tested in such a way that 00249 // all 4 possible cases (parent or child in or out the cone) 00250 // are tested when taking the pair of particle parent+child 00251 // and child+parent. 00252 00253 // here are the tests entering the first series: 00254 // 1. check if the cone is already inserted 00255 // 2. check cone stability for the parent and child particles 00256 00257 //UPDATED(see below): if (centre->side){ 00258 //UPDATED(see below): // test when both particles are not in the cone 00259 //UPDATED(see below): // or when both are in. 00260 //UPDATED(see below): // Note: for the totally exclusive case, test emptyness before 00261 //UPDATED(see below): cone_candidate = cone; 00262 //UPDATED(see below): if (cone.ref.not_empty()){ 00263 //UPDATED(see below): hc->insert(&cone_candidate, parent, child, false, false); 00264 //UPDATED(see below): } 00265 //UPDATED(see below): 00266 //UPDATED(see below): cone_candidate = cone; 00267 //UPDATED(see below): cone_candidate+= *parent + *child; 00268 //UPDATED(see below): hc->insert(&cone_candidate, parent, child, true, true); 00269 //UPDATED(see below): } else { 00270 //UPDATED(see below): // test when 1! of the particles is in the cone 00271 //UPDATED(see below): cone_candidate = cone + *parent; 00272 //UPDATED(see below): hc->insert(&cone_candidate, parent, child, true, false); 00273 //UPDATED(see below): 00274 //UPDATED(see below): cone_candidate = cone + *child; 00275 //UPDATED(see below): hc->insert(&cone_candidate, parent, child, false, true); 00276 //UPDATED(see below): } 00277 //UPDATED(see below): 00278 //UPDATED(see below): nb_tot+=2; 00279 00280 // instead of testing 2 inclusion/exclusion states for every pair, we test the 4 of them 00281 // when the parent has an energy bigger than the child 00282 if (parent->E >= child->E){ 00283 // test when both particles are not in the cone 00284 // Note: for the totally exclusive case, test emptiness before 00285 cone_candidate = cone; 00286 if (cone.ref.not_empty()){ 00287 hc->insert(&cone_candidate, parent, child, false, false); 00288 } 00289 00290 // test when 1! of the particles is in the cone 00291 cone_candidate += *parent; 00292 hc->insert(&cone_candidate, parent, child, true, false); 00293 00294 cone_candidate = cone; 00295 cone_candidate += *child; 00296 hc->insert(&cone_candidate, parent, child, false, true); 00297 00298 // test when both are in. 00299 cone_candidate += *parent; 00300 hc->insert(&cone_candidate, parent, child, true, true); 00301 00302 nb_tot += 4; 00303 } 00304 00305 00306 return 0; 00307 } 00308 00309 00310 /* 00311 * update the cone 00312 * go to the next child for that parent and update 'cone' appropriately 00313 * return 0 if update candidate found, 1 otherwise 00314 ***********************************************************************/ 00315 int CSphstable_cones::update_cone(){ 00316 #ifdef DEBUG_STABLE_CONES 00317 cout << "call 'circles_plot.gp' '" << centre->centre.px << "' '" 00318 << centre->centre.py << "' '" << centre->centre.pz << "'" << endl 00319 << "pause -1 '(" << centre->angle << " " << (centre->side ? '+' : '-') << ")"; 00320 #endif 00321 00322 // get the next child and centre 00323 centre_idx++; 00324 if (centre_idx==vicinity_size) 00325 centre_idx=0; 00326 if (centre_idx==first_cone) 00327 return 1; 00328 00329 // update the cone w.r.t. the old child 00330 // only required if the old child is entering inside in which 00331 // case we need to add it. We also know that the child is 00332 // inside iff its side is -. 00333 if (!centre->side){ 00334 #ifdef DEBUG_STABLE_CONES 00335 cout << " old_enter"; 00336 #endif 00337 // update cone 00338 cone += (*child); 00339 00340 // update info on particles inside 00341 centre->is_inside->cone = true; 00342 00343 // update stability check quantities 00344 dpt += fabs(child->px)+fabs(child->py)+fabs(child->pz); 00345 } 00346 00347 // update centre and child to correspond to the new position 00348 centre = vicinity[centre_idx]; 00349 child = centre->v; 00350 00351 // check cocircularity 00352 // note that if cocirculaity is detected (i.e. if we receive 1 00353 // in the next test), we need to recall 'update_cone' directly 00354 // since tests and remaining part of te update has been performed 00355 //if (cocircular_check()) 00356 if (cocircular_check()){ 00357 #ifdef DEBUG_STABLE_CONES 00358 cout << " Co-circular case detected" << endl; 00359 #endif 00360 return update_cone(); 00361 } 00362 00363 // update the cone w.r.t. the new child 00364 // only required if the new child was already inside in which 00365 // case we need to remove it. We also know that the child is 00366 // inside iff its side is +. 00367 if ((centre->side) && (cone.ref.not_empty())){ 00368 #ifdef DEBUG_STABLE_CONES 00369 cout << " new exit"; 00370 #endif 00371 00372 // update cone 00373 cone -= (*child); 00374 00375 // update info on particles inside 00376 centre->is_inside->cone = false; 00377 00378 // update stability check quantities 00379 dpt += fabs(child->px)+fabs(child->py)+fabs(child->pz); //child->perp2(); 00380 } 00381 00382 // check that the addition and subtraction of vectors does 00383 // not lead to too much rounding error 00384 // for that, we compute the sum of pt modifications and of |pt| 00385 // since last recomputation and once the ratio overpasses a threshold 00386 // we recompute vicinity. 00387 if ((dpt>PT_TSHOLD*(fabs(cone.px)+fabs(cone.py)+fabs(cone.pz))) && (cone.ref.not_empty())){ 00388 recompute_cone_contents(); 00389 } 00390 if (cone.ref.is_empty()){ 00391 cone = CSphmomentum(); 00392 dpt=0.0; 00393 } 00394 00395 #ifdef DEBUG_STABLE_CONES 00396 cout << "'" << endl; 00397 #endif 00398 00399 return 0; 00400 } 00401 00402 00403 /* 00404 * compute stability of all enumerated candidates. 00405 * For all candidate cones which are stable w.r.t. their border particles, 00406 * pass the last test: stability with quadtree intersection 00407 ************************************************************************/ 00408 int CSphstable_cones::proceed_with_stability(){ 00409 int i; 00410 sph_hash_element *elm; 00411 00412 for (i=0;i<=hc->mask;i++){ 00413 // test ith cell of the hash array 00414 elm = hc->hash_array[i]; 00415 00416 // browse elements therein 00417 while (elm!=NULL){ 00418 // test stability 00419 if (elm->is_stable){ 00420 // stability is not ensured by all pairs of "edges" already browsed 00421 #ifdef USE_QUADTREE_FOR_STABILITY_TEST 00422 // => testing stability with quadtree intersection 00423 if (quadtree->circle_intersect(elm->eta, elm->phi, R2)==elm->ref) 00424 #else 00425 // => testing stability with the particle-list intersection 00426 if (circle_intersect(elm->centre)==elm->centre.ref) 00427 #endif 00428 protocones.push_back(CSphmomentum(elm->centre,1.0)); 00429 } 00430 00431 // jump to the next one 00432 elm = elm->next; 00433 } 00434 } 00435 00436 // free hash 00437 // we do that at this level because hash eats rather a lot of memory 00438 // we want to free it before running the split/merge algorithm 00439 #ifdef DEBUG_STABLE_CONES 00440 nb_hash_cones = hc->n_cones; 00441 nb_hash_occupied = hc->n_occupied_cells; 00442 #endif 00443 00444 delete hc; 00445 hc=NULL; 00446 00447 return protocones.size(); 00448 } 00449 00450 00452 // ALGORITHM MAIN STEPS FOR COCIRCULAR SITUATIONS // 00453 // - cocircular_pt_less(v1, v2) // 00454 // - prepare_cocircular_list() // 00455 // - test_cone_cocircular() // 00456 // - test_stability(candidate, border_vect) // 00457 // - updat_cone_cocircular() // 00459 00461 //NEVER USED 00462 //bool cocircular_pt_less(CSphmomentum *v1, CSphmomentum *v2){ 00463 // return v1->perp2() < v2->perp2(); 00464 //} 00465 00466 /* 00467 * run through the vicinity of the current parent and for each child 00468 * establish which other members are cocircular... Note that the list 00469 * associated with each child contains references to vicinity 00470 * elements: thus two vicinity elements each associated with one given 00471 * particle may appear in a list -- this needs to be watched out for 00472 * later on... 00473 **********************************************************************/ 00474 void CSphstable_cones::prepare_cocircular_lists() { 00475 siscone::circulator<vector<CSphvicinity_elm*>::iterator > here(vicinity.begin(), 00476 vicinity.begin(), 00477 vicinity.end()); 00478 00479 siscone::circulator<vector<CSphvicinity_elm*>::iterator > search(here); 00480 00481 do { 00482 CSphvicinity_elm* here_pntr = *here(); 00483 search.set_position(here); 00484 00485 // search forwards for things that should have "here" included in 00486 // their cocircularity list 00487 while (true) { 00488 ++search; 00489 if ( siscone::abs_dphi((*search())->angle, here_pntr->angle) < 00490 here_pntr->cocircular_range 00491 && search() != here()) { 00492 (*search())->cocircular.push_back(here_pntr); 00493 } else { 00494 break; 00495 } 00496 } 00497 00498 // search backwards 00499 search.set_position(here); 00500 while (true) { 00501 --search; 00502 if ( siscone::abs_dphi((*search())->angle, here_pntr->angle) < 00503 here_pntr->cocircular_range 00504 && search() != here()) { 00505 (*search())->cocircular.push_back(here_pntr); 00506 } else { 00507 break; 00508 } 00509 } 00510 00511 ++here; 00512 } while (here() != vicinity.begin()); 00513 } 00514 00515 /* 00516 * Testing cocircular configurations in p^3 time, 00517 * rather than 2^p time; we will test all contiguous subsets of points 00518 * on the border --- note that this is till probably overkill, since 00519 * in principle we only have to test situations where up to a 00520 * half-circle is filled (but going to a full circle is simpler) 00521 ******************************************************************/ 00522 void CSphstable_cones::test_cone_cocircular(CSphmomentum & borderless_cone, 00523 list<CSphmomentum *> & border_list) { 00524 // in spherical coordinates, we don't have a universal x-y axis system 00525 // to measure the angles. So we first determine one minimising 00526 // the uncertainties 00527 CSph3vector angl_dir1, angl_dir2; 00528 centre->centre.get_angular_directions(angl_dir1, angl_dir2); 00529 angl_dir1/=angl_dir1._norm; 00530 angl_dir2/=angl_dir2._norm; 00531 00532 // now we have te reference axis, create the CSphborder_store structure 00533 vector<CSphborder_store> border_vect; 00534 border_vect.reserve(border_list.size()); 00535 for (list<CSphmomentum *>::iterator it = border_list.begin(); 00536 it != border_list.end(); it++) { 00537 border_vect.push_back(CSphborder_store(*it, centre->centre, angl_dir1, angl_dir2)); 00538 } 00539 00540 // get them into order of angle 00541 sort(border_vect.begin(), border_vect.end()); 00542 00543 // set up some circulators, since these will help us go around the 00544 // circle easily 00545 siscone::circulator<vector<CSphborder_store>::iterator > 00546 start(border_vect.begin(), border_vect.begin(),border_vect.end()); 00547 siscone::circulator<vector<CSphborder_store>::iterator > mid(start), end(start); 00548 00549 // test the borderless cone 00550 CSphmomentum candidate = borderless_cone; 00551 //candidate.build_etaphi(); 00552 if (candidate.ref.not_empty()) 00553 test_stability(candidate, border_vect); 00554 00555 do { 00556 // reset status wrt inclusion in the cone 00557 mid = start; 00558 do { 00559 mid()->is_in = false; 00560 } while (++mid != start); 00561 00562 // now run over all inclusion possibilities with this starting point 00563 candidate = borderless_cone; 00564 while (++mid != start) { 00565 // will begin with start+1 and go up to start-1 00566 mid()->is_in = true; 00567 candidate += *(mid()->mom); 00568 test_stability(candidate, border_vect); 00569 } 00570 00571 } while (++start != end); 00572 00573 // mid corresponds to momentum that we need to include to get the 00574 // full cone 00575 mid()->is_in = true; 00576 candidate += *(mid()->mom); 00577 test_stability(candidate, border_vect); 00578 } 00579 00580 00587 void CSphstable_cones::test_stability(CSphmomentum & candidate, const vector<CSphborder_store> & border_vect) { 00588 00589 // this almost certainly has not been done... 00590 //candidate.build_etaphi(); 00591 00592 bool stable = true; 00593 for (unsigned i = 0; i < border_vect.size(); i++) { 00594 if (is_closer(&candidate, border_vect[i].mom,tan2R) ^ (border_vect[i].is_in)) { 00595 stable = false; 00596 break; // it's unstable so there's no point continuing 00597 } 00598 } 00599 00600 if (stable) hc->insert(&candidate); 00601 } 00602 00603 /* 00604 * check if we are in a situation of cocircularity. 00605 * if it is the case, update and test in the corresponding way 00606 * return 'false' if no cocircularity detected, 'true' otherwise 00607 * Note that if cocircularity is detected, we need to 00608 * recall 'update' from 'update' !!! 00609 ***************************************************************/ 00610 bool CSphstable_cones::cocircular_check(){ 00611 // check if many configurations have the same centre. 00612 // if this is the case, branch on the algorithm for this 00613 // special case. 00614 // Note that those situation, being considered separately in 00615 // test_cone_multiple, must only be considered here if all 00616 // angles are on the same side (this avoid multiple counting) 00617 00618 if (centre->cocircular.empty()) return false; 00619 00620 // first get cone into status required at end... 00621 if ((centre->side) && (cone.ref.not_empty())){ 00622 // update cone 00623 cone -= (*child); 00624 00625 // update info on particles inside 00626 centre->is_inside->cone = false; 00627 00628 // update stability check quantities 00629 dpt += fabs(child->px)+fabs(child->py)+fabs(child->pz); //child->perp2(); 00630 } 00631 00632 00633 // now establish the list of unique children in the list 00634 // first make sure parent and child are in! 00635 00636 list<siscone::Cvicinity_inclusion *> removed_from_cone; 00637 list<siscone::Cvicinity_inclusion *> put_in_border; 00638 list<CSphmomentum *> border_list; 00639 00640 CSphmomentum cone_removal; 00641 CSphmomentum border = *parent; 00642 border_list.push_back(parent); 00643 00644 // make sure child appears in the border region 00645 centre->cocircular.push_back(centre); 00646 00647 // now establish the full contents of the cone minus the cocircular 00648 // region and of the cocircular region itself 00649 for(list<CSphvicinity_elm *>::iterator it = centre->cocircular.begin(); 00650 it != centre->cocircular.end(); it++) { 00651 00652 if ((*it)->is_inside->cone) { 00653 cone_removal += *((*it)->v); 00654 (*it)->is_inside->cone = false; 00655 removed_from_cone.push_back((*it)->is_inside); 00656 } 00657 00658 // if a point appears twice (i.e. with + and - sign) in the list of 00659 // points on the border, we take care not to include it twice. 00660 // Note that this situation may appear when a point is at a distance 00661 // close to 2R from the parent 00662 if (!(*it)->is_inside->cocirc) { 00663 border += *((*it)->v); 00664 (*it)->is_inside->cocirc = true; 00665 put_in_border.push_back((*it)->is_inside); 00666 border_list.push_back((*it)->v); 00667 //cout << " adding particle " << (*it)->v->_theta << ", " << (*it)->v->_phi << " to the border list" << endl; 00668 } 00669 } 00670 00671 00672 // figure out whether this pairing has been observed before 00673 CSphmomentum borderless_cone = cone; 00674 borderless_cone -= cone_removal; 00675 bool consider = true; 00676 for (unsigned int i=0;i<multiple_centre_done.size();i++){ 00677 if ((multiple_centre_done[i].first ==borderless_cone.ref) && 00678 (multiple_centre_done[i].second==border.ref)) 00679 consider = false; 00680 } 00681 00682 // now prepare the hard work 00683 if (consider) { 00684 // record the fact that we've now seen this combination 00685 multiple_centre_done.push_back(pair<siscone::Creference,siscone::Creference>(borderless_cone.ref, 00686 border.ref)); 00687 00688 // first figure out whether our cone momentum is good 00689 double local_dpt = fabs(cone_removal.px) + fabs(cone_removal.py); 00690 double total_dpt = dpt + local_dpt; 00691 00692 recompute_cone_contents_if_needed(borderless_cone, total_dpt); 00693 if (total_dpt == 0) { 00694 // a recomputation has taken place -- so take advantage of this 00695 // and update the member cone momentum 00696 cone = borderless_cone + cone_removal; 00697 dpt = local_dpt; 00698 } 00699 00700 test_cone_cocircular(borderless_cone, border_list); 00701 } 00702 00703 00704 // relabel things that were in the cone but got removed 00705 for(list<siscone::Cvicinity_inclusion *>::iterator is_in = removed_from_cone.begin(); 00706 is_in != removed_from_cone.end(); is_in++) { 00707 (*is_in)->cone = true; 00708 } 00709 00710 // relabel things that got put into the border 00711 for(list<siscone::Cvicinity_inclusion *>::iterator is_in = put_in_border.begin(); 00712 is_in != put_in_border.end(); is_in++) { 00713 (*is_in)->cocirc = false; 00714 } 00715 00716 // we're done with everything -- return true to signal to user that we've 00717 // been through the co-circularity rigmarole 00718 return true; 00719 } 00720 00721 00723 // RECOMPUTATION OF CONE CONTENTS // 00724 // - compute_cone_contents() // 00725 // - recompute_cone_contents() // 00726 // - recompute_cone_contents_if_needed() // 00728 00737 void CSphstable_cones::compute_cone_contents() { 00738 siscone::circulator<vector<CSphvicinity_elm*>::iterator > 00739 start(vicinity.begin()+first_cone, vicinity.begin(), vicinity.end()); 00740 00741 siscone::circulator<vector<CSphvicinity_elm*>::iterator > here(start); 00742 00743 // note that in the following algorithm, the cone contents never includes 00744 // the child. Indeed, if it has positive sign, then it will be set as 00745 // outside at the last step in the loop. If it has negative sign, then the 00746 // loop will at some point go to the corresponding situation with positive 00747 // sign and set the inclusion status to 0. 00748 00749 do { 00750 // as we leave this position a particle enters if its side is 00751 // negative (i.e. the centre is the one at -ve angle wrt to the 00752 // parent-child line 00753 if (!(*here())->side) ((*here())->is_inside->cone) = 1; 00754 00755 // move on to the next position 00756 ++here; 00757 00758 // as we arrive at this position a particle leaves if its side is positive 00759 if ((*here())->side) ((*here())->is_inside->cone) = 0; 00760 } while (here != start); 00761 00762 // once we've reached the start the 'is_inside' information should be 00763 // 100% complete, so we can use it to calculate the cone contents 00764 // and then exit 00765 recompute_cone_contents(); 00766 return; 00767 00768 } 00769 00770 00771 /* 00772 * compute the cone momentum from particle list. 00773 * in this version, we use the 'pincluded' information 00774 * from the CSphvicinity class 00775 */ 00776 void CSphstable_cones::recompute_cone_contents(){ 00777 unsigned int i; 00778 00779 // set momentum to 0 00780 cone = CSphmomentum(); 00781 00782 // Important note: we can browse only the particles 00783 // in vicinity since all particles in the cone are 00784 // withing a distance 2R w.r.t. parent hence in vicinity. 00785 // Among those, we only add the particles for which 'is_inside' is true ! 00786 // This methos rather than a direct comparison avoids rounding errors 00787 for (i=0;i<vicinity_size;i++){ 00788 // to avoid double-counting, only use particles with + angle 00789 if ((vicinity[i]->side) && (vicinity[i]->is_inside->cone)) 00790 cone += *vicinity[i]->v; 00791 } 00792 00793 // set check variables back to 0 00794 dpt = 0.0; 00795 } 00796 00797 00798 /* 00799 * if we have gone beyond the acceptable threshold of change, compute 00800 * the cone momentum from particle list. in this version, we use the 00801 * 'pincluded' information from the CSphvicinity class, but we don't 00802 * change the member cone, only the locally supplied one 00803 */ 00804 void CSphstable_cones::recompute_cone_contents_if_needed(CSphmomentum & this_cone, 00805 double & this_dpt){ 00806 00807 if (this_dpt > PT_TSHOLD*(fabs(this_cone.px)+fabs(this_cone.py))) { 00808 if (cone.ref.is_empty()) { 00809 this_cone = CSphmomentum(); 00810 } else { 00811 // set momentum to 0 00812 this_cone = CSphmomentum(); 00813 00814 // Important note: we can browse only the particles 00815 // in vicinity since all particles in the this_cone are 00816 // withing a distance 2R w.r.t. parent hence in vicinity. 00817 // Among those, we only add the particles for which 'is_inside' is true ! 00818 // This methos rather than a direct comparison avoids rounding errors 00819 for (unsigned int i=0;i<vicinity_size;i++){ 00820 // to avoid double-counting, only use particles with + angle 00821 if ((vicinity[i]->side) && (vicinity[i]->is_inside->cone)) 00822 this_cone += *vicinity[i]->v; 00823 } 00824 00825 } 00826 // set check variables back to 0 00827 this_dpt = 0.0; 00828 } 00829 00830 } 00831 00832 00834 // VARIOUS TOOLS // 00835 // - circle_intersect() // 00836 // - is_inside() // 00837 // - abs_dangle() // 00839 00840 00841 /* 00842 * circle intersection. 00843 * computes the intersection with a circle of given centre and radius. 00844 * The output takes the form of a checkxor of the intersection's particles 00845 * - cx circle centre x coordinate 00846 * - cy circle centre y coordinate 00847 * return the checkxor for the intersection 00848 ******************************************************************/ 00849 siscone::Creference CSphstable_cones::circle_intersect(CSph3vector &cone_centre){ 00850 siscone::Creference intersection; 00851 int i; 00852 00853 for (i=0;i<n_part;i++){ 00854 // really check if the distance is less than R 00855 if (is_closer(&cone_centre, &(plist[i]), tan2R)) 00856 intersection+=plist[i].ref; 00857 } 00858 00859 return intersection; 00860 } 00861 00862 }