SISCone  2.0.5
siscone/protocones.cpp
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 }
The SISCone project has been developed by Gavin Salam and Gregory Soyez
Documentation generated on Mon Jun 4 2012 18:23:38 for SISCone by  Doxygen 1.7.6.1