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:: 195 $// 00024 // $Date:: 2008-01-15 15:30:58 -0500 (Tue, 15 Jan 2008) $// 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 protocones.push_back(Cmomentum(elm->eta, elm->phi, elm->ref)); 00374 } 00375 00376 // jump to the next one 00377 elm = elm->next; 00378 } 00379 } 00380 00381 // free hash 00382 // we do that at this level because hash eats rather a lot of memory 00383 // we want to free it before running the split/merge algorithm 00384 delete hc; 00385 hc=NULL; 00386 00387 return protocones.size(); 00388 } 00389 00390 00392 // ALGORITHM MAIN STEPS FOR COCIRCULAR SITUATIONS // 00393 // - cocircular_pt_less(v1, v2) // 00394 // - prepare_cocircular_list() // 00395 // - test_cone_cocircular() // 00396 // - test_stability(candidate, border_vect) // 00397 // - updat_cone_cocircular() // 00399 00401 bool cocircular_pt_less(Cmomentum *v1, Cmomentum *v2){ 00402 return v1->perp2() < v2->perp2(); 00403 } 00404 00405 /* 00406 * run through the vicinity of the current parent and for each child 00407 * establish which other members are cocircular... Note that the list 00408 * associated with each child contains references to vicinity 00409 * elements: thus two vicinity elements each associated with one given 00410 * particle may appear in a list -- this needs to be watched out for 00411 * later on... 00412 **********************************************************************/ 00413 void Cstable_cones::prepare_cocircular_lists() { 00414 circulator<vector<Cvicinity_elm*>::iterator > here(vicinity.begin(), 00415 vicinity.begin(), 00416 vicinity.end()); 00417 00418 circulator<vector<Cvicinity_elm*>::iterator > search(here); 00419 00420 do { 00421 Cvicinity_elm* here_pntr = *here(); 00422 search.set_position(here); 00423 00424 // search forwards for things that should have "here" included in 00425 // their cocircularity list 00426 while (true) { 00427 ++search; 00428 if ( abs_dphi((*search())->angle, here_pntr->angle) < 00429 here_pntr->cocircular_range 00430 && search() != here()) { 00431 (*search())->cocircular.push_back(here_pntr); 00432 } else { 00433 break; 00434 } 00435 } 00436 00437 // search backwards 00438 search.set_position(here); 00439 while (true) { 00440 --search; 00441 if ( abs_dphi((*search())->angle, here_pntr->angle) < 00442 here_pntr->cocircular_range 00443 && search() != here()) { 00444 (*search())->cocircular.push_back(here_pntr); 00445 } else { 00446 break; 00447 } 00448 } 00449 00450 ++here; 00451 } while (here() != vicinity.begin()); 00452 00453 } 00454 00455 /* 00456 * Testing cocircular configurations in p^3 time, 00457 * rather than 2^p time; we will test all contiguous subsets of points 00458 * on the border --- note that this is till probably overkill, since 00459 * in principle we only have to test situations where up to a 00460 * half-circle is filled (but going to a full circle is simpler) 00461 ******************************************************************/ 00462 void Cstable_cones::test_cone_cocircular(Cmomentum & borderless_cone, 00463 list<Cmomentum *> & border_list) { 00464 vector<Cborder_store> border_vect; 00465 00466 border_vect.reserve(border_list.size()); 00467 for (list<Cmomentum *>::iterator it = border_list.begin(); 00468 it != border_list.end(); it++) { 00469 border_vect.push_back(Cborder_store(*it, centre->eta, centre->phi)); 00470 } 00471 00472 // get them into order of angle 00473 sort(border_vect.begin(), border_vect.end()); 00474 00475 // set up some circulators, since these will help us go around the 00476 // circle easily 00477 circulator<vector<Cborder_store>::iterator > 00478 start(border_vect.begin(), border_vect.begin(),border_vect.end()); 00479 circulator<vector<Cborder_store>::iterator > mid(start), end(start); 00480 00481 // test the borderless cone 00482 Cmomentum candidate = borderless_cone; 00483 candidate.build_etaphi(); 00484 if (candidate.ref.not_empty()) 00485 test_stability(candidate, border_vect); 00486 00487 do { 00488 // reset status wrt inclusion in the cone 00489 mid = start; 00490 do { 00491 mid()->is_in = false; 00492 } while (++mid != start); 00493 00494 // now run over all inclusion possibilities with this starting point 00495 candidate = borderless_cone; 00496 while (++mid != start) { 00497 // will begin with start+1 and go up to start-1 00498 mid()->is_in = true; 00499 candidate += *(mid()->mom); 00500 test_stability(candidate, border_vect); 00501 } 00502 00503 } while (++start != end); 00504 00505 // mid corresponds to momentum that we need to include to get the 00506 // full cone 00507 mid()->is_in = true; 00508 candidate += *(mid()->mom); 00509 test_stability(candidate, border_vect); 00510 } 00511 00512 00519 void Cstable_cones::test_stability(Cmomentum & candidate, const vector<Cborder_store> & border_vect) { 00520 00521 // this almost certainly has not been done... 00522 candidate.build_etaphi(); 00523 00524 bool stable = true; 00525 for (unsigned i = 0; i < border_vect.size(); i++) { 00526 if (is_inside(&candidate, border_vect[i].mom) ^ (border_vect[i].is_in)) { 00527 stable = false; 00528 break; // it's unstable so there's no point continuing 00529 } 00530 } 00531 00532 if (stable) hc->insert(&candidate); 00533 } 00534 00535 /* 00536 * check if we are in a situation of cocircularity. 00537 * if it is the case, update and test in the corresponding way 00538 * return 'false' if no cocircularity detected, 'true' otherwise 00539 * Note that if cocircularity is detected, we need to 00540 * recall 'update' from 'update' !!! 00541 ***************************************************************/ 00542 bool Cstable_cones::cocircular_check(){ 00543 // check if many configurations have the same centre. 00544 // if this is the case, branch on the algorithm for this 00545 // special case. 00546 // Note that those situation, being considered separately in 00547 // test_cone_multiple, must only be considered here if all 00548 // angles are on the same side (this avoid multiple counting) 00549 00550 if (centre->cocircular.empty()) return false; 00551 00552 // first get cone into status required at end... 00553 if ((centre->side) && (cone.ref.not_empty())){ 00554 // update cone 00555 cone -= (*child); 00556 00557 // update info on particles inside 00558 centre->is_inside->cone = false; 00559 00560 // update stability check quantities 00561 dpt += fabs(child->px)+fabs(child->py); //child->perp2(); 00562 } 00563 00564 00565 // now establish the list of unique children in the list 00566 // first make sure parent and child are in! 00567 00568 list<Cvicinity_inclusion *> removed_from_cone; 00569 list<Cvicinity_inclusion *> put_in_border; 00570 list<Cmomentum *> border_list; 00571 00572 Cmomentum cone_removal; 00573 Cmomentum border = *parent; 00574 border_list.push_back(parent); 00575 00576 // make sure child appears in the border region 00577 centre->cocircular.push_back(centre); 00578 00579 // now establish the full contents of the cone minus the cocircular 00580 // region and of the cocircular region itself 00581 for(list<Cvicinity_elm *>::iterator it = centre->cocircular.begin(); 00582 it != centre->cocircular.end(); it++) { 00583 00584 if ((*it)->is_inside->cone) { 00585 cone_removal += *((*it)->v); 00586 (*it)->is_inside->cone = false; 00587 removed_from_cone.push_back((*it)->is_inside); 00588 } 00589 00590 // if a point appears twice (i.e. with + and - sign) in the list of 00591 // points on the border, we take care not to include it twice. 00592 // Note that this situation may appear when a point is at a distance 00593 // close to 2R from the parent 00594 if (!(*it)->is_inside->cocirc) { 00595 border += *((*it)->v); 00596 (*it)->is_inside->cocirc = true; 00597 put_in_border.push_back((*it)->is_inside); 00598 border_list.push_back((*it)->v); 00599 } 00600 } 00601 00602 00603 // figure out whether this pairing has been observed before 00604 Cmomentum borderless_cone = cone; 00605 borderless_cone -= cone_removal; 00606 bool consider = true; 00607 for (unsigned int i=0;i<multiple_centre_done.size();i++){ 00608 if ((multiple_centre_done[i].first ==borderless_cone.ref) && 00609 (multiple_centre_done[i].second==border.ref)) 00610 consider = false; 00611 } 00612 00613 // now prepare the hard work 00614 if (consider) { 00615 // record the fact that we've now seen this combination 00616 multiple_centre_done.push_back(pair<Creference,Creference>(borderless_cone.ref, 00617 border.ref)); 00618 00619 // first figure out whether our cone momentum is good 00620 double local_dpt = fabs(cone_removal.px) + fabs(cone_removal.py); 00621 double total_dpt = dpt + local_dpt; 00622 00623 recompute_cone_contents_if_needed(borderless_cone, total_dpt); 00624 if (total_dpt == 0) { 00625 // a recomputation has taken place -- so take advantage of this 00626 // and update the member cone momentum 00627 cone = borderless_cone + cone_removal; 00628 dpt = local_dpt; 00629 } 00630 00631 test_cone_cocircular(borderless_cone, border_list); 00632 } 00633 00634 00635 // relabel things that were in the cone but got removed 00636 for(list<Cvicinity_inclusion *>::iterator is_in = removed_from_cone.begin(); 00637 is_in != removed_from_cone.end(); is_in++) { 00638 (*is_in)->cone = true; 00639 } 00640 00641 // relabel things that got put into the border 00642 for(list<Cvicinity_inclusion *>::iterator is_in = put_in_border.begin(); 00643 is_in != put_in_border.end(); is_in++) { 00644 (*is_in)->cocirc = false; 00645 } 00646 00647 // we're done with everything -- return true to signal to user that we've 00648 // been through the co-circularity rigmarole 00649 return true; 00650 } 00651 00652 00654 // RECOMPUTATION OF CONE CONTENTS // 00655 // - compute_cone_contents() // 00656 // - recompute_cone_contents() // 00657 // - recompute_cone_contents_if_needed() // 00659 00668 void Cstable_cones::compute_cone_contents() { 00669 circulator<vector<Cvicinity_elm*>::iterator > 00670 start(vicinity.begin()+first_cone, vicinity.begin(), vicinity.end()); 00671 00672 circulator<vector<Cvicinity_elm*>::iterator > here(start); 00673 00674 // note that in the following algorithm, the cone contents never includes 00675 // the child. Indeed, if it has positive sign, then it will be set as 00676 // outside at the last step in the loop. If it has negative sign, then the 00677 // loop will at some point go to the corresponding situation with positive 00678 // sign and set the inclusion status to 0. 00679 00680 do { 00681 // as we leave this position a particle enters if its side is 00682 // negative (i.e. the centre is the one at -ve angle wrt to the 00683 // parent-child line 00684 if (!(*here())->side) ((*here())->is_inside->cone) = 1; 00685 00686 // move on to the next position 00687 ++here; 00688 00689 // as we arrive at this position a particle leaves if its side is positive 00690 if ((*here())->side) ((*here())->is_inside->cone) = 0; 00691 } while (here != start); 00692 00693 // once we've reached the start the 'is_inside' information should be 00694 // 100% complete, so we can use it to calculate the cone contents 00695 // and then exit 00696 recompute_cone_contents(); 00697 return; 00698 00699 } 00700 00701 00702 /* 00703 * compute the cone momentum from particle list. 00704 * in this version, we use the 'pincluded' information 00705 * from the Cvicinity class 00706 */ 00707 void Cstable_cones::recompute_cone_contents(){ 00708 unsigned int i; 00709 00710 // set momentum to 0 00711 cone = Cmomentum(); 00712 00713 // Important note: we can browse only the particles 00714 // in vicinity since all particles in the cone are 00715 // withing a distance 2R w.r.t. parent hence in vicinity. 00716 // Among those, we only add the particles for which 'is_inside' is true ! 00717 // This methos rather than a direct comparison avoids rounding errors 00718 for (i=0;i<vicinity_size;i++){ 00719 // to avoid double-counting, only use particles with + angle 00720 if ((vicinity[i]->side) && (vicinity[i]->is_inside->cone)) 00721 cone += *vicinity[i]->v; 00722 } 00723 00724 // set check variables back to 0 00725 dpt = 0.0; 00726 } 00727 00728 00729 /* 00730 * if we have gone beyond the acceptable threshold of change, compute 00731 * the cone momentum from particle list. in this version, we use the 00732 * 'pincluded' information from the Cvicinity class, but we don't 00733 * change the member cone, only the locally supplied one 00734 */ 00735 void Cstable_cones::recompute_cone_contents_if_needed(Cmomentum & this_cone, 00736 double & this_dpt){ 00737 00738 if (this_dpt > PT_TSHOLD*(fabs(this_cone.px)+fabs(this_cone.py))) { 00739 if (cone.ref.is_empty()) { 00740 this_cone = Cmomentum(); 00741 } else { 00742 // set momentum to 0 00743 this_cone = Cmomentum(); 00744 00745 // Important note: we can browse only the particles 00746 // in vicinity since all particles in the this_cone are 00747 // withing a distance 2R w.r.t. parent hence in vicinity. 00748 // Among those, we only add the particles for which 'is_inside' is true ! 00749 // This methos rather than a direct comparison avoids rounding errors 00750 for (unsigned int i=0;i<vicinity_size;i++){ 00751 // to avoid double-counting, only use particles with + angle 00752 if ((vicinity[i]->side) && (vicinity[i]->is_inside->cone)) 00753 this_cone += *vicinity[i]->v; 00754 } 00755 00756 } 00757 // set check variables back to 0 00758 this_dpt = 0.0; 00759 } 00760 00761 } 00762 00763 00765 // VARIOUS TOOLS // 00766 // - circle_intersect() // 00767 // - is_inside() // 00768 // - abs_dangle() // 00770 00771 00772 /* 00773 * circle intersection. 00774 * computes the intersection with a circle of given centre and radius. 00775 * The output takes the form of a checkxor of the intersection's particles 00776 * - cx circle centre x coordinate 00777 * - cy circle centre y coordinate 00778 * return the checkxor for the intersection 00779 ******************************************************************/ 00780 Creference Cstable_cones::circle_intersect(double cx, double cy){ 00781 Creference intersection; 00782 int i; 00783 double dx, dy; 00784 00785 for (i=0;i<n_part;i++){ 00786 // compute the distance of the i-th particle with the parent 00787 dx = plist[i].eta - cx; 00788 dy = fabs(plist[i].phi - cy); 00789 00790 // pay attention to the periodicity in phi ! 00791 if (dy>M_PI) 00792 dy -= twopi; 00793 00794 // really check if the distance is less than VR 00795 if (dx*dx+dy*dy<R2) 00796 intersection+=plist[i].ref; 00797 } 00798 00799 return intersection; 00800 } 00801 00802 /* 00803 * test if a particle is inside a cone of given centre. 00804 * check if the particle of coordinates 'v' is inside the circle of radius R 00805 * centered at 'centre'. 00806 * - centre centre of the circle 00807 * - v particle to test 00808 * return true if inside, false if outside 00809 *****************************************************************************/ 00810 inline bool Cstable_cones::is_inside(Cmomentum *centre, Cmomentum *v){ 00811 double dx, dy; 00812 00813 dx = centre->eta - v->eta; 00814 dy = fabs(centre->phi - v->phi); 00815 if (dy>M_PI) 00816 dy -= twopi; 00817 00818 return dx*dx+dy*dy<R2; 00819 } 00820 00821 /* 00822 * compute the absolute value of the difference between 2 angles. 00823 * We take care of the 2pi periodicity 00824 * - angle1 first angle 00825 * - angle2 second angle 00826 * return the absolute value of the difference between the angles 00827 *****************************************************************/ 00828 inline double abs_dangle(double &angle1, double &angle2){ 00829 double dphi; 00830 00831 dphi = fabs(angle1-angle2); 00832 if (dphi>M_PI) 00833 dphi = dphi-twopi; 00834 00835 return dphi; 00836 } 00837 00838 }