Created
February 25, 2016 05:33
-
-
Save wingyiu/d7ec0bfdb664d8454c0d to your computer and use it in GitHub Desktop.
voronoi sweep line algorithm implementation by author fortune
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# To unbundle, sh this file | |
echo Makefile 1>&2 | |
sed 's/.//' >Makefile <<'//GO.SYSIN DD Makefile' | |
-C=edgelist.c geometry.c heap.c main.c memory.c output.c voronoi.c | |
-O=edgelist.o geometry.o heap.o main.o memory.o output.o voronoi.o | |
- | |
-tt: voronoi t | |
- voronoi -t <t >tt | |
-voronoi: $O | |
- cc -o voronoi $O -lm | |
-$O:defs.h | |
//GO.SYSIN DD Makefile | |
echo defs.h 1>&2 | |
sed 's/.//' >defs.h <<'//GO.SYSIN DD defs.h' | |
-#ifndef NULL | |
-#define NULL 0 | |
-#endif | |
-#define DELETED -2 | |
- | |
-int triangulate, sorted, plot, debug; | |
- | |
-struct Freenode { | |
-struct Freenode *nextfree; | |
-}; | |
-struct Freelist { | |
-struct Freenode *head; | |
-int nodesize; | |
-}; | |
-char *getfree(); | |
-char *malloc(); | |
-char *myalloc(); | |
- | |
-float xmin, xmax, ymin, ymax, deltax, deltay; | |
- | |
- | |
-struct Point { | |
-float x,y; | |
-}; | |
- | |
-/* structure used both for sites and for vertices */ | |
-struct Site { | |
-struct Point coord; | |
-int sitenbr; | |
-int refcnt; | |
-}; | |
- | |
- | |
-struct Site *sites; | |
-int nsites; | |
-int siteidx; | |
-int sqrt_nsites; | |
-int nvertices; | |
-struct Freelist sfl; | |
-struct Site *bottomsite; | |
- | |
- | |
-struct Edge { | |
-float a,b,c; | |
-struct Site *ep[2]; | |
-struct Site *reg[2]; | |
-int edgenbr; | |
-}; | |
-#define le 0 | |
-#define re 1 | |
-int nedges; | |
-struct Freelist efl; | |
- | |
-int has_endpoint(),right_of(); | |
-struct Site *intersect(); | |
-float dist(); | |
-struct Point PQ_min(); | |
-struct Halfedge *PQextractmin(); | |
-struct Edge *bisect(); | |
- | |
-struct Halfedge { | |
-struct Halfedge *ELleft, *ELright; | |
-struct Edge *ELedge; | |
-int ELrefcnt; | |
-char ELpm; | |
-struct Site *vertex; | |
-float ystar; | |
-struct Halfedge *PQnext; | |
-}; | |
- | |
-struct Freelist hfl; | |
-struct Halfedge *ELleftend, *ELrightend; | |
-int ELhashsize; | |
-struct Halfedge **ELhash; | |
-struct Halfedge *HEcreate(), *ELleft(), *ELright(), *ELleftbnd(); | |
-struct Site *leftreg(), *rightreg(); | |
- | |
- | |
-int PQhashsize; | |
-struct Halfedge *PQhash; | |
-struct Halfedge *PQfind(); | |
-int PQcount; | |
-int PQmin; | |
-int PQempty(); | |
- | |
- | |
//GO.SYSIN DD defs.h | |
echo voronoi.man 1>&2 | |
sed 's/.//' >voronoi.man <<'//GO.SYSIN DD voronoi.man' | |
-.TH VORONOI 7 | |
-.SH NAME | |
-voronoi - compute Voronoi diagram or Delaunay triangulation | |
-.SH SYNOPSIS | |
-.B voronoi | |
-[ | |
-.B -s -t -p | |
-] | |
-.SH DESCRIPTION | |
-.I Voronoi | |
-reads the standard input for a set of points in the plane and writes either | |
-the Voronoi diagram or the Delaunay triangulation to the standard output. | |
-Each input line should consist of two real numbers, separated by white space. | |
-.PP | |
-If option | |
-.B -t | |
-is present, the Delaunay triangulation is produced. | |
-Each output line is a triple | |
-.I i j k, | |
-which are the indices of the three points in a Delaunay triangle. Points are | |
-numbered starting at 0. | |
-.PP | |
-If option | |
-.B -t | |
-is not present, the Voronoi diagram is produced. | |
-There are four output record types. | |
-.TP | |
-.I s a b | |
-indicates that an input point at coordinates | |
-.I a b | |
-was seen. | |
-.TP | |
-.I l a b c | |
-indicates a line with equation | |
-.I ax + by = c. | |
-.TP | |
-.I v a b | |
-indicates a vertex at | |
-.I a b. | |
-.TP | |
-.I e l v1 v2 | |
-indicates a Voronoi segment which is a subsegment of line number | |
-.I l | |
-with endpoints numbered | |
-.I v1 | |
-and | |
-.I v2. | |
-If | |
-.I v1 | |
-or | |
-.I v2 | |
-is -1, the line extends to infinity. | |
-.PP | |
-The other options are: | |
-.TP | |
-.B s | |
-The input is sorted by | |
-.I y | |
-coordinate (the second number in the pair). The first input line should be | |
-.I npoints xmin xmax ymin ymax. | |
-This describes the number of points and the range of the points. This | |
-line is used to determine internal hash table size; it need not be exact | |
-but performance suffers if it is grossly wrong. | |
-.TP | |
-.B p | |
-Produce output suitable for input to | |
-.I plot | |
-(1), rather than the forms described above. | |
-.PP | |
-On unsorted data uniformly distributed in the unit square, | |
-.I voronoi | |
-uses about | |
-.I 20n+140\(srn | |
-bytes of storage. On sorted data, | |
-.I voronoi | |
-uses about | |
-.I 160\(srn | |
-bytes. | |
-.SH AUTHOR | |
-Steve J. Fortune (1987) A Sweepline Algorithm for Voronoi Diagrams, | |
-Algorithmica 2, 153-174. | |
-.SH DIAGNOSTICS | |
-Insufficient memory. | |
-.SH BUGS | |
-The sort used by | |
-.I voronoi | |
-is much faster than | |
-.I sort | |
-(1). | |
-Also | |
-.I sort | |
-(1) does not correctly sort real data with embedded exponent fields. | |
-Very strange output results if | |
-.B -s | |
-is used on unsorted data. | |
-Binary input-output would probably halve execution time. | |
//GO.SYSIN DD voronoi.man | |
echo edgelist.c 1>&2 | |
sed 's/.//' >edgelist.c <<'//GO.SYSIN DD edgelist.c' | |
-# | |
-#include "defs.h" | |
- | |
-int ntry, totalsearch; | |
- | |
-ELinitialize() | |
-{ | |
-int i; | |
- freeinit(&hfl, sizeof **ELhash); | |
- ELhashsize = 2 * sqrt_nsites; | |
- ELhash = (struct Halfedge **) myalloc ( sizeof *ELhash * ELhashsize); | |
- for(i=0; i<ELhashsize; i +=1) ELhash[i] = (struct Halfedge *)NULL; | |
- ELleftend = HEcreate( (struct Edge *)NULL, 0); | |
- ELrightend = HEcreate( (struct Edge *)NULL, 0); | |
- ELleftend -> ELleft = (struct Halfedge *)NULL; | |
- ELleftend -> ELright = ELrightend; | |
- ELrightend -> ELleft = ELleftend; | |
- ELrightend -> ELright = (struct Halfedge *)NULL; | |
- ELhash[0] = ELleftend; | |
- ELhash[ELhashsize-1] = ELrightend; | |
-} | |
- | |
- | |
-struct Halfedge *HEcreate(e, pm) | |
-struct Edge *e; | |
-int pm; | |
-{ | |
-struct Halfedge *answer; | |
- answer = (struct Halfedge *) getfree(&hfl); | |
- answer -> ELedge = e; | |
- answer -> ELpm = pm; | |
- answer -> PQnext = (struct Halfedge *) NULL; | |
- answer -> vertex = (struct Site *) NULL; | |
- answer -> ELrefcnt = 0; | |
- return(answer); | |
-} | |
- | |
- | |
-ELinsert(lb, new) | |
-struct Halfedge *lb, *new; | |
-{ | |
- new -> ELleft = lb; | |
- new -> ELright = lb -> ELright; | |
- (lb -> ELright) -> ELleft = new; | |
- lb -> ELright = new; | |
-} | |
- | |
-/* Get entry from hash table, pruning any deleted nodes */ | |
-struct Halfedge *ELgethash(b) | |
-int b; | |
-{ | |
-struct Halfedge *he; | |
- | |
- if(b<0 || b>=ELhashsize) return((struct Halfedge *) NULL); | |
- he = ELhash[b]; | |
- if (he == (struct Halfedge *) NULL || | |
- he -> ELedge != (struct Edge *) DELETED ) return (he); | |
- | |
-/* Hash table points to deleted half edge. Patch as necessary. */ | |
- ELhash[b] = (struct Halfedge *) NULL; | |
- if ((he -> ELrefcnt -= 1) == 0) makefree(he, &hfl); | |
- return ((struct Halfedge *) NULL); | |
-} | |
- | |
-struct Halfedge *ELleftbnd(p) | |
-struct Point *p; | |
-{ | |
-int i, bucket; | |
-struct Halfedge *he; | |
- | |
-/* Use hash table to get close to desired halfedge */ | |
- bucket = (p->x - xmin)/deltax * ELhashsize; | |
- if(bucket<0) bucket =0; | |
- if(bucket>=ELhashsize) bucket = ELhashsize - 1; | |
- he = ELgethash(bucket); | |
- if(he == (struct Halfedge *) NULL) | |
- { for(i=1; 1 ; i += 1) | |
- { if ((he=ELgethash(bucket-i)) != (struct Halfedge *) NULL) break; | |
- if ((he=ELgethash(bucket+i)) != (struct Halfedge *) NULL) break; | |
- }; | |
- totalsearch += i; | |
- }; | |
- ntry += 1; | |
-/* Now search linear list of halfedges for the corect one */ | |
- if (he==ELleftend || (he != ELrightend && right_of(he,p))) | |
- {do {he = he -> ELright;} while (he!=ELrightend && right_of(he,p)); | |
- he = he -> ELleft; | |
- } | |
- else | |
- do {he = he -> ELleft;} while (he!=ELleftend && !right_of(he,p)); | |
- | |
-/* Update hash table and reference counts */ | |
- if(bucket > 0 && bucket <ELhashsize-1) | |
- { if(ELhash[bucket] != (struct Halfedge *) NULL) | |
- ELhash[bucket] -> ELrefcnt -= 1; | |
- ELhash[bucket] = he; | |
- ELhash[bucket] -> ELrefcnt += 1; | |
- }; | |
- return (he); | |
-} | |
- | |
- | |
-/* This delete routine can't reclaim node, since pointers from hash | |
- table may be present. */ | |
-ELdelete(he) | |
-struct Halfedge *he; | |
-{ | |
- (he -> ELleft) -> ELright = he -> ELright; | |
- (he -> ELright) -> ELleft = he -> ELleft; | |
- he -> ELedge = (struct Edge *)DELETED; | |
-} | |
- | |
- | |
-struct Halfedge *ELright(he) | |
-struct Halfedge *he; | |
-{ | |
- return (he -> ELright); | |
-} | |
- | |
-struct Halfedge *ELleft(he) | |
-struct Halfedge *he; | |
-{ | |
- return (he -> ELleft); | |
-} | |
- | |
- | |
-struct Site *leftreg(he) | |
-struct Halfedge *he; | |
-{ | |
- if(he -> ELedge == (struct Edge *)NULL) return(bottomsite); | |
- return( he -> ELpm == le ? | |
- he -> ELedge -> reg[le] : he -> ELedge -> reg[re]); | |
-} | |
- | |
-struct Site *rightreg(he) | |
-struct Halfedge *he; | |
-{ | |
- if(he -> ELedge == (struct Edge *)NULL) return(bottomsite); | |
- return( he -> ELpm == le ? | |
- he -> ELedge -> reg[re] : he -> ELedge -> reg[le]); | |
-} | |
- | |
- | |
//GO.SYSIN DD edgelist.c | |
echo geometry.c 1>&2 | |
sed 's/.//' >geometry.c <<'//GO.SYSIN DD geometry.c' | |
-# | |
-#include "defs.h" | |
-#include <math.h> | |
- | |
-geominit() | |
-{ | |
-struct Edge e; | |
-float sn; | |
- | |
- freeinit(&efl, sizeof e); | |
- nvertices = 0; | |
- nedges = 0; | |
- sn = nsites+4; | |
- sqrt_nsites = sqrt(sn); | |
- deltay = ymax - ymin; | |
- deltax = xmax - xmin; | |
-} | |
- | |
- | |
-struct Edge *bisect(s1,s2) | |
-struct Site *s1,*s2; | |
-{ | |
-float dx,dy,adx,ady; | |
-struct Edge *newedge; | |
- | |
- newedge = (struct Edge *) getfree(&efl); | |
- | |
- newedge -> reg[0] = s1; | |
- newedge -> reg[1] = s2; | |
- ref(s1); | |
- ref(s2); | |
- newedge -> ep[0] = (struct Site *) NULL; | |
- newedge -> ep[1] = (struct Site *) NULL; | |
- | |
- dx = s2->coord.x - s1->coord.x; | |
- dy = s2->coord.y - s1->coord.y; | |
- adx = dx>0 ? dx : -dx; | |
- ady = dy>0 ? dy : -dy; | |
- newedge -> c = s1->coord.x * dx + s1->coord.y * dy + (dx*dx + dy*dy)*0.5; | |
- if (adx>ady) | |
- { newedge -> a = 1.0; newedge -> b = dy/dx; newedge -> c /= dx;} | |
- else | |
- { newedge -> b = 1.0; newedge -> a = dx/dy; newedge -> c /= dy;}; | |
- | |
- newedge -> edgenbr = nedges; | |
- out_bisector(newedge); | |
- nedges += 1; | |
- return(newedge); | |
-} | |
- | |
- | |
-struct Site *intersect(el1, el2, p) | |
-struct Halfedge *el1, *el2; | |
-struct Point *p; | |
-{ | |
-struct Edge *e1,*e2, *e; | |
-struct Halfedge *el; | |
-float d, xint, yint; | |
-int right_of_site; | |
-struct Site *v; | |
- | |
- e1 = el1 -> ELedge; | |
- e2 = el2 -> ELedge; | |
- if(e1 == (struct Edge*)NULL || e2 == (struct Edge*)NULL) | |
- return ((struct Site *) NULL); | |
- if (e1->reg[1] == e2->reg[1]) return ((struct Site *) NULL); | |
- | |
- d = e1->a * e2->b - e1->b * e2->a; | |
- if (-1.0e-10<d && d<1.0e-10) return ((struct Site *) NULL); | |
- | |
- xint = (e1->c*e2->b - e2->c*e1->b)/d; | |
- yint = (e2->c*e1->a - e1->c*e2->a)/d; | |
- | |
- if( (e1->reg[1]->coord.y < e2->reg[1]->coord.y) || | |
- (e1->reg[1]->coord.y == e2->reg[1]->coord.y && | |
- e1->reg[1]->coord.x < e2->reg[1]->coord.x) ) | |
- { el = el1; e = e1;} | |
- else | |
- { el = el2; e = e2;}; | |
- right_of_site = xint >= e -> reg[1] -> coord.x; | |
- if ((right_of_site && el -> ELpm == le) || | |
- (!right_of_site && el -> ELpm == re)) return ((struct Site *) NULL); | |
- | |
- v = (struct Site *) getfree(&sfl); | |
- v -> refcnt = 0; | |
- v -> coord.x = xint; | |
- v -> coord.y = yint; | |
- return(v); | |
-} | |
- | |
-/* returns 1 if p is to right of halfedge e */ | |
-int right_of(el, p) | |
-struct Halfedge *el; | |
-struct Point *p; | |
-{ | |
-struct Edge *e; | |
-struct Site *topsite; | |
-int right_of_site, above, fast; | |
-float dxp, dyp, dxs, t1, t2, t3, yl; | |
- | |
-e = el -> ELedge; | |
-topsite = e -> reg[1]; | |
-right_of_site = p -> x > topsite -> coord.x; | |
-if(right_of_site && el -> ELpm == le) return(1); | |
-if(!right_of_site && el -> ELpm == re) return (0); | |
- | |
-if (e->a == 1.0) | |
-{ dyp = p->y - topsite->coord.y; | |
- dxp = p->x - topsite->coord.x; | |
- fast = 0; | |
- if ((!right_of_site &e->b<0.0) | (right_of_site&e->b>=0.0) ) | |
- { above = dyp>= e->b*dxp; | |
- fast = above; | |
- } | |
- else | |
- { above = p->x + p->y*e->b > e-> c; | |
- if(e->b<0.0) above = !above; | |
- if (!above) fast = 1; | |
- }; | |
- if (!fast) | |
- { dxs = topsite->coord.x - (e->reg[0])->coord.x; | |
- above = e->b * (dxp*dxp - dyp*dyp) < | |
- dxs*dyp*(1.0+2.0*dxp/dxs + e->b*e->b); | |
- if(e->b<0.0) above = !above; | |
- }; | |
-} | |
-else /*e->b==1.0 */ | |
-{ yl = e->c - e->a*p->x; | |
- t1 = p->y - yl; | |
- t2 = p->x - topsite->coord.x; | |
- t3 = yl - topsite->coord.y; | |
- above = t1*t1 > t2*t2 + t3*t3; | |
-}; | |
-return (el->ELpm==le ? above : !above); | |
-} | |
- | |
- | |
-endpoint(e, lr, s) | |
-struct Edge *e; | |
-int lr; | |
-struct Site *s; | |
-{ | |
-e -> ep[lr] = s; | |
-ref(s); | |
-if(e -> ep[re-lr]== (struct Site *) NULL) return; | |
-out_ep(e); | |
-deref(e->reg[le]); | |
-deref(e->reg[re]); | |
-makefree(e, &efl); | |
-} | |
- | |
- | |
-float dist(s,t) | |
-struct Site *s,*t; | |
-{ | |
-float dx,dy; | |
- dx = s->coord.x - t->coord.x; | |
- dy = s->coord.y - t->coord.y; | |
- return(sqrt(dx*dx + dy*dy)); | |
-} | |
- | |
- | |
-int makevertex(v) | |
-struct Site *v; | |
-{ | |
-v -> sitenbr = nvertices; | |
-nvertices += 1; | |
-out_vertex(v); | |
-} | |
- | |
- | |
-deref(v) | |
-struct Site *v; | |
-{ | |
-v -> refcnt -= 1; | |
-if (v -> refcnt == 0 ) makefree(v, &sfl); | |
-} | |
- | |
-ref(v) | |
-struct Site *v; | |
-{ | |
-v -> refcnt += 1; | |
-} | |
//GO.SYSIN DD geometry.c | |
echo heap.c 1>&2 | |
sed 's/.//' >heap.c <<'//GO.SYSIN DD heap.c' | |
-# | |
-#include "defs.h" | |
- | |
- | |
-PQinsert(he, v, offset) | |
-struct Halfedge *he; | |
-struct Site *v; | |
-float offset; | |
-{ | |
-struct Halfedge *last, *next; | |
- | |
-he -> vertex = v; | |
-ref(v); | |
-he -> ystar = v -> coord.y + offset; | |
-last = &PQhash[PQbucket(he)]; | |
-while ((next = last -> PQnext) != (struct Halfedge *) NULL && | |
- (he -> ystar > next -> ystar || | |
- (he -> ystar == next -> ystar && v -> coord.x > next->vertex->coord.x))) | |
- { last = next;}; | |
-he -> PQnext = last -> PQnext; | |
-last -> PQnext = he; | |
-PQcount += 1; | |
-} | |
- | |
-PQdelete(he) | |
-struct Halfedge *he; | |
-{ | |
-struct Halfedge *last; | |
- | |
-if(he -> vertex != (struct Site *) NULL) | |
-{ last = &PQhash[PQbucket(he)]; | |
- while (last -> PQnext != he) last = last -> PQnext; | |
- last -> PQnext = he -> PQnext; | |
- PQcount -= 1; | |
- deref(he -> vertex); | |
- he -> vertex = (struct Site *) NULL; | |
-}; | |
-} | |
- | |
-int PQbucket(he) | |
-struct Halfedge *he; | |
-{ | |
-int bucket; | |
- | |
-bucket = (he->ystar - ymin)/deltay * PQhashsize; | |
-if (bucket<0) bucket = 0; | |
-if (bucket>=PQhashsize) bucket = PQhashsize-1 ; | |
-if (bucket < PQmin) PQmin = bucket; | |
-return(bucket); | |
-} | |
- | |
- | |
- | |
-int PQempty() | |
-{ | |
- return(PQcount==0); | |
-} | |
- | |
- | |
-struct Point PQ_min() | |
-{ | |
-struct Point answer; | |
- | |
- while(PQhash[PQmin].PQnext == (struct Halfedge *)NULL) {PQmin += 1;}; | |
- answer.x = PQhash[PQmin].PQnext -> vertex -> coord.x; | |
- answer.y = PQhash[PQmin].PQnext -> ystar; | |
- return (answer); | |
-} | |
- | |
-struct Halfedge *PQextractmin() | |
-{ | |
-struct Halfedge *curr; | |
- | |
- curr = PQhash[PQmin].PQnext; | |
- PQhash[PQmin].PQnext = curr -> PQnext; | |
- PQcount -= 1; | |
- return(curr); | |
-} | |
- | |
- | |
-PQinitialize() | |
-{ | |
-int i; struct Point *s; | |
- | |
- PQcount = 0; | |
- PQmin = 0; | |
- PQhashsize = 4 * sqrt_nsites; | |
- PQhash = (struct Halfedge *) myalloc(PQhashsize * sizeof *PQhash); | |
- for(i=0; i<PQhashsize; i+=1) PQhash[i].PQnext = (struct Halfedge *)NULL; | |
-} | |
- | |
//GO.SYSIN DD heap.c | |
echo main.c 1>&2 | |
sed 's/.//' >main.c <<'//GO.SYSIN DD main.c' | |
-/* | |
- * The author of this software is Steven Fortune. Copyright (c) 1994 by AT&T | |
- * Bell Laboratories. | |
- * Permission to use, copy, modify, and distribute this software for any | |
- * purpose without fee is hereby granted, provided that this entire notice | |
- * is included in all copies of any software which is or includes a copy | |
- * or modification of this software and in all copies of the supporting | |
- * documentation for such software. | |
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED | |
- * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY | |
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY | |
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. | |
- */ | |
-# | |
-#include <stdio.h> | |
-#include "defs.h" | |
-struct Site *readone(); | |
-struct Site *nextone(); | |
- | |
-main(argc,argv) | |
-char **argv; | |
-int argc; | |
-{ | |
-int c; | |
-struct Site *(*next)(); | |
- | |
-sorted = 0; triangulate = 0; plot = 0; debug = 0; | |
-while((c=getopt(argc,argv,"dpst")) != EOF) | |
- switch(c) { | |
- case 'd': debug = 1; | |
- break; | |
- case 's': sorted = 1; | |
- break; | |
- case 't': triangulate = 1; | |
- break; | |
- case 'p': plot = 1; | |
- break; | |
- }; | |
- | |
-freeinit(&sfl, sizeof *sites); | |
-if(sorted) | |
-{ scanf("%d %f %f %f %f", &nsites, &xmin, &xmax, &ymin, &ymax); | |
- next = readone; | |
-} | |
-else | |
-{ readsites(); | |
- next = nextone; | |
-}; | |
- | |
-siteidx = 0; | |
-geominit(); | |
-if(plot) plotinit(); | |
- | |
-voronoi(triangulate, next); | |
- | |
-} | |
- | |
-/* sort sites on y, then x, coord */ | |
-int scomp(s1,s2) | |
-struct Point *s1,*s2; | |
-{ | |
- if(s1 -> y < s2 -> y) return(-1); | |
- if(s1 -> y > s2 -> y) return(1); | |
- if(s1 -> x < s2 -> x) return(-1); | |
- if(s1 -> x > s2 -> x) return(1); | |
- return(0); | |
-} | |
- | |
-/* return a single in-storage site */ | |
-struct Site *nextone() | |
-{ | |
-struct Site *s; | |
-if(siteidx < nsites) | |
-{ s = &sites[siteidx]; | |
- siteidx += 1; | |
- return(s); | |
-} | |
-else return( (struct Site *)NULL); | |
-} | |
- | |
- | |
-/* read all sites, sort, and compute xmin, xmax, ymin, ymax */ | |
-readsites() | |
-{ | |
-int i; | |
- | |
-nsites=0; | |
-sites = (struct Site *) myalloc(4000*sizeof *sites); | |
-while(scanf("%f %f", &sites[nsites].coord.x, &sites[nsites].coord.y)!=EOF) | |
-{ sites[nsites].sitenbr = nsites; | |
- sites[nsites].refcnt = 0; | |
- nsites += 1; | |
- if (nsites % 4000 == 0) | |
- sites = (struct Site *) realloc(sites,(nsites+4000)*sizeof*sites); | |
-}; | |
-qsort(sites, nsites, sizeof *sites, scomp); | |
-xmin=sites[0].coord.x; | |
-xmax=sites[0].coord.x; | |
-for(i=1; i<nsites; i+=1) | |
-{ if(sites[i].coord.x < xmin) xmin = sites[i].coord.x; | |
- if(sites[i].coord.x > xmax) xmax = sites[i].coord.x; | |
-}; | |
-ymin = sites[0].coord.y; | |
-ymax = sites[nsites-1].coord.y; | |
-} | |
- | |
-/* read one site */ | |
-struct Site *readone() | |
-{ | |
-struct Site *s; | |
- | |
-s = (struct Site *) getfree(&sfl); | |
-s -> refcnt = 0; | |
-s -> sitenbr = siteidx; | |
-siteidx += 1; | |
-if(scanf("%f %f", &(s->coord.x), &(s->coord.y)) == EOF) | |
- return ((struct Site *) NULL ); | |
-return(s); | |
-} | |
//GO.SYSIN DD main.c | |
echo memory.c 1>&2 | |
sed 's/.//' >memory.c <<'//GO.SYSIN DD memory.c' | |
-# | |
-#include "defs.h" | |
-#include <stdio.h> | |
- | |
-freeinit(fl, size) | |
-struct Freelist *fl; | |
-int size; | |
-{ | |
-fl -> head = (struct Freenode *) NULL; | |
-fl -> nodesize = size; | |
-} | |
- | |
-char *getfree(fl) | |
-struct Freelist *fl; | |
-{ | |
-int i; struct Freenode *t; | |
-if(fl->head == (struct Freenode *) NULL) | |
-{ t = (struct Freenode *) myalloc(sqrt_nsites * fl->nodesize); | |
- for(i=0; i<sqrt_nsites; i+=1) | |
- makefree((struct Freenode *)((char *)t+i*fl->nodesize), fl); | |
-}; | |
-t = fl -> head; | |
-fl -> head = (fl -> head) -> nextfree; | |
-return((char *)t); | |
-} | |
- | |
- | |
- | |
-makefree(curr,fl) | |
-struct Freenode *curr; | |
-struct Freelist *fl; | |
-{ | |
-curr -> nextfree = fl -> head; | |
-fl -> head = curr; | |
-} | |
- | |
-int total_alloc; | |
-char *myalloc(n) | |
-unsigned n; | |
-{ | |
-char *t; | |
-if ((t=malloc(n)) == (char *) 0) | |
-{ fprintf(stderr,"Insufficient memory processing site %d (%d bytes in use)\n", | |
- siteidx, total_alloc); | |
- exit(); | |
-}; | |
-total_alloc += n; | |
-return(t); | |
-} | |
//GO.SYSIN DD memory.c | |
echo output.c 1>&2 | |
sed 's/.//' >output.c <<'//GO.SYSIN DD output.c' | |
-# | |
-#include "defs.h" | |
-#include <stdio.h> | |
-/* for those who don't have Cherry's plot */ | |
-/* #include <plot.h> */ | |
-openpl(){} | |
-line(){} | |
-circle(){} | |
-range(){} | |
- | |
-float pxmin, pxmax, pymin, pymax, cradius; | |
- | |
-out_bisector(e) | |
-struct Edge *e; | |
-{ | |
-if(triangulate & plot &!debug) | |
- line(e->reg[0]->coord.x, e->reg[0]->coord.y, | |
- e->reg[1]->coord.x, e->reg[1]->coord.y); | |
-if(!triangulate & !plot &!debug) | |
- printf("l %f %f %f", e->a, e->b, e->c); | |
-if(debug) | |
- printf("line(%d) %gx+%gy=%g, bisecting %d %d\n", e->edgenbr, | |
- e->a, e->b, e->c, e->reg[le]->sitenbr, e->reg[re]->sitenbr); | |
-} | |
- | |
- | |
-out_ep(e) | |
-struct Edge *e; | |
-{ | |
-if(!triangulate & plot) | |
- clip_line(e); | |
-if(!triangulate & !plot) | |
-{ printf("e %d", e->edgenbr); | |
- printf(" %d ", e->ep[le] != (struct Site *)NULL ? e->ep[le]->sitenbr : -1); | |
- printf("%d\n", e->ep[re] != (struct Site *)NULL ? e->ep[re]->sitenbr : -1); | |
-}; | |
-} | |
- | |
-out_vertex(v) | |
-struct Site *v; | |
-{ | |
-if(!triangulate & !plot &!debug) | |
- printf ("v %f %f\n", v->coord.x, v->coord.y); | |
-if(debug) | |
- printf("vertex(%d) at %f %f\n", v->sitenbr, v->coord.x, v->coord.y); | |
-} | |
- | |
- | |
-out_site(s) | |
-struct Site *s; | |
-{ | |
-if(!triangulate & plot & !debug) | |
- circle (s->coord.x, s->coord.y, cradius); | |
-if(!triangulate & !plot & !debug) | |
- printf("s %f %f\n", s->coord.x, s->coord.y); | |
-if(debug) | |
- printf("site (%d) at %f %f\n", s->sitenbr, s->coord.x, s->coord.y); | |
-} | |
- | |
- | |
-out_triple(s1, s2, s3) | |
-struct Site *s1, *s2, *s3; | |
-{ | |
-if(triangulate & !plot &!debug) | |
- printf("%d %d %d\n", s1->sitenbr, s2->sitenbr, s3->sitenbr); | |
-if(debug) | |
- printf("circle through left=%d right=%d bottom=%d\n", | |
- s1->sitenbr, s2->sitenbr, s3->sitenbr); | |
-} | |
- | |
- | |
- | |
-plotinit() | |
-{ | |
-float dx,dy,d; | |
- | |
-dy = ymax - ymin; | |
-dx = xmax - xmin; | |
-d = ( dx > dy ? dx : dy) * 1.1; | |
-pxmin = xmin - (d-dx)/2.0; | |
-pxmax = xmax + (d-dx)/2.0; | |
-pymin = ymin - (d-dy)/2.0; | |
-pymax = ymax + (d-dy)/2.0; | |
-cradius = (pxmax - pxmin)/350.0; | |
-openpl(); | |
-range(pxmin, pymin, pxmax, pymax); | |
-} | |
- | |
- | |
-int clip_line(e) | |
-struct Edge *e; | |
-{ | |
-struct Site *s1, *s2; | |
-float x1,x2,y1,y2; | |
- | |
- if(e -> a == 1.0 && e ->b >= 0.0) | |
- { s1 = e -> ep[1]; | |
- s2 = e -> ep[0]; | |
- } | |
- else | |
- { s1 = e -> ep[0]; | |
- s2 = e -> ep[1]; | |
- }; | |
- | |
- if(e -> a == 1.0) | |
- { | |
- y1 = pymin; | |
- if (s1!=(struct Site *)NULL && s1->coord.y > pymin) | |
- y1 = s1->coord.y; | |
- if(y1>pymax) return; | |
- x1 = e -> c - e -> b * y1; | |
- y2 = pymax; | |
- if (s2!=(struct Site *)NULL && s2->coord.y < pymax) | |
- y2 = s2->coord.y; | |
- if(y2<pymin) return(0); | |
- x2 = e -> c - e -> b * y2; | |
- if ((x1> pxmax & x2>pxmax) | (x1<pxmin&x2<pxmin)) return; | |
- if(x1> pxmax) | |
- { x1 = pxmax; y1 = (e -> c - x1)/e -> b;}; | |
- if(x1<pxmin) | |
- { x1 = pxmin; y1 = (e -> c - x1)/e -> b;}; | |
- if(x2>pxmax) | |
- { x2 = pxmax; y2 = (e -> c - x2)/e -> b;}; | |
- if(x2<pxmin) | |
- { x2 = pxmin; y2 = (e -> c - x2)/e -> b;}; | |
- } | |
- else | |
- { | |
- x1 = pxmin; | |
- if (s1!=(struct Site *)NULL && s1->coord.x > pxmin) | |
- x1 = s1->coord.x; | |
- if(x1>pxmax) return(0); | |
- y1 = e -> c - e -> a * x1; | |
- x2 = pxmax; | |
- if (s2!=(struct Site *)NULL && s2->coord.x < pxmax) | |
- x2 = s2->coord.x; | |
- if(x2<pxmin) return(0); | |
- y2 = e -> c - e -> a * x2; | |
- if ((y1> pymax & y2>pymax) | (y1<pymin&y2<pymin)) return(0); | |
- if(y1> pymax) | |
- { y1 = pymax; x1 = (e -> c - y1)/e -> a;}; | |
- if(y1<pymin) | |
- { y1 = pymin; x1 = (e -> c - y1)/e -> a;}; | |
- if(y2>pymax) | |
- { y2 = pymax; x2 = (e -> c - y2)/e -> a;}; | |
- if(y2<pymin) | |
- { y2 = pymin; x2 = (e -> c - y2)/e -> a;}; | |
- }; | |
- | |
- line(x1,y1,x2,y2); | |
-} | |
//GO.SYSIN DD output.c | |
echo voronoi.c 1>&2 | |
sed 's/.//' >voronoi.c <<'//GO.SYSIN DD voronoi.c' | |
-# | |
-#include "defs.h" | |
- | |
- | |
-/* implicit parameters: nsites, sqrt_nsites, xmin, xmax, ymin, ymax, | |
- deltax, deltay (can all be estimates). | |
- Performance suffers if they are wrong; better to make nsites, | |
- deltax, and deltay too big than too small. (?) */ | |
- | |
-voronoi(triangulate, nextsite) | |
-int triangulate; | |
-struct Site *(*nextsite)(); | |
-{ | |
-struct Site *newsite, *bot, *top, *temp, *p; | |
-struct Site *v; | |
-struct Point newintstar; | |
-int pm; | |
-struct Halfedge *lbnd, *rbnd, *llbnd, *rrbnd, *bisector; | |
-struct Edge *e; | |
- | |
- | |
-PQinitialize(); | |
-bottomsite = (*nextsite)(); | |
-out_site(bottomsite); | |
-ELinitialize(); | |
- | |
-newsite = (*nextsite)(); | |
-while(1) | |
-{ | |
- if(!PQempty()) newintstar = PQ_min(); | |
- | |
- if (newsite != (struct Site *)NULL | |
- && (PQempty() | |
- || newsite -> coord.y < newintstar.y | |
- || (newsite->coord.y == newintstar.y | |
- && newsite->coord.x < newintstar.x))) | |
- {/* new site is smallest */ | |
- out_site(newsite); | |
- lbnd = ELleftbnd(&(newsite->coord)); | |
- rbnd = ELright(lbnd); | |
- bot = rightreg(lbnd); | |
- e = bisect(bot, newsite); | |
- bisector = HEcreate(e, le); | |
- ELinsert(lbnd, bisector); | |
- if ((p = intersect(lbnd, bisector)) != (struct Site *) NULL) | |
- { PQdelete(lbnd); | |
- PQinsert(lbnd, p, dist(p,newsite)); | |
- }; | |
- lbnd = bisector; | |
- bisector = HEcreate(e, re); | |
- ELinsert(lbnd, bisector); | |
- if ((p = intersect(bisector, rbnd)) != (struct Site *) NULL) | |
- { PQinsert(bisector, p, dist(p,newsite)); | |
- }; | |
- newsite = (*nextsite)(); | |
- } | |
- else if (!PQempty()) | |
- /* intersection is smallest */ | |
- { lbnd = PQextractmin(); | |
- llbnd = ELleft(lbnd); | |
- rbnd = ELright(lbnd); | |
- rrbnd = ELright(rbnd); | |
- bot = leftreg(lbnd); | |
- top = rightreg(rbnd); | |
- out_triple(bot, top, rightreg(lbnd)); | |
- v = lbnd->vertex; | |
- makevertex(v); | |
- endpoint(lbnd->ELedge,lbnd->ELpm,v); | |
- endpoint(rbnd->ELedge,rbnd->ELpm,v); | |
- ELdelete(lbnd); | |
- PQdelete(rbnd); | |
- ELdelete(rbnd); | |
- pm = le; | |
- if (bot->coord.y > top->coord.y) | |
- { temp = bot; bot = top; top = temp; pm = re;} | |
- e = bisect(bot, top); | |
- bisector = HEcreate(e, pm); | |
- ELinsert(llbnd, bisector); | |
- endpoint(e, re-pm, v); | |
- deref(v); | |
- if((p = intersect(llbnd, bisector)) != (struct Site *) NULL) | |
- { PQdelete(llbnd); | |
- PQinsert(llbnd, p, dist(p,bot)); | |
- }; | |
- if ((p = intersect(bisector, rrbnd)) != (struct Site *) NULL) | |
- { PQinsert(bisector, p, dist(p,bot)); | |
- }; | |
- } | |
- else break; | |
-}; | |
- | |
-for(lbnd=ELright(ELleftend); lbnd != ELrightend; lbnd=ELright(lbnd)) | |
- { e = lbnd -> ELedge; | |
- out_ep(e); | |
- }; | |
-} | |
//GO.SYSIN DD voronoi.c | |
echo t 1>&2 | |
sed 's/.//' >t <<'//GO.SYSIN DD t' | |
-0.532095 0.894141 | |
-0.189043 0.613426 | |
-0.550977 0.415724 | |
-0.00397384 0.60576 | |
-0.89423 0.666812 | |
-0.0730728 0.740658 | |
-0.64018 0.926186 | |
-0.389914 0.553149 | |
-0.046918 0.172275 | |
-0.820327 0.578957 | |
-0.166575 0.597895 | |
-0.587999 0.824301 | |
-0.184717 0.0608049 | |
-0.264707 0.661072 | |
-0.564959 0.824897 | |
-0.986991 0.654621 | |
-0.214221 0.611877 | |
-0.997171 0.807318 | |
-0.233578 0.380796 | |
-0.209772 0.585171 | |
-0.631619 0.418295 | |
-0.441601 0.474479 | |
-0.246242 0.196578 | |
-0.243191 0.428592 | |
-0.129101 0.460463 | |
-0.808454 0.240363 | |
-0.23591 0.362678 | |
-0.841259 0.0182264 | |
-0.825533 0.867529 | |
-0.780973 0.282859 | |
-0.492706 0.0717757 | |
-0.0641069 0.0241644 | |
-0.711451 0.621806 | |
-0.532239 0.872561 | |
-0.264527 0.947361 | |
-0.984485 0.373498 | |
-0.890788 0.0900603 | |
-0.81489 0.765458 | |
-0.656357 0.383494 | |
-0.161836 0.878997 | |
-0.789622 0.367808 | |
-0.00529994 0.694075 | |
-0.751558 0.0541492 | |
-0.315169 0.989785 | |
-0.0675723 0.642346 | |
-0.144209 0.130059 | |
-0.755242 0.723929 | |
-0.0258396 0.306045 | |
-0.00905612 0.544864 | |
-0.0917369 0.0311395 | |
-0.000120247 0.760615 | |
-0.599014 0.406906 | |
-0.0209242 0.0676926 | |
-0.402961 0.743223 | |
-0.536965 0.776167 | |
-0.791622 0.4288 | |
-0.0492686 0.546021 | |
-0.321031 0.883358 | |
-0.45994 0.0493888 | |
-0.306635 0.920045 | |
-0.290264 0.480864 | |
-0.117081 0.709596 | |
-0.663268 0.827229 | |
-0.25703 0.908703 | |
-0.138396 0.712536 | |
-0.37325 0.578061 | |
-0.792062 0.598336 | |
-0.761925 0.679885 | |
-0.498106 0.0823257 | |
-0.0791993 0.879007 | |
-0.389481 0.161374 | |
-0.909555 0.33623 | |
-0.78771 0.527877 | |
-0.87391 0.282804 | |
-0.914291 0.579771 | |
-0.126212 0.635836 | |
-0.962689 0.412397 | |
-0.662097 0.205412 | |
-0.514842 0.35217 | |
-0.573771 0.571652 | |
-0.541641 0.302552 | |
-0.880047 0.447681 | |
-0.854456 0.455932 | |
-0.882323 0.00625933 | |
-0.0835167 0.817145 | |
-0.868329 0.54442 | |
-0.211671 0.598359 | |
-0.169315 0.4421 | |
-0.116072 0.753312 | |
-0.900911 0.0493624 | |
-0.889781 0.970528 | |
-0.209244 0.783234 | |
-0.0556217 0.973298 | |
-0.787673 0.0775736 | |
-0.327654 0.267293 | |
-0.571657 0.956988 | |
-0.519674 0.443726 | |
-0.0206049 0.472568 | |
-0.00635056 0.409455 | |
-0.414254 0.229849 | |
//GO.SYSIN DD t |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment