/* * 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 "vdefs.h" #include #ifndef lint static char RCSid[] = "$Id: vgeometry.c,v 1.2 2003/07/24 15:44:06 pturner Exp $"; #endif /* vgeometry.c */ void geominit(void); struct Edge *bisect(struct Site *s1, struct Site *s2); struct Site *intersect(struct Halfedge *el1, struct Halfedge *el2, struct Point *p); int right_of(struct Halfedge *el, struct Point *p); void endpoint(struct Edge *e, int lr, struct Site *s); double dist(struct Site *s, struct Site *t); void makevertex(struct Site *v); void deref(struct Site *v); void ref(struct Site *v); void geominit(void) { struct Edge e; double sn; freeinit(&efl, sizeof e); nvertices = 0; nedges = 0; sn = nsites + 4; sqrt_nsites = sqrt(sn); deltay = vymax - vymin; deltax = vxmax - vxmin; } struct Edge *bisect(struct Site * s1, struct Site * s2) { double 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(struct Halfedge * el1, struct Halfedge * el2, struct Point * p) { struct Edge *e1, *e2, *e; struct Halfedge *el; double 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(struct Halfedge * el, struct Point * p) { struct Edge *e; struct 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); } void endpoint(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); } double dist(struct Site * s, struct Site * t) { double dx, dy; dx = s->coord.x - t->coord.x; dy = s->coord.y - t->coord.y; return (sqrt(dx * dx + dy * dy)); } void makevertex(struct Site * v) { v->sitenbr = nvertices; nvertices += 1; out_vertex(v); } void deref(struct Site * v) { v->refcnt -= 1; if (v->refcnt == 0) makefree(v, &sfl); } void ref(struct Site * v) { v->refcnt += 1; }