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