/* This software may only be used by you under license from AT&T Corp. ("AT&T"). A copy of AT&T's Source Code Agreement is available at AT&T's Internet website having the URL: If you received this software without first entering into a license with AT&T, you have an infringing copy of this software and cannot use it without violating AT&T's intellectual property rights. */ #pragma prototyped #include "mem.h" #include "hedges.h" #include "render.h" #define DELETED -2 Halfedge *ELleftend, *ELrightend; static Freelist hfl; static int ELhashsize; static Halfedge **ELhash; static int ntry, totalsearch; void ELcleanup() { freeinit(&hfl, sizeof **ELhash); free (ELhash); ELhash = NULL; } void ELinitialize() { int i; freeinit(&hfl, sizeof **ELhash); ELhashsize = 2 * sqrt_nsites; if (ELhash == NULL) ELhash = N_GNEW (ELhashsize, Halfedge *); for(i=0; i ELleft = (Halfedge *)NULL; ELleftend -> ELright = ELrightend; ELrightend -> ELleft = ELleftend; ELrightend -> ELright = (Halfedge *)NULL; ELhash[0] = ELleftend; ELhash[ELhashsize-1] = ELrightend; } Site * hintersect(Halfedge *el1, Halfedge *el2) { Edge *e1,*e2, *e; Halfedge *el; double d, xint, yint; int right_of_site; Site *v; e1 = el1 -> ELedge; e2 = el2 -> ELedge; if(e1 == (Edge*)NULL || e2 == (Edge*)NULL) return ((Site *) NULL); if (e1->reg[1] == e2->reg[1]) return ((Site *) NULL); d = e1->a * e2->b - e1->b * e2->a; if (-1.0e-10c*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 ((Site *) NULL); v = getsite (); 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(Halfedge *el, Point *p) { Edge *e; Site *topsite; int right_of_site, above, fast; double 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); } Halfedge * HEcreate(Edge *e, char pm) { Halfedge *answer; answer = (Halfedge *) getfree(&hfl); answer -> ELedge = e; answer -> ELpm = pm; answer -> PQnext = (Halfedge *) NULL; answer -> vertex = (Site *) NULL; answer -> ELrefcnt = 0; return(answer); } void ELinsert(Halfedge *lb, Halfedge *new) { new -> ELleft = lb; new -> ELright = lb -> ELright; (lb -> ELright) -> ELleft = new; lb -> ELright = new; } /* Get entry from hash table, pruning any deleted nodes */ static Halfedge * ELgethash(int b) { Halfedge *he; if(b<0 || b>=ELhashsize) return((Halfedge *) NULL); he = ELhash[b]; if (he == (Halfedge *) NULL || he -> ELedge != (Edge *) DELETED ) return (he); /* Hash table points to deleted half edge. Patch as necessary. */ ELhash[b] = (Halfedge *) NULL; if ((he -> ELrefcnt -= 1) == 0) makefree(he, &hfl); return ((Halfedge *) NULL); } Halfedge * ELleftbnd(Point *p) { int i, bucket; 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 == (Halfedge *) NULL) { for(i=1; 1 ; i += 1) { if ((he=ELgethash(bucket-i)) != (Halfedge *) NULL) break; if ((he=ELgethash(bucket+i)) != (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 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. */ void ELdelete(Halfedge *he) { (he -> ELleft) -> ELright = he -> ELright; (he -> ELright) -> ELleft = he -> ELleft; he -> ELedge = (Edge *)DELETED; } Halfedge * ELright(Halfedge *he) { return (he -> ELright); } Halfedge * ELleft(Halfedge *he) { return (he -> ELleft); } Site * leftreg(Halfedge *he) { if(he -> ELedge == (Edge *)NULL) return(bottomsite); return( he -> ELpm == le ? he -> ELedge -> reg[le] : he -> ELedge -> reg[re]); } Site * rightreg(Halfedge *he) { if(he -> ELedge == (Edge *)NULL) return(bottomsite); return( he -> ELpm == le ? he -> ELedge -> reg[re] : he -> ELedge -> reg[le]); }