2
* The author of this software is Steven Fortune. Copyright (c) 1994 by AT&T
4
* Permission to use, copy, modify, and distribute this software for any
5
* purpose without fee is hereby granted, provided that this entire notice
6
* is included in all copies of any software which is or includes a copy
7
* or modification of this software and in all copies of the supporting
8
* documentation for such software.
9
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
10
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
11
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
12
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
16
* This code was originally written by Stephan Fortune in C code. Shane O'Sullivan,
17
* have since modified it, encapsulating it in a C++ class and, fixing memory leaks and
18
* adding accessors to the Voronoi Edges.
19
* Permission to use, copy, modify, and distribute this software for any
20
* purpose without fee is hereby granted, provided that this entire notice
21
* is included in all copies of any software which is or includes a copy
22
* or modification of this software and in all copies of the supporting
23
* documentation for such software.
24
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
25
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
26
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
27
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
31
* Subsequently, Robert Kern modified it to yield Python objects.
32
* Copyright 2005 Robert Kern <robert.kern@gmail.com>
33
* See LICENSE.txt in the scipy source directory.
36
#include "VoronoiDiagramGenerator.h"
38
VoronoiDiagramGenerator::VoronoiDiagramGenerator()
43
allMemoryList = new FreeNodeArrayList;
44
allMemoryList->memory = 0;
45
allMemoryList->next = 0;
46
currentMemoryBlock = allMemoryList;
51
minDistanceBetweenSites = 0;
54
VoronoiDiagramGenerator::~VoronoiDiagramGenerator()
60
if(allMemoryList != 0)
66
bool VoronoiDiagramGenerator::generateVoronoi(double *xValues, double *yValues, int numPoints, double minX, double maxX, double minY, double maxY, double minDist)
73
minDistanceBetweenSites = minDist;
80
freeinit(&sfl, sizeof (Site));
82
sites = (struct Site *) myalloc(nsites*sizeof( *sites));
92
for(i = 0; i< nsites; i++)
94
sites[i].coord.x = xValues[i];
95
sites[i].coord.y = yValues[i];
101
else if(xValues[i] > xmax)
104
if(yValues[i] < ymin)
106
else if(yValues[i] > ymax)
109
//printf("\n%f %f\n",xValues[i],yValues[i]);
112
qsort(sites, nsites, sizeof (*sites), scomp);
136
voronoi(triangulate);
141
bool VoronoiDiagramGenerator::ELinitialize()
144
freeinit(&hfl, sizeof **ELhash);
145
ELhashsize = 2 * sqrt_nsites;
146
ELhash = (struct Halfedge **) myalloc ( sizeof *ELhash * ELhashsize);
151
for(i=0; i<ELhashsize; i +=1) ELhash[i] = (struct Halfedge *)NULL;
152
ELleftend = HEcreate( (struct Edge *)NULL, 0);
153
ELrightend = HEcreate( (struct Edge *)NULL, 0);
154
ELleftend -> ELleft = (struct Halfedge *)NULL;
155
ELleftend -> ELright = ELrightend;
156
ELrightend -> ELleft = ELleftend;
157
ELrightend -> ELright = (struct Halfedge *)NULL;
158
ELhash[0] = ELleftend;
159
ELhash[ELhashsize-1] = ELrightend;
165
struct Halfedge* VoronoiDiagramGenerator::HEcreate(struct Edge *e,int pm)
167
struct Halfedge *answer;
168
answer = (struct Halfedge *) getfree(&hfl);
169
answer -> ELedge = e;
171
answer -> PQnext = (struct Halfedge *) NULL;
172
answer -> vertex = (struct Site *) NULL;
173
answer -> ELrefcnt = 0;
178
void VoronoiDiagramGenerator::ELinsert(struct Halfedge *lb, struct Halfedge *newHe)
180
newHe -> ELleft = lb;
181
newHe -> ELright = lb -> ELright;
182
(lb -> ELright) -> ELleft = newHe;
183
lb -> ELright = newHe;
186
/* Get entry from hash table, pruning any deleted nodes */
187
struct Halfedge * VoronoiDiagramGenerator::ELgethash(int b)
191
if(b<0 || b>=ELhashsize)
192
return((struct Halfedge *) NULL);
194
if (he == (struct Halfedge *) NULL || he->ELedge != (struct Edge *) DELETED )
197
/* Hash table points to deleted half edge. Patch as necessary. */
198
ELhash[b] = (struct Halfedge *) NULL;
199
if ((he -> ELrefcnt -= 1) == 0)
200
makefree((Freenode*)he, &hfl);
201
return ((struct Halfedge *) NULL);
204
struct Halfedge * VoronoiDiagramGenerator::ELleftbnd(struct Point *p)
209
/* Use hash table to get close to desired halfedge */
210
bucket = (int)((p->x - xmin)/deltax * ELhashsize); //use the hash function to find the place in the hash map that this HalfEdge should be
212
if(bucket<0) bucket =0; //make sure that the bucket position in within the range of the hash array
213
if(bucket>=ELhashsize) bucket = ELhashsize - 1;
215
he = ELgethash(bucket);
216
if(he == (struct Halfedge *) NULL) //if the HE isn't found, search backwards and forwards in the hash map for the first non-null entry
220
if ((he=ELgethash(bucket-i)) != (struct Halfedge *) NULL)
222
if ((he=ELgethash(bucket+i)) != (struct Halfedge *) NULL)
228
/* Now search linear list of halfedges for the correct one */
229
if (he==ELleftend || (he != ELrightend && right_of(he,p)))
234
} while (he!=ELrightend && right_of(he,p)); //keep going right on the list until either the end is reached, or you find the 1st edge which the point
235
he = he -> ELleft; //isn't to the right of
237
else //if the point is to the left of the HalfEdge, then search left for the HE just to the left of the point
241
} while (he!=ELleftend && !right_of(he,p));
243
/* Update hash table and reference counts */
244
if(bucket > 0 && bucket <ELhashsize-1)
246
if(ELhash[bucket] != (struct Halfedge *) NULL)
248
ELhash[bucket] -> ELrefcnt -= 1;
251
ELhash[bucket] -> ELrefcnt += 1;
257
/* This delete routine can't reclaim node, since pointers from hash
258
table may be present. */
259
void VoronoiDiagramGenerator::ELdelete(struct Halfedge *he)
261
(he -> ELleft) -> ELright = he -> ELright;
262
(he -> ELright) -> ELleft = he -> ELleft;
263
he -> ELedge = (struct Edge *)DELETED;
267
struct Halfedge * VoronoiDiagramGenerator::ELright(struct Halfedge *he)
269
return (he -> ELright);
272
struct Halfedge * VoronoiDiagramGenerator::ELleft(struct Halfedge *he)
274
return (he -> ELleft);
278
struct Site * VoronoiDiagramGenerator::leftreg(struct Halfedge *he)
280
if(he -> ELedge == (struct Edge *)NULL)
282
return( he -> ELpm == le ?
283
he -> ELedge -> reg[le] : he -> ELedge -> reg[re]);
286
struct Site * VoronoiDiagramGenerator::rightreg(struct Halfedge *he)
288
if(he -> ELedge == (struct Edge *)NULL) //if this halfedge has no edge, return the bottom site (whatever that is)
291
//if the ELpm field is zero, return the site 0 that this edge bisects, otherwise return site number 1
292
return( he -> ELpm == le ? he -> ELedge -> reg[re] : he -> ELedge -> reg[le]);
295
void VoronoiDiagramGenerator::geominit()
299
freeinit(&efl, sizeof(Edge));
302
sn = (double)nsites+4;
303
sqrt_nsites = (int)sqrt(sn);
304
deltay = ymax - ymin;
305
deltax = xmax - xmin;
309
struct Edge * VoronoiDiagramGenerator::bisect(struct Site *s1, struct Site *s2)
311
double dx,dy,adx,ady;
312
struct Edge *newedge;
314
newedge = (struct Edge *) getfree(&efl);
316
newedge -> reg[0] = s1; //store the sites that this edge is bisecting
317
newedge -> reg[1] = s2;
320
newedge -> ep[0] = (struct Site *) NULL; //to begin with, there are no endpoints on the bisector - it goes to infinity
321
newedge -> ep[1] = (struct Site *) NULL;
323
dx = s2->coord.x - s1->coord.x; //get the difference in x dist between the sites
324
dy = s2->coord.y - s1->coord.y;
325
adx = dx>0 ? dx : -dx; //make sure that the difference in positive
326
ady = dy>0 ? dy : -dy;
327
newedge -> c = (double)(s1->coord.x * dx + s1->coord.y * dy + (dx*dx + dy*dy)*0.5);//get the slope of the line
331
newedge -> a = 1.0; newedge -> b = dy/dx; newedge -> c /= dx;//set formula of line, with x fixed to 1
335
newedge -> b = 1.0; newedge -> a = dx/dy; newedge -> c /= dy;//set formula of line, with y fixed to 1
338
newedge -> edgenbr = nedges;
340
//printf("\nbisect(%d) ((%f,%f) and (%f,%f)",nedges,s1->coord.x,s1->coord.y,s2->coord.x,s2->coord.y);
346
//create a new site where the HalfEdges el1 and el2 intersect - note that the Point in the argument list is not used, don't know why it's there
347
struct Site * VoronoiDiagramGenerator::intersect(struct Halfedge *el1, struct Halfedge *el2, struct Point *p)
349
struct Edge *e1,*e2, *e;
351
double d, xint, yint;
357
if(e1 == (struct Edge*)NULL || e2 == (struct Edge*)NULL)
358
return ((struct Site *) NULL);
360
//if the two edges bisect the same parent, return null
361
if (e1->reg[1] == e2->reg[1])
362
return ((struct Site *) NULL);
364
d = e1->a * e2->b - e1->b * e2->a;
365
if (-1.0e-10<d && d<1.0e-10)
366
return ((struct Site *) NULL);
368
xint = (e1->c*e2->b - e2->c*e1->b)/d;
369
yint = (e2->c*e1->a - e1->c*e2->a)/d;
371
if( (e1->reg[1]->coord.y < e2->reg[1]->coord.y) ||
372
(e1->reg[1]->coord.y == e2->reg[1]->coord.y &&
373
e1->reg[1]->coord.x < e2->reg[1]->coord.x) )
384
right_of_site = xint >= e -> reg[1] -> coord.x;
385
if ((right_of_site && el -> ELpm == le) || (!right_of_site && el -> ELpm == re))
386
return ((struct Site *) NULL);
388
//create a new site at the point of intersection - this is a new vector event waiting to happen
389
v = (struct Site *) getfree(&sfl);
396
/* returns 1 if p is to right of halfedge e */
397
int VoronoiDiagramGenerator::right_of(struct Halfedge *el,struct Point *p)
400
struct Site *topsite;
401
int right_of_site, above, fast;
402
double dxp, dyp, dxs, t1, t2, t3, yl;
405
topsite = e -> reg[1];
406
right_of_site = p -> x > topsite -> coord.x;
407
if(right_of_site && el -> ELpm == le) return(1);
408
if(!right_of_site && el -> ELpm == re) return (0);
411
{ dyp = p->y - topsite->coord.y;
412
dxp = p->x - topsite->coord.x;
414
if ((!right_of_site & (e->b<0.0)) | (right_of_site & (e->b>=0.0)) )
415
{ above = dyp>= e->b*dxp;
419
{ above = p->x + p->y*e->b > e-> c;
420
if(e->b<0.0) above = !above;
421
if (!above) fast = 1;
424
{ dxs = topsite->coord.x - (e->reg[0])->coord.x;
425
above = e->b * (dxp*dxp - dyp*dyp) <
426
dxs*dyp*(1.0+2.0*dxp/dxs + e->b*e->b);
427
if(e->b<0.0) above = !above;
431
{ yl = e->c - e->a*p->x;
433
t2 = p->x - topsite->coord.x;
434
t3 = yl - topsite->coord.y;
435
above = t1*t1 > t2*t2 + t3*t3;
437
return (el->ELpm==le ? above : !above);
441
void VoronoiDiagramGenerator::endpoint(struct Edge *e,int lr,struct Site * s)
445
if(e -> ep[re-lr]== (struct Site *) NULL)
452
makefree((Freenode*)e, &efl);
456
double VoronoiDiagramGenerator::dist(struct Site *s,struct Site *t)
459
dx = s->coord.x - t->coord.x;
460
dy = s->coord.y - t->coord.y;
461
return (double)(sqrt(dx*dx + dy*dy));
465
void VoronoiDiagramGenerator::makevertex(struct Site *v)
467
v -> sitenbr = nvertices;
473
void VoronoiDiagramGenerator::deref(struct Site *v)
476
if (v -> refcnt == 0 )
477
makefree((Freenode*)v, &sfl);
480
void VoronoiDiagramGenerator::ref(struct Site *v)
485
//push the HalfEdge into the ordered linked list of vertices
486
void VoronoiDiagramGenerator::PQinsert(struct Halfedge *he,struct Site * v, double offset)
488
struct Halfedge *last, *next;
492
he -> ystar = (double)(v -> coord.y + offset);
493
last = &PQhash[PQbucket(he)];
494
while ((next = last -> PQnext) != (struct Halfedge *) NULL &&
495
(he -> ystar > next -> ystar ||
496
(he -> ystar == next -> ystar && v -> coord.x > next->vertex->coord.x)))
500
he -> PQnext = last -> PQnext;
505
//remove the HalfEdge from the list of vertices
506
void VoronoiDiagramGenerator::PQdelete(struct Halfedge *he)
508
struct Halfedge *last;
510
if(he -> vertex != (struct Site *) NULL)
512
last = &PQhash[PQbucket(he)];
513
while (last -> PQnext != he)
514
last = last -> PQnext;
516
last -> PQnext = he -> PQnext;
519
he -> vertex = (struct Site *) NULL;
523
int VoronoiDiagramGenerator::PQbucket(struct Halfedge *he)
527
bucket = (int)((he->ystar - ymin)/deltay * PQhashsize);
528
if (bucket<0) bucket = 0;
529
if (bucket>=PQhashsize) bucket = PQhashsize-1 ;
530
if (bucket < PQmin) PQmin = bucket;
536
int VoronoiDiagramGenerator::PQempty()
542
struct Point VoronoiDiagramGenerator::PQ_min()
546
while(PQhash[PQmin].PQnext == (struct Halfedge *)NULL) {PQmin += 1;};
547
answer.x = PQhash[PQmin].PQnext -> vertex -> coord.x;
548
answer.y = PQhash[PQmin].PQnext -> ystar;
552
struct Halfedge * VoronoiDiagramGenerator::PQextractmin()
554
struct Halfedge *curr;
556
curr = PQhash[PQmin].PQnext;
557
PQhash[PQmin].PQnext = curr -> PQnext;
563
bool VoronoiDiagramGenerator::PQinitialize()
569
PQhashsize = 4 * sqrt_nsites;
570
PQhash = (struct Halfedge *) myalloc(PQhashsize * sizeof *PQhash);
575
for(i=0; i<PQhashsize; i+=1) PQhash[i].PQnext = (struct Halfedge *)NULL;
581
void VoronoiDiagramGenerator::freeinit(struct Freelist *fl,int size)
583
fl -> head = (struct Freenode *) NULL;
584
fl -> nodesize = size;
587
char * VoronoiDiagramGenerator::getfree(struct Freelist *fl)
592
if(fl->head == (struct Freenode *) NULL)
594
t = (struct Freenode *) myalloc(sqrt_nsites * fl->nodesize);
599
currentMemoryBlock->next = new FreeNodeArrayList;
600
currentMemoryBlock = currentMemoryBlock->next;
601
currentMemoryBlock->memory = t;
602
currentMemoryBlock->next = 0;
604
for(i=0; i<sqrt_nsites; i+=1)
605
makefree((struct Freenode *)((char *)t+i*fl->nodesize), fl);
608
fl -> head = (fl -> head) -> nextfree;
614
void VoronoiDiagramGenerator::makefree(struct Freenode *curr,struct Freelist *fl)
616
curr -> nextfree = fl -> head;
620
void VoronoiDiagramGenerator::cleanup()
628
FreeNodeArrayList* current=0, *prev = 0;
630
current = prev = allMemoryList;
632
while(current->next != 0)
635
current = current->next;
641
if(current != 0 && current->memory != 0)
643
free(current->memory);
647
allMemoryList = new FreeNodeArrayList;
648
allMemoryList->next = 0;
649
allMemoryList->memory = 0;
650
currentMemoryBlock = allMemoryList;
653
void VoronoiDiagramGenerator::cleanupEdges()
655
GraphEdge* geCurrent = 0, *gePrev = 0;
656
geCurrent = gePrev = allEdges;
658
while(geCurrent != 0 && geCurrent->next != 0)
661
geCurrent = geCurrent->next;
669
void VoronoiDiagramGenerator::cleanupEdgeList()
671
EdgeList* elCurrent = 0, *elPrev = 0;
672
elCurrent = elPrev = allEdgeList;
674
while (elCurrent != 0 && elCurrent->next != 0)
677
elCurrent = elCurrent->next;
684
void VoronoiDiagramGenerator::pushGraphEdge(double x1, double y1, double x2, double y2)
686
GraphEdge* newEdge = new GraphEdge;
687
newEdge->next = allEdges;
695
void VoronoiDiagramGenerator::pushEdgeList(Edge *e)
697
EdgeList* newEdge = new EdgeList;
698
newEdge->next = allEdgeList;
699
allEdgeList = newEdge;
704
newEdge->ep0nbr = e->ep[0]->sitenbr;
705
newEdge->ep0x = e->ep[0]->coord.x;
706
newEdge->ep0y = e->ep[0]->coord.y;
708
newEdge->ep0nbr = -1;
711
newEdge->ep1nbr = e->ep[1]->sitenbr;
712
newEdge->ep1x = e->ep[1]->coord.x;
713
newEdge->ep1y = e->ep[1]->coord.y;
715
newEdge->ep1nbr = -1;
717
newEdge->reg0nbr = e->reg[0]->sitenbr;
718
newEdge->reg1nbr = e->reg[1]->sitenbr;
719
newEdge->edgenbr = e->edgenbr;
722
char * VoronoiDiagramGenerator::myalloc(unsigned n)
731
/* for those who don't have Cherry's plot */
732
/* #include <plot.h> */
733
void VoronoiDiagramGenerator::openpl(){}
734
void VoronoiDiagramGenerator::line(double x1, double y1, double x2, double y2)
736
pushGraphEdge(x1,y1,x2,y2);
739
void VoronoiDiagramGenerator::circle(double x, double y, double radius){}
740
void VoronoiDiagramGenerator::range(double minX, double minY, double maxX, double maxY){}
744
void VoronoiDiagramGenerator::out_bisector(struct Edge *e)
751
void VoronoiDiagramGenerator::out_ep(struct Edge *e)
757
void VoronoiDiagramGenerator::out_vertex(struct Site *v)
763
void VoronoiDiagramGenerator::out_site(struct Site *s)
765
if(!triangulate & plot & !debug)
766
circle (s->coord.x, s->coord.y, cradius);
771
void VoronoiDiagramGenerator::out_triple(struct Site *s1, struct Site *s2,struct Site * s3)
778
void VoronoiDiagramGenerator::plotinit()
784
// d = (double)(( dx > dy ? dx : dy) * 1.1);
785
// pxmin = (double)(xmin - (d-dx)/2.0);
786
// pxmax = (double)(xmax + (d-dx)/2.0);
787
// pymin = (double)(ymin - (d-dy)/2.0);
788
// pymax = (double)(ymax + (d-dy)/2.0);
789
// cradius = (double)((pxmax - pxmin)/350.0);
791
// range(pxmin, pymin, pxmax, pymax);
795
void VoronoiDiagramGenerator::clip_line(struct Edge *e)
797
// struct Site *s1, *s2;
798
// double x1=0,x2=0,y1=0,y2=0;
802
// x1 = e->reg[0]->coord.x;
803
// x2 = e->reg[1]->coord.x;
804
// y1 = e->reg[0]->coord.y;
805
// y2 = e->reg[1]->coord.y;
807
// //if the distance between the two points this line was created from is less than
808
// //the square root of 2, then ignore it
809
// if(sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))) < minDistanceBetweenSites)
813
// pxmin = borderMinX;
814
// pxmax = borderMaxX;
815
// pymin = borderMinY;
816
// pymax = borderMaxY;
818
// if(e -> a == 1.0 && e ->b >= 0.0)
832
// if (s1!=(struct Site *)NULL && s1->coord.y > pymin)
838
// // printf("\nClipped (1) y1 = %f to %f",y1,pymax);
842
// x1 = e -> c - e -> b * y1;
844
// if (s2!=(struct Site *)NULL && s2->coord.y < pymax)
849
// //printf("\nClipped (2) y2 = %f to %f",y2,pymin);
853
// x2 = (e->c) - (e->b) * y2;
854
// if (((x1> pxmax) & (x2>pxmax)) | ((x1<pxmin)&(x2<pxmin)))
856
// //printf("\nClipLine jumping out(3), x1 = %f, pxmin = %f, pxmax = %f",x1,pxmin,pxmax);
860
// { x1 = pxmax; y1 = (e -> c - x1)/e -> b;};
862
// { x1 = pxmin; y1 = (e -> c - x1)/e -> b;};
864
// { x2 = pxmax; y2 = (e -> c - x2)/e -> b;};
866
// { x2 = pxmin; y2 = (e -> c - x2)/e -> b;};
871
// if (s1!=(struct Site *)NULL && s1->coord.x > pxmin)
875
// //printf("\nClipped (3) x1 = %f to %f",x1,pxmin);
879
// y1 = e -> c - e -> a * x1;
881
// if (s2!=(struct Site *)NULL && s2->coord.x < pxmax)
885
// //printf("\nClipped (4) x2 = %f to %f",x2,pxmin);
889
// y2 = e -> c - e -> a * x2;
890
// if (((y1> pymax) & (y2>pymax)) | ((y1<pymin)&(y2<pymin)))
892
// //printf("\nClipLine jumping out(6), y1 = %f, pymin = %f, pymax = %f",y2,pymin,pymax);
896
// { y1 = pymax; x1 = (e -> c - y1)/e -> a;};
898
// { y1 = pymin; x1 = (e -> c - y1)/e -> a;};
900
// { y2 = pymax; x2 = (e -> c - y2)/e -> a;};
902
// { y2 = pymin; x2 = (e -> c - y2)/e -> a;};
905
// //printf("\nPushing line (%f,%f,%f,%f)",x1,y1,x2,y2);
906
// line(x1,y1,x2,y2);
910
/* implicit parameters: nsites, sqrt_nsites, xmin, xmax, ymin, ymax,
911
deltax, deltay (can all be estimates).
912
Performance suffers if they are wrong; better to make nsites,
913
deltax, and deltay too big than too small. (?) */
915
bool VoronoiDiagramGenerator::voronoi(int triangulate)
917
struct Site *newsite, *bot, *top, *temp, *p;
919
struct Point newintstar;
921
struct Halfedge *lbnd, *rbnd, *llbnd, *rrbnd, *bisector;
925
bottomsite = nextone();
926
out_site(bottomsite);
927
bool retval = ELinitialize();
937
newintstar = PQ_min();
939
//if the lowest site has a smaller y value than the lowest vector intersection, process the site
940
//otherwise process the vector intersection
942
if (newsite != (struct Site *)NULL && (PQempty() || newsite -> coord.y < newintstar.y
943
|| (newsite->coord.y == newintstar.y && newsite->coord.x < newintstar.x)))
944
{/* new site is smallest - this is a site event*/
945
out_site(newsite); //output the site
946
lbnd = ELleftbnd(&(newsite->coord)); //get the first HalfEdge to the LEFT of the new site
947
rbnd = ELright(lbnd); //get the first HalfEdge to the RIGHT of the new site
948
bot = rightreg(lbnd); //if this halfedge has no edge, , bot = bottom site (whatever that is)
949
e = bisect(bot, newsite); //create a new edge that bisects
950
bisector = HEcreate(e, le); //create a new HalfEdge, setting its ELpm field to 0
951
ELinsert(lbnd, bisector); //insert this new bisector edge between the left and right vectors in a linked list
953
if ((p = intersect(lbnd, bisector)) != (struct Site *) NULL) //if the new bisector intersects with the left edge, remove the left edge's vertex, and put in the new one
956
PQinsert(lbnd, p, dist(p,newsite));
959
bisector = HEcreate(e, re); //create a new HalfEdge, setting its ELpm field to 1
960
ELinsert(lbnd, bisector); //insert the new HE to the right of the original bisector earlier in the IF stmt
962
if ((p = intersect(bisector, rbnd)) != (struct Site *) NULL) //if this new bisector intersects with the
964
PQinsert(bisector, p, dist(p,newsite)); //push the HE into the ordered linked list of vertices
968
else if (!PQempty()) /* intersection is smallest - this is a vector event */
970
lbnd = PQextractmin(); //pop the HalfEdge with the lowest vector off the ordered list of vectors
971
llbnd = ELleft(lbnd); //get the HalfEdge to the left of the above HE
972
rbnd = ELright(lbnd); //get the HalfEdge to the right of the above HE
973
rrbnd = ELright(rbnd); //get the HalfEdge to the right of the HE to the right of the lowest HE
974
bot = leftreg(lbnd); //get the Site to the left of the left HE which it bisects
975
top = rightreg(rbnd); //get the Site to the right of the right HE which it bisects
977
out_triple(bot, top, rightreg(lbnd)); //output the triple of sites, stating that a circle goes through them
979
v = lbnd->vertex; //get the vertex that caused this event
980
makevertex(v); //set the vertex number - couldn't do this earlier since we didn't know when it would be processed
981
endpoint(lbnd->ELedge,lbnd->ELpm,v); //set the endpoint of the left HalfEdge to be this vector
982
endpoint(rbnd->ELedge,rbnd->ELpm,v); //set the endpoint of the right HalfEdge to be this vector
983
ELdelete(lbnd); //mark the lowest HE for deletion - can't delete yet because there might be pointers to it in Hash Map
984
PQdelete(rbnd); //remove all vertex events to do with the right HE
985
ELdelete(rbnd); //mark the right HE for deletion - can't delete yet because there might be pointers to it in Hash Map
986
pm = le; //set the pm variable to zero
988
if (bot->coord.y > top->coord.y) //if the site to the left of the event is higher than the Site
989
{ //to the right of it, then swap them and set the 'pm' variable to 1
995
e = bisect(bot, top); //create an Edge (or line) that is between the two Sites. This creates
996
//the formula of the line, and assigns a line number to it
997
bisector = HEcreate(e, pm); //create a HE from the Edge 'e', and make it point to that edge with its ELedge field
998
ELinsert(llbnd, bisector); //insert the new bisector to the right of the left HE
999
endpoint(e, re-pm, v); //set one endpoint to the new edge to be the vector point 'v'.
1000
//If the site to the left of this bisector is higher than the right
1001
//Site, then this endpoint is put in position 0; otherwise in pos 1
1002
deref(v); //delete the vector 'v'
1004
//if left HE and the new bisector don't intersect, then delete the left HE, and reinsert it
1005
if((p = intersect(llbnd, bisector)) != (struct Site *) NULL)
1008
PQinsert(llbnd, p, dist(p,bot));
1011
//if right HE and the new bisector don't intersect, then reinsert it
1012
if ((p = intersect(bisector, rrbnd)) != (struct Site *) NULL)
1014
PQinsert(bisector, p, dist(p,bot));
1023
for(lbnd=ELright(ELleftend); lbnd != ELrightend; lbnd=ELright(lbnd))
1038
int scomp(const void *p1,const void *p2)
1040
struct Point *s1 = (Point*)p1, *s2=(Point*)p2;
1041
if(s1 -> y < s2 -> y) return(-1);
1042
if(s1 -> y > s2 -> y) return(1);
1043
if(s1 -> x < s2 -> x) return(-1);
1044
if(s1 -> x > s2 -> x) return(1);
1048
/* return a single in-storage site */
1049
struct Site * VoronoiDiagramGenerator::nextone()
1052
if(siteidx < nsites)
1054
s = &sites[siteidx];
1059
return( (struct Site *)NULL);
1062
bool VoronoiDiagramGenerator::getNextDelaunay(int& ep0, double& ep0x, double& ep0y,
1063
int& ep1, double& ep1x, double& ep1y,
1064
int& reg0, int& reg1)
1066
if (iterEdgeList == 0)
1069
ep0 = iterEdgeList->ep0nbr;
1070
ep0x = iterEdgeList->ep0x;
1071
ep0y = iterEdgeList->ep0y;
1072
ep1 = iterEdgeList->ep1nbr;
1073
ep1x = iterEdgeList->ep1x;
1074
ep1y = iterEdgeList->ep1y;
1075
reg0 = iterEdgeList->reg0nbr;
1076
reg1 = iterEdgeList->reg1nbr;
1078
iterEdgeList = iterEdgeList->next;
1083
//PyObject* VoronoiDiagramGenerator::_getMesh()
1085
// PyObject *vlist, *dlist, *tlist;
1086
// PyObject *temp, *faces, *face;
1087
// int tri0, tri1, reg0, reg1;
1088
// double tri0x, tri0y, tri1x, tri1y;
1089
// int length, numtri, i;
1092
// numtri = nvertices;
1094
// dlist = PyList_New(length);
1095
// if (!dlist) goto fail;
1096
// vlist = PyList_New(numtri);
1097
// if (!vlist) goto fail;
1098
// tlist = PyList_New(numtri);
1099
// if (!tlist) goto fail;
1101
// for (i=0; i<numtri; i++) {
1102
// faces = PyList_New(0);
1103
// if (!faces) goto fail;
1104
// PyList_SET_ITEM(tlist, i, faces);
1107
// resetEdgeListIter();
1109
// while (getNextDelaunay(tri0, tri0x, tri0y, tri1, tri1x, tri1y, reg0, reg1)) {
1111
// face = Py_BuildValue("(ii)", reg0, reg1);
1112
// if (!face) goto fail;
1113
// PyList_SET_ITEM(dlist, i, face);
1115
// temp = PyList_GET_ITEM(vlist, tri0);
1117
// temp = Py_BuildValue("(dd)", tri0x, tri0y);
1118
// PyList_SET_ITEM(vlist, tri0, temp);
1120
// faces = PyList_GET_ITEM(tlist, tri0);
1121
// if (PyList_Append(faces, face) < 0) goto fail;
1124
// temp = PyList_GET_ITEM(vlist, tri1);
1126
// temp = Py_BuildValue("(dd)", tri1x, tri1y);
1127
// PyList_SET_ITEM(vlist, tri1, temp);
1129
// faces = PyList_GET_ITEM(tlist, tri1);
1130
// if (PyList_Append(faces, face) < 0) goto fail;
1134
// temp = PyTuple_Pack(3, vlist, dlist, tlist);
1135
// if (!temp) goto fail;
1137
// Py_DECREF(vlist);
1138
// Py_DECREF(dlist);
1139
// Py_DECREF(tlist);
1144
// Py_XDECREF(vlist);
1145
// Py_XDECREF(dlist);
1146
// Py_XDECREF(temp);
1147
// Py_XDECREF(faces);
1148
// Py_XDECREF(face);