114 #include "fastjet/internal/Voronoi.hh" 
  118 FASTJET_BEGIN_NAMESPACE
 
  120 LimitedWarning VoronoiDiagramGenerator::_warning_degeneracy;
 
  122 VoronoiDiagramGenerator::VoronoiDiagramGenerator(){
 
  127   allMemoryList = 
new FreeNodeArrayList;
 
  128   allMemoryList->memory = NULL;
 
  129   allMemoryList->next = NULL;
 
  130   currentMemoryBlock = allMemoryList;
 
  133   minDistanceBetweenSites = 0;
 
  139 VoronoiDiagramGenerator::~VoronoiDiagramGenerator(){
 
  143   if (allMemoryList != NULL)
 
  144     delete allMemoryList;
 
  149 bool VoronoiDiagramGenerator::generateVoronoi(vector<VPoint> *_parent_sites,
 
  150                                               double minX, 
double maxX, 
 
  151                                               double minY, 
double maxY, 
 
  158   minDistanceBetweenSites = minDist;
 
  160   parent_sites = _parent_sites;
 
  162   nsites = n_parent_sites = parent_sites->size();
 
  165   freeinit(&sfl, 
sizeof (Site));
 
  168   sites = (Site *) myalloc(nsites*
sizeof( Site));
 
  174   xmax = xmin = (*parent_sites)[0].x;
 
  175   ymax = ymin = (*parent_sites)[0].y;
 
  177   for(i=0;i<nsites;i++){
 
  178     x = (*parent_sites)[i].x;
 
  179     y = (*parent_sites)[i].y;
 
  180     sites[i].coord.x = x;
 
  181     sites[i].coord.y = y;
 
  182     sites[i].sitenbr = i;
 
  196   qsort(sites, nsites, 
sizeof (*sites), scomp);
 
  205   unsigned int offset=0;
 
  206   for (
int is=1;is<nsites;is++){
 
  207     if (sites[is].coord.y==sites[is-1].coord.y && sites[is].coord.x==sites[is-1].coord.x){
 
  209     } 
else if (offset>0){
 
  210       sites[is-offset] = sites[is];
 
  216     _warning_degeneracy.warn(
"VoronoiDiagramGenerator: two (or more) particles are degenerate in rapidity and azimuth, Voronoi cell assigned to the first of each set of degenerate particles.");
 
  243 bool VoronoiDiagramGenerator::ELinitialize(){
 
  245   freeinit(&hfl, 
sizeof(Halfedge));
 
  246   ELhashsize = 2 * sqrt_nsites;
 
  248   ELhash = (Halfedge **) myalloc ( 
sizeof(Halfedge*)*ELhashsize);
 
  253   for(i=0; i<ELhashsize; i +=1) ELhash[i] = (Halfedge *)NULL;
 
  254   ELleftend = HEcreate((Edge*) NULL, 0);
 
  255   ELrightend = HEcreate((Edge*) NULL, 0);
 
  256   ELleftend->ELleft = (Halfedge*) NULL;
 
  257   ELleftend->ELright = ELrightend;
 
  258   ELrightend->ELleft = ELleftend;
 
  259   ELrightend->ELright = (Halfedge*) NULL;
 
  260   ELhash[0] = ELleftend;
 
  261   ELhash[ELhashsize-1] = ELrightend;
 
  267 Halfedge* VoronoiDiagramGenerator::HEcreate(Edge *e,
int pm){
 
  269   answer = (Halfedge*) getfree(&hfl);
 
  272   answer->PQnext = (Halfedge*) NULL;
 
  273   answer->vertex = (Site*) NULL;
 
  274   answer->ELrefcnt = 0;
 
  279 void VoronoiDiagramGenerator::ELinsert(Halfedge *lb, Halfedge *newHe)
 
  282   newHe->ELright = lb->ELright;
 
  283   (lb->ELright)->ELleft = newHe;
 
  289 Halfedge* VoronoiDiagramGenerator::ELgethash(
int b){
 
  292   if ((b<0) || (b>=ELhashsize)) 
 
  293     return (Halfedge *) NULL;
 
  296   if ((he==(Halfedge*) NULL) || (he->ELedge!=(Edge*) DELETED)) 
 
  300   ELhash[b] = (Halfedge*) NULL;
 
  301   if ((he->ELrefcnt -= 1) == 0) 
 
  302     makefree((Freenode*)he, &hfl);
 
  303   return (Halfedge*) NULL;
 
  306 Halfedge * VoronoiDiagramGenerator::ELleftbnd(VPoint *p){
 
  329   if (p->x < xmin){ bucket=0;}
 
  330   else if (p->x >= xmax){ bucket = ELhashsize - 1;}
 
  332     bucket= (int)((p->x - xmin)/deltax * ELhashsize);
 
  333     if (bucket>=ELhashsize) bucket = ELhashsize - 1;  
 
  336   he = ELgethash(bucket);
 
  340   if (he == (Halfedge*) NULL){   
 
  342       if ((he=ELgethash(bucket-i)) != (Halfedge*) NULL) 
 
  344       if ((he=ELgethash(bucket+i)) != (Halfedge*) NULL) 
 
  351   if ((he==ELleftend)  || (he != ELrightend && right_of(he,p))){
 
  354     } 
while (he!=ELrightend && right_of(he,p));
 
  363     } 
while ((he!=ELleftend )&& (!right_of(he,p)));
 
  366   if ((bucket > 0) && (bucket <ELhashsize-1)){  
 
  367     if(ELhash[bucket] != (Halfedge *) NULL){
 
  368       ELhash[bucket]->ELrefcnt -= 1;
 
  371     ELhash[bucket]->ELrefcnt += 1;
 
  380 void VoronoiDiagramGenerator::ELdelete(Halfedge *he){
 
  381   (he->ELleft)->ELright = he->ELright;
 
  382   (he->ELright)->ELleft = he->ELleft;
 
  383   he->ELedge = (Edge*) DELETED;
 
  387 Halfedge* VoronoiDiagramGenerator::ELright(Halfedge *he){
 
  392 Halfedge* VoronoiDiagramGenerator::ELleft(Halfedge *he){
 
  397 Site * VoronoiDiagramGenerator::leftreg(Halfedge *he){
 
  398   if (he->ELedge == (Edge*) NULL) 
 
  400   return (he->ELpm == le) 
 
  401     ? he->ELedge->reg[le] 
 
  402     : he->ELedge->reg[re];
 
  405 Site * VoronoiDiagramGenerator::rightreg(Halfedge *he){
 
  406   if (he->ELedge == (Edge*) NULL)
 
  413   return (he->ELpm == le)
 
  414     ? he->ELedge->reg[re] 
 
  415     : he->ELedge->reg[le];
 
  418 void VoronoiDiagramGenerator::geominit(){
 
  421   freeinit(&efl, 
sizeof(Edge));
 
  424   sn = (double)nsites+4;
 
  425   sqrt_nsites = (int)sqrt(sn);
 
  426   deltay = ymax - ymin;
 
  427   deltax = xmax - xmin;
 
  431 Edge * VoronoiDiagramGenerator::bisect(Site *s1, Site *s2){
 
  432   double dx,dy,adx,ady;
 
  435   newedge = (Edge*) getfree(&efl);
 
  437   newedge->reg[0] = s1; 
 
  438   newedge->reg[1] = s2;
 
  444   newedge->ep[0] = (Site*) NULL;
 
  445   newedge->ep[1] = (Site*) NULL;
 
  448   dx = s2->coord.x - s1->coord.x;
 
  449   dy = s2->coord.y - s1->coord.y;
 
  452   adx = dx>0 ? dx : -dx;
 
  453   ady = dy>0 ? dy : -dy;
 
  456   newedge->c = (double)(s1->coord.x * dx + s1->coord.y * dy
 
  457                         + (dx*dx + dy*dy)*0.5);
 
  461     newedge->a = 1.0; newedge->b = dy/dx; newedge->c /= dx;
 
  464     newedge->b = 1.0; newedge->a = dx/dy; newedge->c /= dy;
 
  467   newedge->edgenbr = nedges;
 
  479 Site* VoronoiDiagramGenerator::intersect(Halfedge *el1, Halfedge *el2
 
  483   double d, xint, yint;
 
  489   if ((e1==(Edge*)NULL) || (e2==(Edge*)NULL)) 
 
  490     return ((Site*) NULL);
 
  493   if (e1->reg[1] == e2->reg[1]) 
 
  511   double dx = e2->reg[1]->coord.x - e1->reg[1]->coord.x;
 
  512   double dy = e2->reg[1]->coord.y - e1->reg[1]->coord.y;
 
  513   double dxref = e1->reg[1]->coord.x - e1->reg[0]->coord.x;
 
  514   double dyref = e1->reg[1]->coord.y - e1->reg[0]->coord.y;
 
  516   if (dx*dx + dy*dy < 1e-14*(dxref*dxref+dyref*dyref)){
 
  518     double adx = dx>0 ? dx : -dx;
 
  519     double ady = dy>0 ? dy : -dy;
 
  523     double c = (double)(e1->reg[1]->coord.x * dx + e1->reg[1]->coord.y * dy
 
  524                         + (dx*dx + dy*dy)*0.5);
 
  527       a = 1.0; b = dy/dx; c /= dx;
 
  529       b = 1.0; a = dx/dy; c /= dy;
 
  532     d = e1->a * b - e1->b * a;
 
  533     if (-1.0e-10<d && d<1.0e-10) {
 
  537     xint = (e1->c*b - c*e1->b)/d;
 
  538     yint = (c*e1->a - e1->c*a)/d;
 
  541     d = e1->a * e2->b - e1->b * e2->a;
 
  542     if (-1.0e-10<d && d<1.0e-10) {
 
  546     xint = (e1->c*e2->b - e2->c*e1->b)/d;
 
  547     yint = (e2->c*e1->a - e1->c*e2->a)/d;
 
  551   volatile double local_y1 = e1->reg[1]->coord.y;
 
  552   volatile double local_y2 = e2->reg[1]->coord.y;
 
  554   if( (local_y1 < local_y2) ||
 
  555       ((local_y1 == local_y2) &&
 
  556        (e1->reg[1]->coord.x <  e2->reg[1]->coord.x)) ){ 
 
  564   right_of_site = xint >= e->reg[1]->coord.x;
 
  565   if ((right_of_site && el->ELpm == le) || (!right_of_site && el->ELpm == re)) 
 
  570   v = (Site*) getfree(&sfl);
 
  580 int VoronoiDiagramGenerator::right_of(Halfedge *el,VPoint *p)
 
  584   int right_of_site, above, fast;
 
  585   double dxp, dyp, dxs, t1, t2, t3, yl;
 
  589   right_of_site = p->x > topsite->coord.x;
 
  590   if(right_of_site && el->ELpm == le) 
return(1);
 
  591   if(!right_of_site && el->ELpm == re) 
return (0);
 
  594     {   dyp = p->y - topsite->coord.y;
 
  595     dxp = p->x - topsite->coord.x;
 
  597     if ((!right_of_site & (e->b<0.0)) | (right_of_site & (e->b>=0.0)) )
 
  598       { above = dyp>= e->b*dxp; 
 
  602       { above = p->x + p->y*e->b > e-> c;
 
  603       if(e->b<0.0) above = !above;
 
  604       if (!above) fast = 1;
 
  607       { dxs = topsite->coord.x - (e->reg[0])->coord.x;
 
  608       above = e->b * (dxp*dxp - dyp*dyp) <
 
  609         dxs*dyp*(1.0+2.0*dxp/dxs + e->b*e->b);
 
  610       if(e->b<0.0) above = !above;
 
  614     {   yl = e->c - e->a*p->x;
 
  616     t2 = p->x - topsite->coord.x;
 
  617     t3 = yl - topsite->coord.y;
 
  618     above = t1*t1 > t2*t2 + t3*t3;
 
  620   return (el->ELpm==le ? above : !above);
 
  624 void VoronoiDiagramGenerator::endpoint(Edge *e,
int lr,Site * s)
 
  628   if(e->ep[re-lr]== (Site *) NULL) 
 
  635   makefree((Freenode*)e, &efl);
 
  639 double VoronoiDiagramGenerator::dist(Site *s,Site *t)
 
  642   dx = s->coord.x - t->coord.x;
 
  643   dy = s->coord.y - t->coord.y;
 
  644   return (
double)(sqrt(dx*dx + dy*dy));
 
  648 void VoronoiDiagramGenerator::makevertex(Site *v)
 
  650   v->sitenbr = nvertices;
 
  656 void VoronoiDiagramGenerator::deref(Site *v)
 
  660     makefree((Freenode*)v, &sfl);
 
  663 void VoronoiDiagramGenerator::ref(Site *v)
 
  669 void VoronoiDiagramGenerator::PQinsert(Halfedge *he,Site * v, 
double offset)
 
  671   Halfedge *last, *next;
 
  675   he->ystar = (double)(v->coord.y + offset);
 
  676   last = &PQhash[PQbucket(he)];
 
  677   while ((next = last->PQnext) != (Halfedge *) NULL &&
 
  678          (he->ystar  > next->ystar  ||
 
  679           (he->ystar == next->ystar && v->coord.x > next->vertex->coord.x)))
 
  683   he->PQnext = last->PQnext; 
 
  689 void VoronoiDiagramGenerator::PQdelete(Halfedge *he)
 
  693   if(he->vertex != (Site *) NULL)
 
  695       last = &PQhash[PQbucket(he)];
 
  696       while (last->PQnext != he) 
 
  699       last->PQnext = he->PQnext;
 
  702       he->vertex = (Site *) NULL;
 
  706 int VoronoiDiagramGenerator::PQbucket(Halfedge *he)
 
  725   double hey = he->ystar;
 
  726   if (hey < ymin){ bucket = 0;}
 
  727   else if (hey >= ymax){ bucket = PQhashsize-1;}
 
  729     bucket = (int)((hey - ymin)/deltay * PQhashsize);
 
  730     if (bucket>=PQhashsize) bucket = PQhashsize-1 ;
 
  733   if (bucket < PQmin) PQmin = bucket;
 
  739 int VoronoiDiagramGenerator::PQempty()
 
  745 VPoint VoronoiDiagramGenerator::PQ_min()
 
  749   while(PQhash[PQmin].PQnext == (Halfedge *)NULL) {PQmin += 1;};
 
  750   answer.x = PQhash[PQmin].PQnext->vertex->coord.x;
 
  751   answer.y = PQhash[PQmin].PQnext->ystar;
 
  755 Halfedge * VoronoiDiagramGenerator::PQextractmin()
 
  759   curr = PQhash[PQmin].PQnext;
 
  760   PQhash[PQmin].PQnext = curr->PQnext;
 
  766 bool VoronoiDiagramGenerator::PQinitialize()
 
  772   PQhashsize = 4 * sqrt_nsites;
 
  774   PQhash = (Halfedge *) myalloc(PQhashsize * 
sizeof(Halfedge));
 
  779   for(i=0; i<PQhashsize; i+=1) PQhash[i].PQnext = (Halfedge *)NULL;
 
  785 void VoronoiDiagramGenerator::freeinit(Freelist *fl,
int size)
 
  787   fl->head = (Freenode *) NULL;
 
  791 char * VoronoiDiagramGenerator::getfree(Freelist *fl)
 
  796   if(fl->head == (Freenode *) NULL)
 
  798       t =  (Freenode *) myalloc(sqrt_nsites * fl->nodesize);
 
  803       currentMemoryBlock->next = 
new FreeNodeArrayList;
 
  804       currentMemoryBlock = currentMemoryBlock->next;
 
  805       currentMemoryBlock->memory = t;
 
  806       currentMemoryBlock->next = 0;
 
  808       for(i=0; i<sqrt_nsites; i+=1)     
 
  809         makefree((Freenode *)((
char *)t+i*fl->nodesize), fl);           
 
  812   fl->head = (fl->head)->nextfree;
 
  818 void VoronoiDiagramGenerator::makefree(Freenode *curr,Freelist *fl)
 
  820   curr->nextfree = fl->head;
 
  824 void VoronoiDiagramGenerator::cleanup()
 
  831   FreeNodeArrayList* current=NULL, *prev=NULL;
 
  833   current = prev = allMemoryList;
 
  835   while(current->next!=NULL){
 
  837     current = current->next;
 
  844     if (current->memory!=NULL){
 
  845       free(current->memory);
 
  850   allMemoryList = 
new FreeNodeArrayList;
 
  851   allMemoryList->next = NULL;
 
  852   allMemoryList->memory = NULL;
 
  853   currentMemoryBlock = allMemoryList;
 
  862 void VoronoiDiagramGenerator::cleanupEdges()
 
  864   GraphEdge* geCurrent = NULL, *gePrev = NULL;
 
  865   geCurrent = gePrev = allEdges;
 
  867   while(geCurrent!=NULL){
 
  869     geCurrent = geCurrent->next;
 
  877 void VoronoiDiagramGenerator::pushGraphEdge(
double x1, 
double y1, 
double x2, 
double y2,
 
  880   GraphEdge* newEdge = 
new GraphEdge;
 
  881   newEdge->next = allEdges;
 
  888   newEdge->point1 = s1->sitenbr;
 
  889   newEdge->point2 = s2->sitenbr;
 
  893 char * VoronoiDiagramGenerator::myalloc(
unsigned n)
 
  950 void VoronoiDiagramGenerator::plotinit()
 
  956   d = (double)(( dx > dy ? dx : dy) * 1.1);
 
  957   pxmin = (double)(xmin - (d-dx)/2.0);
 
  958   pxmax = (double)(xmax + (d-dx)/2.0);
 
  959   pymin = (double)(ymin - (d-dy)/2.0);
 
  960   pymax = (double)(ymax + (d-dy)/2.0);
 
  961   cradius = (double)((pxmax - pxmin)/350.0);
 
  967 void VoronoiDiagramGenerator::clip_line(Edge *e)
 
  970   double x1=0,x2=0,y1=0,y2=0; 
 
  972   x1 = e->reg[0]->coord.x;
 
  973   x2 = e->reg[1]->coord.x;
 
  974   y1 = e->reg[0]->coord.y;
 
  975   y2 = e->reg[1]->coord.y;
 
  989   if(e->a == 1.0 && e ->b >= 0.0)
 
 1003       if (s1!=(Site *)NULL && s1->coord.y > pymin)
 
 1013       x1 = e->c - e->b * y1;
 
 1015       if (s2!=(Site *)NULL && s2->coord.y < pymax) 
 
 1024       x2 = (e->c) - (e->b) * y2;
 
 1025       if (((x1> pxmax) & (x2>pxmax)) | ((x1<pxmin)&(x2<pxmin))) 
 
 1031         {       x1 = pxmax; y1 = (e->c - x1)/e->b;};
 
 1033         {       x1 = pxmin; y1 = (e->c - x1)/e->b;};
 
 1035         {       x2 = pxmax; y2 = (e->c - x2)/e->b;};
 
 1037         {       x2 = pxmin; y2 = (e->c - x2)/e->b;};
 
 1042       if (s1!=(Site *)NULL && s1->coord.x > pxmin) 
 
 1050       y1 = e->c - e->a * x1;
 
 1052       if (s2!=(Site *)NULL && s2->coord.x < pxmax) 
 
 1060       y2 = e->c - e->a * x2;
 
 1061       if (((y1> pymax) & (y2>pymax)) | ((y1<pymin)&(y2<pymin))) 
 
 1067         {       y1 = pymax; x1 = (e->c - y1)/e->a;};
 
 1069         {       y1 = pymin; x1 = (e->c - y1)/e->a;};
 
 1071         {       y2 = pymax; x2 = (e->c - y2)/e->a;};
 
 1073         {       y2 = pymin; x2 = (e->c - y2)/e->a;};
 
 1079   pushGraphEdge(x1,y1,x2,y2,e->reg[0],e->reg[1]);
 
 1088 bool VoronoiDiagramGenerator::voronoi()
 
 1090   Site *newsite, *bot, *top, *temp, *p;
 
 1094   Halfedge *lbnd, *rbnd, *llbnd, *rrbnd, *bisector;
 
 1098   bottomsite = nextone();
 
 1100   bool retval = ELinitialize();
 
 1105   newsite = nextone();
 
 1110         newintstar = PQ_min();
 
 1114       if (newsite != (Site *)NULL  && (PQempty() || newsite->coord.y < newintstar.y
 
 1115                                        || (newsite->coord.y == newintstar.y && newsite->coord.x < newintstar.x)))
 
 1118           lbnd = ELleftbnd(&(newsite->coord));                          
 
 1119           rbnd = ELright(lbnd);                                         
 
 1120           bot = rightreg(lbnd);                                         
 
 1121           e = bisect(bot, newsite);                                     
 
 1122           bisector = HEcreate(e, le);                                   
 
 1123           ELinsert(lbnd, bisector);                                     
 
 1125           if ((p = intersect(lbnd, bisector)) != (Site *) NULL)         
 
 1128               PQinsert(lbnd, p, dist(p,newsite));
 
 1131           bisector = HEcreate(e, re);                                   
 
 1132           ELinsert(lbnd, bisector);                                     
 
 1134           if ((p = intersect(bisector, rbnd)) != (Site *) NULL) 
 
 1136               PQinsert(bisector, p, dist(p,newsite));                   
 
 1138           newsite = nextone();  
 
 1140       else if (!PQempty())                       
 
 1142           lbnd = PQextractmin();                                                
 
 1143           llbnd = ELleft(lbnd);                                         
 
 1144           rbnd = ELright(lbnd);                                         
 
 1145           rrbnd = ELright(rbnd);                                                
 
 1146           bot = leftreg(lbnd);                                          
 
 1147           top = rightreg(rbnd);                                         
 
 1153           endpoint(lbnd->ELedge,lbnd->ELpm,v);  
 
 1154           endpoint(rbnd->ELedge,rbnd->ELpm,v);  
 
 1160           if (bot->coord.y > top->coord.y)              
 
 1167           e = bisect(bot, top);                                 
 
 1169           bisector = HEcreate(e, pm);                           
 
 1170           ELinsert(llbnd, bisector);                            
 
 1171           endpoint(e, re-pm, v);                                        
 
 1177           if((p = intersect(llbnd, bisector)) != (Site *) NULL)
 
 1180               PQinsert(llbnd, p, dist(p,bot));
 
 1184           if ((p = intersect(bisector, rrbnd)) != (Site *) NULL)
 
 1186               PQinsert(bisector, p, dist(p,bot));
 
 1195   for(lbnd=ELright(ELleftend); lbnd != ELrightend; lbnd=ELright(lbnd))
 
 1209 int scomp(
const void *p1,
const void *p2)
 
 1211   VPoint *s1 = (VPoint*)p1, *s2=(VPoint*)p2;
 
 1212   if(s1->y < s2->y) 
return(-1);
 
 1213   if(s1->y > s2->y) 
return(1);
 
 1214   if(s1->x < s2->x) 
return(-1);
 
 1215   if(s1->x > s2->x) 
return(1);
 
 1220 Site * VoronoiDiagramGenerator::nextone()
 
 1223   if(siteidx < nsites)
 
 1225       s = &sites[siteidx];
 
 1230     return( (Site *)NULL);
 
 1233 FASTJET_END_NAMESPACE