bool LAB::user::operator!=(const LAB::user& _Rhs) const { return !_equal_to(_Rhs); }
/* 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 triangulate_monotone_polygons( int nvert, int nmonpoly, int op[][3]) { register int i; point_t ymax, ymin; int p, vfirst, posmax, posmin, v; int vcount, processed; #ifdef DEBUG for (i = 0; i < nmonpoly; i++) { fprintf(stderr, "\n\nPolygon %d: ", i); vfirst = mchain[mon[i]].vnum; p = mchain[mon[i]].next; fprintf (stderr, "%d ", mchain[mon[i]].vnum); while (mchain[p].vnum != vfirst) { fprintf(stderr, "%d ", mchain[p].vnum); p = mchain[p].next; } } fprintf(stderr, "\n"); #endif op_idx = 0; for (i = 0; i < nmonpoly; i++) { vcount = 1; processed = FALSE; vfirst = mchain[mon[i]].vnum; ymax = ymin = vert[vfirst].pt; posmax = posmin = mon[i]; mchain[mon[i]].marked = TRUE; p = mchain[mon[i]].next; while ((v = mchain[p].vnum) != vfirst) { if (mchain[p].marked) { processed = TRUE; break; /* break from while */ } else mchain[p].marked = TRUE; if (_greater_than(&vert[v].pt, &ymax)) { ymax = vert[v].pt; posmax = p; } if (_less_than(&vert[v].pt, &ymin)) { ymin = vert[v].pt; posmin = p; } p = mchain[p].next; vcount++; } if (processed) /* Go to next polygon */ continue; if (vcount == 3) /* already a triangle */ { op[op_idx][0] = mchain[p].vnum; op[op_idx][1] = mchain[mchain[p].next].vnum; op[op_idx][2] = mchain[mchain[p].prev].vnum; op_idx++; } else /* triangulate the polygon */ { v = mchain[mchain[posmax].next].vnum; if (_equal_to(&vert[v].pt, &ymin)) { /* LHS is a single line */ triangulate_single_polygon(nvert, posmax, TRI_LHS, op); } else triangulate_single_polygon(nvert, posmax, TRI_RHS, op); } } #ifdef DEBUG for (i = 0; i < op_idx; i++) fprintf(stderr, "tri #%d: (%d, %d, %d)\n", i, op[i][0], op[i][1], op[i][2]); #endif return op_idx; }