SISCone  2.0.5
siscone/quadtree.cpp
00001 
00002 // File: quadtree.cpp                                                        //
00003 // Description: source file for quadtree management (Cquadtree class)        //
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:: 320                                                          $//
00024 // $Date:: 2011-11-15 09:54:50 +0100 (Tue, 15 Nov 2011)                     $//
00026 
00027 #include "quadtree.h"
00028 #include <math.h>
00029 #include <stdio.h>
00030 #include <iostream>
00031 
00032 namespace siscone{
00033 
00034 using namespace std;
00035 
00036 /*******************************************************************
00037  * Cquadtree implementation                                        *
00038  * Implementation of a 2D quadtree.                                *
00039  * This class implements the traditional two-dimensional quadtree. *
00040  * The elements at each node are of 'Cmomentum' type.              *
00041  *******************************************************************/
00042 
00043 // default ctor
00044 //--------------
00045 Cquadtree::Cquadtree(){
00046   v = NULL;
00047 
00048   children[0][0] = children[0][1] = children[1][0] = children[1][1] = NULL;
00049   has_child = false;
00050 }
00051 
00052 
00053 // ctor with initialisation (see init for details)
00054 //--------------------------
00055 Cquadtree::Cquadtree(double _x, double _y, double _half_size_x, double _half_size_y){
00056   v = NULL;
00057 
00058   children[0][0] = children[0][1] = children[1][0] = children[1][1] = NULL;
00059   has_child = false;
00060 
00061   init(_x, _y, _half_size_x, _half_size_y);
00062 }
00063 
00064 
00065 // default destructor
00066 // at destruction, everything is destroyed except 
00067 // physical values at the leaves
00068 //------------------------------------------------
00069 Cquadtree::~Cquadtree(){
00070   if (has_child){
00071     if (v!=NULL) delete v;
00072     delete children[0][0];
00073     delete children[0][1];
00074     delete children[1][0];
00075     delete children[1][1];
00076   }
00077 }
00078 
00079 
00080 /*
00081  * init the tree.
00082  * By initializing the tree, we mean setting the cell parameters
00083  * and preparing the object to act as a seed for a new tree.
00084  *  - _x           x-position of the center
00085  *  - _y           y-position of the center
00086  *  - half_size_x  half x-size of the cell
00087  *  - half_size_y  half y-size of the cell
00088  * return 0 on success, 1 on error. Note that if the cell
00089  *        is already filled, we return an error.
00090  ******************************************************************/
00091 int Cquadtree::init(double _x, double _y, double _half_size_x, double _half_size_y){
00092   if (v!=NULL)
00093     return 1;
00094 
00095   centre_x = _x;
00096   centre_y = _y;
00097   half_size_x = _half_size_x;
00098   half_size_y = _half_size_y;
00099 
00100   return 0;
00101 }
00102 
00103 
00104 /*
00105  * adding a particle to the tree.
00106  * This method adds one vector to the quadtree structure which 
00107  * is updated consequently.
00108  *  - v   vector to add
00109  * return 0 on success 1 on error
00110  ******************************************************************/
00111 int Cquadtree::add(Cmomentum *v_add){
00112   // Description of the method:
00113   // --------------------------
00114   // the addition process goes as follows:
00115   //  1. check if the cell is empty, in which case, add the particle 
00116   //     here and leave.
00117   //  2. If there is a unique particle already inside,
00118   //      (a) create children
00119   //      (b) forward the existing particle to the appropriate child
00120   //  3. Add current particle to this cell and forward to the 
00121   //     adequate child
00122   // NOTE: we assume in the whole procedure that the particle is 
00123   //       indeed inside the cell !
00124 
00125   // step 1: the case of empty cells
00126   if (v==NULL){
00127     v = v_add;
00128     return 0;
00129   }
00130 
00131   // step 2: additional work if 1! particle already present
00132   //         we use the fact that only 1-particle systems have no child
00133   if (!has_child){
00134     double new_half_size_x = 0.5*half_size_x;
00135     double new_half_size_y = 0.5*half_size_y;
00136     // create children
00137     children[0][0] = new Cquadtree(centre_x-new_half_size_x, centre_y-new_half_size_y,
00138                                    new_half_size_x, new_half_size_y);
00139     children[0][1] = new Cquadtree(centre_x-new_half_size_x, centre_y+new_half_size_y,
00140                                    new_half_size_x, new_half_size_y);
00141     children[1][0] = new Cquadtree(centre_x+new_half_size_x, centre_y-new_half_size_y,
00142                                    new_half_size_x, new_half_size_y);
00143     children[1][1] = new Cquadtree(centre_x+new_half_size_x, centre_y+new_half_size_y,
00144                                    new_half_size_x, new_half_size_y);
00145 
00146     has_child = true;
00147 
00148     // forward to child
00149     //? The following line assumes 'true'==1 and 'false'==0
00150     // Note: v being a single particle, eta and phi are correct
00151     children[v->eta>centre_x][v->phi>centre_y]->add(v);
00152 
00153     // copy physical params
00154     v = new Cmomentum(*v);
00155   }
00156 
00157   // step 3: add new particle
00158   // Note: v_add being a single particle, eta and phi are correct
00159   children[v_add->eta>centre_x][v_add->phi>centre_y]->add(v_add);
00160   *v+=*v_add;
00161 
00162   return 0;
00163 }
00164 
00165 
00166 /*
00167  * circle intersection.
00168  * computes the intersection with a circle of given centre and radius.
00169  * The output takes the form of a quadtree with all squares included 
00170  * in the circle.
00171  *  - cx    circle centre x coordinate
00172  *  - cy    circle centre y coordinate
00173  *  - cR2   circle radius SQUARED
00174  * return the checksum for the intersection
00175  ******************************************************************/
00176 Creference Cquadtree::circle_intersect(double cx, double cy, double cR2){
00177   // Description of the method:
00178   // --------------------------
00179   // 1. check if cell is empty => no intersection
00180   // 2. if cell has 1! particle, check if it is inside the circle.
00181   //    If yes, add it and return, if not simply return.
00182   // 3. check if the circle intersects the square. If not, return.
00183   // 4. check if the square is inside the circle. 
00184   //    If yes, add it to qt and return.
00185   // 5. check intersections with children.
00186 
00187   // step 1: if there is no particle inside te square, no reason to go further
00188   if (v==NULL)
00189     return Creference();
00190 
00191   double dx, dy;
00192 
00193   // step 2: if there is only one particle inside the square, test if it is in
00194   //         the circle, in which case return associated reference
00195   if (!has_child){
00196     // compute the distance
00197     // Note: v has only one particle => eta and phi are defined
00198     dx = cx - v->eta;
00199     dy = fabs(cy - v->phi);
00200     if (dy>M_PI) 
00201       dy -= 2.0*M_PI;
00202 
00203     // test distance
00204     if (dx*dx+dy*dy<cR2){
00205       return v->ref;
00206     }
00207 
00208     return Creference();
00209   }
00210 
00211   // step 3: check if there is an intersection
00212   //double ryp, rym;
00213   double dx_c, dy_c;
00214 
00215   // store distance with the centre of the square
00216   dx_c = fabs(cx-centre_x);
00217   dy_c = fabs(cy-centre_y);
00218   if (dy_c>M_PI) dy_c = 2.0*M_PI-dy_c;
00219 
00220   // compute (minimal) the distance (pay attention to the periodicity in phi).
00221   dx = dx_c-half_size_x;
00222   if (dx<0) dx=0;
00223   dy = dy_c-half_size_y;
00224   if (dy<0) dy=0;
00225 
00226   // check the distance 
00227   if (dx*dx+dy*dy>=cR2){
00228     // no intersection
00229     return Creference();
00230   }
00231 
00232   // step 4: check if included
00233 
00234   // compute the (maximal) distance
00235   dx = dx_c+half_size_x;
00236   dy = dy_c+half_size_y;
00237   if (dy>M_PI) dy = M_PI;
00238 
00239   // compute the distance
00240   if (dx*dx+dy*dy<cR2){
00241     return v->ref;
00242   }
00243 
00244   // step 5: the square is not fully in. Recurse to children
00245   return children[0][0]->circle_intersect(cx, cy, cR2)
00246     + children[0][1]->circle_intersect(cx, cy, cR2)
00247     + children[1][0]->circle_intersect(cx, cy, cR2)
00248     + children[1][1]->circle_intersect(cx, cy, cR2);
00249 }
00250 
00251 
00252 /*
00253  * output a data file for drawing the grid.
00254  * This can be used to output a data file containing all the
00255  * grid subdivisions. The file contents is as follows:
00256  * first and second columns give center of the cell, the third 
00257  * gives the size.
00258  *  - flux  opened stream to write to
00259  * return 0 on success, 1 on error
00260  ******************************************************************/
00261 int Cquadtree::save(FILE *flux){
00262 
00263   if (flux==NULL)
00264     return 1;
00265 
00266   if (has_child){
00267     fprintf(flux, "%e\t%e\t%e\t%e\n", centre_x, centre_y, half_size_x, half_size_y);
00268     children[0][0]->save(flux);
00269     children[0][1]->save(flux);
00270     children[1][0]->save(flux);
00271     children[1][1]->save(flux);
00272   }
00273 
00274   return 0;
00275 }
00276 
00277 
00278 /*
00279  * output a data file for drawing the tree leaves.
00280  * This can be used to output a data file containing all the
00281  * tree leaves. The file contents is as follows:
00282  * first and second columns give center of the cell, the third 
00283  * gives the size.
00284  *  - flux  opened stream to write to
00285  * return 0 on success, 1 on error
00286  ******************************************************************/
00287 int Cquadtree::save_leaves(FILE *flux){
00288 
00289   if (flux==NULL)
00290     return 1;
00291 
00292   if (has_child){
00293     if (children[0][0]!=NULL) children[0][0]->save_leaves(flux);
00294     if (children[0][1]!=NULL) children[0][1]->save_leaves(flux);
00295     if (children[1][0]!=NULL) children[1][0]->save_leaves(flux);
00296     if (children[1][1]!=NULL) children[1][1]->save_leaves(flux);
00297   } else {
00298     fprintf(flux, "%e\t%e\t%e\t%e\n", centre_x, centre_y, half_size_x, half_size_y);
00299   }
00300 
00301   return 0;
00302 }
00303 
00304 }
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