From: Emden Gansner Date: Wed, 15 Aug 2012 21:10:57 +0000 (-0400) Subject: Provide optional non-recursive partitioning function X-Git-Tag: LAST_LIBGRAPH~32^2~345^2^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f20234854a02446b8d0a53e65b4e2d55e5baa8e7;p=graphviz Provide optional non-recursive partitioning function --- diff --git a/lib/ortho/partition.c b/lib/ortho/partition.c index 1bb668690..c0814ec70 100644 --- a/lib/ortho/partition.c +++ b/lib/ortho/partition.c @@ -316,6 +316,7 @@ make_new_monotone_poly (int mcur, int v0, int v1) return mnew; } +#ifndef NO_RECURSE /* recursively visit all the trapezoids */ static int traverse_polygon (int* visited, boxf* decomp, int size, segment_t* seg, trap_t* tr, @@ -612,6 +613,342 @@ traverse_polygon (int* visited, boxf* decomp, int size, segment_t* seg, trap_t* return size; } +#else +typedef struct { + int mcur, trnum, from, dir; +} frame_t; + +typedef struct { + frame_t* data; + int top, size; +} stk_t; + +static stk_t* +stkOpen () +{ + stk_t* sp = NEW(stk_t); + sp->size=1024; + sp->data=N_NEW(sp->size,frame_t); + sp->top=0; + return sp; +} + +static void +stkGrow (stk_t* sp) +{ + sp->size *= 2; + sp->data = RALLOC(sp->size,sp->data,frame_t); +} + +static void +stkClose (stk_t* sp) +{ + free (sp->data); + free (sp); +} + +#define stkSize(s) (s->top) +#define stkPush(s,m,t,f,d) {if(s->top==s->size)stkGrow(s); \ + fp=s->data+s->top; \ + fp->mcur=m; \ + fp->trnum=t; \ + fp->from=f; \ + fp->dir=d; \ + s->top++;} + +#define stkPop(s,m,t,f,d) {s->top--; \ + fp=s->data+s->top; \ + m=fp->mcur; \ + t=fp->trnum; \ + f=fp->from; \ + d=fp->dir; } + +static int +traverse_polygon (int* visited, boxf* decomp, int size, segment_t* seg, trap_t* tr, + int mcur0, int trnum0, int from0, int flip, int dir0) +{ + trap_t *t; + int mnew; + int v0, v1; + stk_t* stk = stkOpen(); + int mcur, trnum, from, dir; + frame_t* fp; + + stkPush (stk, mcur0, trnum0, from0, dir0); + + while (stkSize(stk)) { + stkPop(stk, mcur, trnum, from, dir); + t = &tr[trnum]; + + if ((trnum <= 0) || visited[trnum]) + continue; + + visited[trnum] = TRUE; + + if ((t->hi.y > t->lo.y) && + (seg[t->lseg].v0.x == seg[t->lseg].v1.x) && + (seg[t->rseg].v0.x == seg[t->rseg].v1.x)) { + if (flip) { + decomp[size].LL.x = t->lo.y; + decomp[size].LL.y = -seg[t->rseg].v0.x; + decomp[size].UR.x = t->hi.y; + decomp[size].UR.y = -seg[t->lseg].v0.x; + } else { + decomp[size].LL.x = seg[t->lseg].v0.x; + decomp[size].LL.y = t->lo.y; + decomp[size].UR.x = seg[t->rseg].v0.x; + decomp[size].UR.y = t->hi.y; + } + size++; + } + + /* We have much more information available here. */ + /* rseg: goes upwards */ + /* lseg: goes downwards */ + + /* Initially assume that dir = TR_FROM_DN (from the left) */ + /* Switch v0 and v1 if necessary afterwards */ + + + /* special cases for triangles with cusps at the opposite ends. */ + /* take care of this first */ + if ((t->u0 <= 0) && (t->u1 <= 0)) + { + if ((t->d0 > 0) && (t->d1 > 0)) /* downward opening triangle */ + { + v0 = tr[t->d1].lseg; + v1 = t->lseg; + if (from == t->d1) + { + mnew = make_new_monotone_poly(mcur, v1, v0); + stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP); + } + else + { + mnew = make_new_monotone_poly(mcur, v0, v1); + stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP); + } + } + else + { + stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN); + } + } + + else if ((t->d0 <= 0) && (t->d1 <= 0)) + { + if ((t->u0 > 0) && (t->u1 > 0)) /* upward opening triangle */ + { + v0 = t->rseg; + v1 = tr[t->u0].rseg; + if (from == t->u1) + { + mnew = make_new_monotone_poly(mcur, v1, v0); + stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN); + } + else + { + mnew = make_new_monotone_poly(mcur, v0, v1); + stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN); + } + } + else + { + stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN); + } + } + + else if ((t->u0 > 0) && (t->u1 > 0)) + { + if ((t->d0 > 0) && (t->d1 > 0)) /* downward + upward cusps */ + { + v0 = tr[t->d1].lseg; + v1 = tr[t->u0].rseg; + if (((dir == TR_FROM_DN) && (t->d1 == from)) || + ((dir == TR_FROM_UP) && (t->u1 == from))) + { + mnew = make_new_monotone_poly(mcur, v1, v0); + stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN); + } + else + { + mnew = make_new_monotone_poly(mcur, v0, v1); + stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN); + } + } + else /* only downward cusp */ + { + if (_equal_to(&t->lo, &seg[t->lseg].v1)) + { + v0 = tr[t->u0].rseg; + v1 = seg[t->lseg].next; + + if ((dir == TR_FROM_UP) && (t->u0 == from)) + { + mnew = make_new_monotone_poly(mcur, v1, v0); + stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN); + } + else + { + mnew = make_new_monotone_poly(mcur, v0, v1); + stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN); + } + } + else + { + v0 = t->rseg; + v1 = tr[t->u0].rseg; + if ((dir == TR_FROM_UP) && (t->u1 == from)) + { + mnew = make_new_monotone_poly(mcur, v1, v0); + stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN); + stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN); + } + else + { + mnew = make_new_monotone_poly(mcur, v0, v1); + stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN); + } + } + } + } + else if ((t->u0 > 0) || (t->u1 > 0)) /* no downward cusp */ + { + if ((t->d0 > 0) && (t->d1 > 0)) /* only upward cusp */ + { + if (_equal_to(&t->hi, &seg[t->lseg].v0)) + { + v0 = tr[t->d1].lseg; + v1 = t->lseg; + if (!((dir == TR_FROM_DN) && (t->d0 == from))) + { + mnew = make_new_monotone_poly(mcur, v1, v0); + stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN); + } + else + { + mnew = make_new_monotone_poly(mcur, v0, v1); + stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP); + } + } + else + { + v0 = tr[t->d1].lseg; + v1 = seg[t->rseg].next; + + if ((dir == TR_FROM_DN) && (t->d1 == from)) + { + mnew = make_new_monotone_poly(mcur, v1, v0); + stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN); + stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP); + } + else + { + mnew = make_new_monotone_poly(mcur, v0, v1); + stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN); + } + } + } + else /* no cusp */ + { + if (_equal_to(&t->hi, &seg[t->lseg].v0) && + _equal_to(&t->lo, &seg[t->rseg].v0)) + { + v0 = t->rseg; + v1 = t->lseg; + if (dir == TR_FROM_UP) + { + mnew = make_new_monotone_poly(mcur, v1, v0); + stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN); + } + else + { + mnew = make_new_monotone_poly(mcur, v0, v1); + stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP); + } + } + else if (_equal_to(&t->hi, &seg[t->rseg].v1) && + _equal_to(&t->lo, &seg[t->lseg].v1)) + { + v0 = seg[t->rseg].next; + v1 = seg[t->lseg].next; + + if (dir == TR_FROM_UP) + { + mnew = make_new_monotone_poly(mcur, v1, v0); + stkPush (stk, mnew, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mnew, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN); + } + else + { + mnew = make_new_monotone_poly(mcur, v0, v1); + stkPush (stk, mnew, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mnew, t->u0, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP); + } + } + else /* no split possible */ + { + stkPush (stk, mcur, t->d1, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u1, trnum, TR_FROM_DN); + stkPush (stk, mcur, t->d0, trnum, TR_FROM_UP); + stkPush (stk, mcur, t->u0, trnum, TR_FROM_DN); + } + } + } + } + + stkClose (stk); + return size; +} +#endif static int monotonate_trapezoids(int nsegs, segment_t*seg, trap_t* tr,