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