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,
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,