00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "fastjet/ClusterSequenceVoronoiArea.hh"
00032 #include "fastjet/internal/Voronoi.hh"
00033 #include <list>
00034 #include <cassert>
00035 #include <ostream>
00036 #include <iterator>
00037 #include <cmath>
00038 #include <limits>
00039
00040 using namespace std;
00041
00042 FASTJET_BEGIN_NAMESPACE
00043
00044 typedef ClusterSequenceVoronoiArea::VoronoiAreaCalc VAC;
00045
00048 class ClusterSequenceVoronoiArea::VoronoiAreaCalc {
00049 public:
00053 VoronoiAreaCalc(const vector<PseudoJet>::const_iterator &,
00054 const vector<PseudoJet>::const_iterator &,
00055 double effective_R);
00056
00059 inline double area (int index) const {return _areas[index];};
00060
00061 private:
00062 std::vector<double> _areas;
00063 double _effective_R;
00064 double _effective_R_squared;
00065
00070 double edge_circle_intersection(const Point &p0,
00071 const GraphEdge &edge);
00072
00076 inline double circle_area(const double d12_2, double d01_2, double d02_2){
00077 return 0.5*_effective_R_squared
00078 *acos((d01_2+d02_2-d12_2)/(2*sqrt(d01_2*d02_2)));
00079 }
00080 };
00081
00082
00087 double VAC::edge_circle_intersection(const Point &p0,
00088 const GraphEdge &edge){
00089 Point p1(edge.x1-p0.x, edge.y1-p0.y);
00090 Point p2(edge.x2-p0.x, edge.y2-p0.y);
00091 Point pdiff = p2-p1;
00092
00093
00094
00095 double cross = vector_product(p1, p2);
00096 double d12_2 = norm(pdiff);
00097 double d01_2 = norm(p1);
00098 double d02_2 = norm(p2);
00099
00100
00101 double delta = d12_2*_effective_R_squared - cross*cross;
00102
00103
00104 if (delta<=0){
00105 return circle_area(d12_2, d01_2, d02_2);
00106 }
00107
00108
00109 delta = sqrt(delta);
00110
00111
00112 double b = scalar_product(pdiff, p1);
00113
00114
00115
00116
00117
00118
00119
00120 double tp = (delta-b)/d12_2;
00121
00122
00123 if (tp<0)
00124 return circle_area(d12_2, d01_2, d02_2);
00125
00126
00127 double tm = -(delta+b)/d12_2;
00128
00129
00130 if (tp<1){
00131
00132
00133
00134
00135
00136
00137
00138 if (tm<0)
00139 return tp*0.5*fabs(cross)
00140 +circle_area((1-tp)*(1-tp)*d12_2, _effective_R_squared, d02_2);
00141
00142
00143
00144
00145
00146 return (tp-tm)*0.5*fabs(cross)
00147 + circle_area(tm*tm*d12_2, d01_2, _effective_R_squared)
00148 + circle_area((1-tp)*(1-tp)*d12_2, _effective_R_squared, d02_2);
00149 }
00150
00151
00152
00153
00154 if (tm>1)
00155 return circle_area(d12_2, d01_2, d02_2);
00156
00157
00158 if (tm<0)
00159 return 0.5*fabs(cross);
00160
00161
00162
00163
00164 return (1-tm)*0.5*fabs(cross)
00165 +circle_area(tm*tm*d12_2, d01_2, _effective_R_squared);
00166 }
00167
00168
00169
00170
00171 VAC::VoronoiAreaCalc(const vector<PseudoJet>::const_iterator &jet_begin,
00172 const vector<PseudoJet>::const_iterator &jet_end,
00173 double effective_R) {
00174
00175 assert(effective_R < 0.5*pi);
00176
00177 vector<Point> voronoi_particles;
00178 vector<int> voronoi_indices;
00179
00180 _effective_R = effective_R;
00181 _effective_R_squared = effective_R*effective_R;
00182
00183 double minrap = numeric_limits<double>::max();
00184 double maxrap = -minrap;
00185
00186 unsigned int n_tot = 0, n_added = 0;
00187
00188
00189
00190 for (vector<PseudoJet>::const_iterator jet_it = jet_begin;
00191 jet_it != jet_end; jet_it++) {
00192 _areas.push_back(0.0);
00193 if ((jet_it->perp2()) != 0.0 || (jet_it->E() != jet_it->pz())){
00194
00195 double rap = jet_it->rap(), phi = jet_it->phi();
00196 voronoi_particles.push_back(Point(rap, phi));
00197 voronoi_indices.push_back(n_tot);
00198 n_added++;
00199
00200
00201
00202
00203 if (phi < 2*_effective_R) {
00204 voronoi_particles.push_back(Point(rap,phi+twopi));
00205 voronoi_indices.push_back(-1);
00206 n_added++;
00207 } else if (twopi-phi < 2*_effective_R) {
00208 voronoi_particles.push_back(Point(rap,phi-twopi));
00209 voronoi_indices.push_back(-1);
00210 n_added++;
00211 }
00212
00213
00214 maxrap = max(maxrap,rap);
00215 minrap = min(minrap,rap);
00216 }
00217 n_tot++;
00218 }
00219
00220 assert(n_added > 0);
00221
00222
00223 double max_extend = 2*max(maxrap-minrap+4*_effective_R, twopi+8*_effective_R);
00224 voronoi_particles.push_back(Point(0.5*(minrap+maxrap)-max_extend, pi));
00225 voronoi_particles.push_back(Point(0.5*(minrap+maxrap)+max_extend, pi));
00226 voronoi_particles.push_back(Point(0.5*(minrap+maxrap), pi-max_extend));
00227 voronoi_particles.push_back(Point(0.5*(minrap+maxrap), pi+max_extend));
00228
00229
00230 VoronoiDiagramGenerator vdg;
00231 vdg.generateVoronoi(&voronoi_particles,
00232 0.5*(minrap+maxrap)-max_extend, 0.5*(minrap+maxrap)+max_extend,
00233 pi-max_extend, pi+max_extend);
00234
00235 vdg.resetIterator();
00236 GraphEdge *e=NULL;
00237 unsigned int v_index;
00238 int p_index;
00239 vector<PseudoJet>::const_iterator jet;
00240
00241 while(vdg.getNext(&e)){
00242 v_index = e->point1;
00243 if (v_index<n_added){
00244 p_index = voronoi_indices[v_index];
00245 if (p_index!=-1){
00246 jet = jet_begin+voronoi_indices[v_index];
00247 _areas[p_index]+=
00248 edge_circle_intersection(voronoi_particles[v_index], *e);
00249 }
00250 }
00251 v_index = e->point2;
00252 if (v_index<n_added){
00253 p_index = voronoi_indices[v_index];
00254 if (p_index!=-1){
00255 jet = jet_begin+voronoi_indices[v_index];
00256 _areas[p_index]+=
00257 edge_circle_intersection(voronoi_particles[v_index], *e);
00258 }
00259 }
00260 }
00261
00262 }
00263
00264
00265
00267 void ClusterSequenceVoronoiArea::_initializeVA () {
00268
00269 _pa_calc = new VAC(_jets.begin(),
00270 _jets.begin()+n_particles(),
00271 _effective_Rfact*_jet_def.R());
00272
00273
00274
00275 _voronoi_area.reserve(2*n_particles());
00276 for (unsigned int i=0; i<n_particles(); i++) {
00277 _voronoi_area.push_back(_pa_calc->area(i));
00278
00279 if (_jets[i].perp2() > 0) {
00280 _voronoi_area_4vector.push_back((_pa_calc->area(i)/_jets[i].perp())
00281 * _jets[i]);
00282 } else {
00283
00284
00285 _voronoi_area_4vector.push_back(PseudoJet(0.0,0.0,0.0,0.0));
00286 }
00287 }
00288
00289
00290 for (unsigned int i = n_particles(); i < _history.size(); i++) {
00291 double area;
00292 PseudoJet area_4vect;
00293 if (_history[i].parent2 >= 0) {
00294 area = _voronoi_area[_history[i].parent1] +
00295 _voronoi_area[_history[i].parent2];
00296 area_4vect = _voronoi_area_4vector[_history[i].parent1] +
00297 _voronoi_area_4vector[_history[i].parent2];
00298 } else {
00299 area = _voronoi_area[_history[i].parent1];
00300 area_4vect = _voronoi_area_4vector[_history[i].parent1];
00301 }
00302 _voronoi_area.push_back(area);
00303 _voronoi_area_4vector.push_back(area_4vect);
00304 }
00305
00306 }
00307
00308
00309 ClusterSequenceVoronoiArea::~ClusterSequenceVoronoiArea() {
00310 delete _pa_calc;
00311 }
00312
00313 FASTJET_END_NAMESPACE