SISCone  2.0.5
siscone/spherical/vicinity.cpp
00001 
00002 // File: vicinity.cpp                                                        //
00003 // Description: source file for particle vicinity (Cvicinity class)          //
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:: 255                                                          $//
00026 // $Date:: 2008-07-12 17:40:35 +0200 (Sat, 12 Jul 2008)                     $//
00028 
00029 #include "vicinity.h"
00030 #include <math.h>
00031 #include <algorithm>
00032 #include <iostream>
00033 
00034 namespace siscone_spherical{
00035 
00036 using namespace std;
00037 
00038 /*************************************************************
00039  * CSphvicinity_elm implementation                           *
00040  * element in the vicinity of a parent.                      *
00041  * class used to manage one points in the vicinity           *
00042  * of a parent point.                                        *
00043  *************************************************************/
00044 
00045 // ordering pointers to CSphvicinity_elm
00046 //---------------------------------------
00047 bool ve_less(CSphvicinity_elm *ve1, CSphvicinity_elm *ve2){
00048   return ve1->angle < ve2->angle;
00049 }
00050 
00051 
00052 /*************************************************************
00053  * CSphvicinity implementation                               *
00054  * list of element in the vicinity of a parent.              *
00055  * class used to manage the points which are in the vicinity *
00056  * of a parent point. The construction of the list can be    *
00057  * made from a list of points or from a quadtree.            *
00058  *************************************************************/
00059 
00060 // default constructor
00061 //---------------------
00062 CSphvicinity::CSphvicinity(){
00063   n_part = 0;
00064 
00065   ve_list = NULL;
00066 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00067   quadtree = NULL;
00068 #endif
00069 
00070   parent = NULL;
00071   VR2 = VR = 0.0;
00072 
00073 }
00074 
00075 // constructor with initialisation
00076 //---------------------------------
00077 CSphvicinity::CSphvicinity(vector<CSphmomentum> &_particle_list){
00078   parent = NULL;
00079   ve_list = NULL;
00080 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00081   quadtree = NULL;
00082 #endif
00083   cosVR = VR2 = tan2R = VR = 0.0;
00084 
00085   set_particle_list(_particle_list);
00086 }
00087 
00088 // default destructor
00089 //--------------------
00090 CSphvicinity::~CSphvicinity(){
00091   if (ve_list!=NULL)
00092     delete[] ve_list;
00093 
00094 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00095   if (quadtree!=NULL)
00096     delete quadtree;
00097 #endif
00098 }
00099 
00100 /*
00101  * set the particle_list
00102  *  - particle_list   list of particles (type CSphmomentum)
00103  *  - n               number of particles in the list
00104  ************************************************************/ 
00105 void CSphvicinity::set_particle_list(vector<CSphmomentum> &_particle_list){
00106   int i,j;
00107 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00108   double eta_max=0.0;
00109 #endif
00110   
00111   // if the particle list is not empty, destroy it !
00112   if (ve_list!=NULL){
00113     delete[] ve_list;
00114   }
00115   vicinity.clear();
00116 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00117   if (quadtree!=NULL)
00118     delete quadtree;
00119 #endif
00120 
00121   // allocate memory array for particles
00122   // Note: - we compute max for |eta|
00123   //       - we allocate indices to particles
00124   n_part = 0;
00125   plist.clear();
00126   pincluded.clear();
00127   for (i=0;i<(int) _particle_list.size();i++){
00128     // if a particle is colinear with the beam (infinite rapidity)
00129     // we do not take it into account
00130     //if (fabs(_particle_list[i].pz)!=_particle_list[i].E){
00131       plist.push_back(_particle_list[i]);
00132       pincluded.push_back(siscone::Cvicinity_inclusion()); // zero inclusion status
00133 
00134       // the parent_index is handled in the split_merge because 
00135       // of our multiple-pass procedure.
00136       // Hence, it is not required here any longer.
00137       // plist[n_part].parent_index = i;
00138       plist[n_part].index = n_part;
00139 
00140       // make sure the reference is randomly created
00141       plist[n_part].ref.randomize();
00142 
00143 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00144       if (fabs(plist[n_part].eta)>eta_max) eta_max=fabs(plist[n_part].eta);
00145 #endif
00146       n_part++;
00147       //}
00148   }
00149 
00150   // allocate quadtree and vicinity_elm list
00151   // note: we set phi in [-pi:pi] as it is the natural range for atan2!
00152   ve_list = new CSphvicinity_elm[2*n_part];
00153 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00154   eta_max+=0.1;
00155   quadtree = new siscone::Cquadtree(0.0, 0.0, eta_max, M_PI);
00156 #endif
00157 
00158   // append particle to the vicinity_elm list
00159   j = 0;
00160   for (i=0;i<n_part;i++){
00161 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00162     quadtree->add(&plist[i]);
00163 #endif
00164     ve_list[j].v = ve_list[j+1].v = &plist[i];
00165     ve_list[j].is_inside = ve_list[j+1].is_inside = &(pincluded[i]);
00166     j+=2;
00167   }
00168 
00169 }
00170 
00171 
00172 /*
00173  * build the vicinity list from a list of points.
00174  *  - _parent   reference particle
00175  *  - _VR       vicinity radius
00176  ************************************************************/
00177 void CSphvicinity::build(CSphmomentum *_parent, double _VR){
00178   int i;
00179 
00180   // set parent and radius
00181   parent = _parent;
00182 
00183   VR  = _VR;
00184   VR2 = VR*VR;
00185   cosVR = cos(VR);
00186   R2  = 0.25*VR2;
00187   R   = 0.5*VR;
00188   double tmp = tan(R);
00189   tan2R = tmp*tmp;
00190 
00191   D2_R = 2.0*(1-cos(R));
00192   //tmp = sqrt(D2_R);
00193   inv_R_EPS_COCIRC  = 1.0 / R / EPSILON_COCIRCULAR;
00194   inv_R_2EPS_COCIRC = 0.5 / R / EPSILON_COCIRCULAR;
00195 
00196   // clear vicinity
00197   vicinity.clear();
00198 
00199   // init parent variables
00200   // we cpte the direction of the centre and two orthogonal ones 
00201   // to measure the angles. Those are taken orthogonal to the
00202   // axis of smallest components (of the centre) to increase precision
00203   parent_centre = (*parent)/parent->_norm;
00204   parent_centre.get_angular_directions(angular_dir1, angular_dir2);
00205   angular_dir1 /= angular_dir1._norm;
00206   angular_dir2 /= angular_dir2._norm;
00207   
00208   // really browse the particle list
00209   for (i=0;i<n_part;i++){
00210     append_to_vicinity(&plist[i]);
00211   }
00212 
00213   // sort the vicinity
00214   sort(vicinity.begin(), vicinity.end(), ve_less);
00215 
00216   vicinity_size = vicinity.size();
00217 }
00218 
00219 
00221 //TODO//
00222 inline double sort_angle(double s, double c){
00223   if (s==0) return (c>0) ? 0.0 : 2.0;
00224   double t=c/s;
00225   return (s>0) ? 1-t/(1+fabs(t)) : 3-t/(1+fabs(t));
00226 }
00227 
00228 
00229 /*
00230  * append a particle to the 'vicinity' list after
00231  * having computed the angular-ordering quantities
00232  *  - v   vector to test
00233  **********************************************************/
00234 void CSphvicinity::append_to_vicinity(CSphmomentum *v){
00235   // skip the particle itself)
00236   if (v==parent)
00237     return;
00238 
00239   int i=2*(v->index);
00240 
00241   // compute the distance of the i-th particle with the parent
00242   double dot = dot_product3(parent_centre,*v);
00243   CSph3vector vnormal = *v;
00244   vnormal/=v->_norm;
00245   dot/=v->_norm;
00246 
00247   // really check if the distance is less than VR
00248   if (dot>cosVR){
00249     CSph3vector cross = cross_product3(parent_centre,vnormal);
00250 
00251     // for the centres
00252     CSph3vector median = (parent_centre+vnormal);
00253     double amplT = sqrt((tan2R*(1+dot)+(dot-1))*(1+dot));
00254     CSph3vector transverse = amplT*cross/cross._norm;
00255 
00256     // first angle (+)
00257     ve_list[i].centre = median + transverse;
00258     ve_list[i].centre.build_norm();
00259     ve_list[i].centre/=ve_list[i].centre._norm;    
00260     CSph3vector diff = ve_list[i].centre - parent_centre;
00261     //ve_list[i].angle = atan2(dot_product3(angular_dir2, diff),dot_product3(angular_dir1, diff));
00262     ve_list[i].angle = sort_angle(dot_product3(angular_dir2, diff),dot_product3(angular_dir1, diff));
00263     ve_list[i].side = true;
00264     ve_list[i].cocircular.clear();
00265     vicinity.push_back(&(ve_list[i]));
00266 
00267     // second angle (-)    
00268     ve_list[i+1].centre = median - transverse;
00269     ve_list[i+1].centre.build_norm();
00270     ve_list[i+1].centre/=ve_list[i+1].centre._norm;    
00271     diff = ve_list[i+1].centre - parent_centre;
00272     ve_list[i+1].angle = sort_angle(dot_product3(angular_dir2, diff),dot_product3(angular_dir1, diff));
00273     ve_list[i+1].side = false;
00274     ve_list[i+1].cocircular.clear();
00275     vicinity.push_back(&(ve_list[i+1]));
00276 
00277     // now work out the cocircularity range for the two points (range
00278     // of angle within which the points stay within a distance
00279     // EPSILON_COCIRCULAR of circule
00280     // P = parent; C = child; O = Origin (center of circle)
00281     CSph3vector OP = parent_centre - ve_list[i+1].centre;
00282     CSph3vector OC = vnormal - ve_list[i+1].centre;
00283     
00284     // two sources of error are (GPS CCN29-19) epsilon/(R sin theta)
00285     // and sqrt(2*epsilon/(R (1-cos theta))) and the way things work
00286     // out, it is the _smaller_ of the two that is relevant [NB have
00287     // changed definition of theta here relative to that used in
00288     // CCN29] [NB2: write things so as to avoid zero denominators and
00289     // to minimize the multiplications, divisions and above all sqrts
00290     // -- that means that c & s are defined including a factor of VR2]
00291     double inv_err1 = cross_product3(OP,OC)._norm * inv_R_EPS_COCIRC;
00292     double inv_err2_sq = (D2_R-dot_product3(OP,OC)) * inv_R_2EPS_COCIRC;
00293     ve_list[i].cocircular_range = siscone::pow2(inv_err1) > inv_err2_sq ? 
00294       1.0/inv_err1 : 
00295       sqrt(1.0/inv_err2_sq);
00296     ve_list[i+1].cocircular_range = ve_list[i].cocircular_range;
00297   }
00298 }
00299 
00300 }
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