static int monotonate_trapezoids(int nsegs, segment_t*seg, trap_t* tr, int flip, boxf* decomp) { int i, size; int tr_start; int tr_size = TRSIZE(nsegs); int* visited = N_NEW(tr_size,int); mchain = N_NEW(tr_size, monchain_t); vert = N_NEW(nsegs+1,vertexchain_t); mon = N_NEW(nsegs, int); /* First locate a trapezoid which lies inside the polygon */ /* and which is triangular */ for (i = 0; i < TRSIZE(nsegs); i++) if (inside_polygon(&tr[i], seg)) break; tr_start = i; /* Initialise the mon data-structure and start spanning all the */ /* trapezoids within the polygon */ for (i = 1; i <= nsegs; i++) { mchain[i].prev = seg[i].prev; mchain[i].next = seg[i].next; mchain[i].vnum = i; vert[i].pt = seg[i].v0; vert[i].vnext[0] = seg[i].next; /* next vertex */ vert[i].vpos[0] = i; /* locn. of next vertex */ vert[i].nextfree = 1; } chain_idx = nsegs; mon_idx = 0; mon[0] = 1; /* position of any vertex in the first */ /* chain */ /* traverse the polygon */ if (tr[tr_start].u0 > 0) size = traverse_polygon (visited, decomp, 0, seg, tr, 0, tr_start, tr[tr_start].u0, flip, TR_FROM_UP); else if (tr[tr_start].d0 > 0) size = traverse_polygon (visited, decomp, 0, seg, tr, 0, tr_start, tr[tr_start].d0, flip, TR_FROM_DN); free (visited); free (mchain); free (vert); free (mon); /* return the number of rects created */ return size; }
/* recursively visit all the trapezoids */ static int traverse_polygon (int* visited, boxf* decomp, int size, segment_t* seg, trap_t* tr, int mcur, int trnum, int from, int flip, int dir) { trap_t *t = &tr[trnum]; int mnew; int v0, v1; int retval; int do_switch = FALSE; if ((trnum <= 0) || visited[trnum]) return size; 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) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP); } else { mnew = make_new_monotone_poly(mcur, v0, v1); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP); } } else { retval = SP_NOSPLIT; /* Just traverse all neighbours */ size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP); } } 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) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN); } else { mnew = make_new_monotone_poly(mcur, v0, v1); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN); } } else { retval = SP_NOSPLIT; /* Just traverse all neighbours */ size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP); } } 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; retval = SP_2UP_2DN; if (((dir == TR_FROM_DN) && (t->d1 == from)) || ((dir == TR_FROM_UP) && (t->u1 == from))) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP); } else { mnew = make_new_monotone_poly(mcur, v0, v1); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP); } } else /* only downward cusp */ { if (_equal_to(&t->lo, &seg[t->lseg].v1)) { v0 = tr[t->u0].rseg; v1 = seg[t->lseg].next; retval = SP_2UP_LEFT; if ((dir == TR_FROM_UP) && (t->u0 == from)) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP); } else { mnew = make_new_monotone_poly(mcur, v0, v1); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN); } } else { v0 = t->rseg; v1 = tr[t->u0].rseg; retval = SP_2UP_RIGHT; if ((dir == TR_FROM_UP) && (t->u1 == from)) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN); } else { mnew = make_new_monotone_poly(mcur, v0, v1); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u1, trnum, flip, 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; retval = SP_2DN_LEFT; if (!((dir == TR_FROM_DN) && (t->d0 == from))) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP); } else { mnew = make_new_monotone_poly(mcur, v0, v1); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP); } } else { v0 = tr[t->d1].lseg; v1 = seg[t->rseg].next; retval = SP_2DN_RIGHT; if ((dir == TR_FROM_DN) && (t->d1 == from)) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP); } else { mnew = make_new_monotone_poly(mcur, v0, v1); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP); } } } 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; retval = SP_SIMPLE_LRDN; if (dir == TR_FROM_UP) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP); } else { mnew = make_new_monotone_poly(mcur, v0, v1); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN); } } 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; retval = SP_SIMPLE_LRUP; if (dir == TR_FROM_UP) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP); } else { mnew = make_new_monotone_poly(mcur, v0, v1); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN); } } else /* no split possible */ { retval = SP_NOSPLIT; size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN); size = traverse_polygon (visited, decomp, size, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP); } } } return size; }
int monotonate_trapezoids( int n) { register int i; int tr_start; memset((void *)vert, 0, sizeof(vert)); memset((void *)visited, 0, sizeof(visited)); memset((void *)mchain, 0, sizeof(mchain)); memset((void *)mon, 0, sizeof(mon)); /* First locate a trapezoid which lies inside the polygon */ /* and which is triangular */ for (i = 0; i < TRSIZE; i++) if (inside_polygon(&tr[i])) break; tr_start = i; /* Initialise the mon data-structure and start spanning all the */ /* trapezoids within the polygon */ #if 0 for (i = 1; i <= n; i++) { mchain[i].prev = i - 1; mchain[i].next = i + 1; mchain[i].vnum = i; vert[i].pt = seg[i].v0; vert[i].vnext[0] = i + 1; /* next vertex */ vert[i].vpos[0] = i; /* locn. of next vertex */ vert[i].nextfree = 1; } mchain[1].prev = n; mchain[n].next = 1; vert[n].vnext[0] = 1; vert[n].vpos[0] = n; chain_idx = n; mon_idx = 0; mon[0] = 1; /* position of any vertex in the first */ /* chain */ #else for (i = 1; i <= n; i++) { mchain[i].prev = seg[i].prev; mchain[i].next = seg[i].next; mchain[i].vnum = i; vert[i].pt = seg[i].v0; vert[i].vnext[0] = seg[i].next; /* next vertex */ vert[i].vpos[0] = i; /* locn. of next vertex */ vert[i].nextfree = 1; } chain_idx = n; mon_idx = 0; mon[0] = 1; /* position of any vertex in the first */ /* chain */ #endif /* traverse the polygon */ if (tr[tr_start].u0 > 0) traverse_polygon(0, tr_start, tr[tr_start].u0, TR_FROM_UP); else if (tr[tr_start].d0 > 0) traverse_polygon(0, tr_start, tr[tr_start].d0, TR_FROM_DN); /* return the number of polygons created */ return newmon(); }