monotone.c
来自「[Game.Programming].Academic - Graphics G」· C语言 代码 · 共 689 行 · 第 1/2 页
C
689 行
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); traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN); traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP); traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN); traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP); } else { mnew = make_new_monotone_poly(mcur, v0, v1); traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN); traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP); traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN); traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP); } } else /* only downward cusp */ { if (_equal_to(&t->lo, &seg[t->lseg].v1)) { v0 = tr[t->u0].rseg; v1 = MODULO_NEXT(t->lseg + 1, global.nseg); retval = SP_2UP_LEFT; if ((dir == TR_FROM_UP) && (t->u0 == from)) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN); traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP); traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN); traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP); } else { mnew = make_new_monotone_poly(mcur, v0, v1); traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN); traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP); traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP); traverse_polygon(mnew, t->u0, trnum, 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); traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN); traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP); traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP); traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN); } else { mnew = make_new_monotone_poly(mcur, v0, v1); traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN); traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP); traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP); traverse_polygon(mnew, t->u1, 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; retval = SP_2DN_LEFT; if (!((dir == TR_FROM_DN) && (t->d0 == from))) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN); traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP); traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN); traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP); } else { mnew = make_new_monotone_poly(mcur, v0, v1); traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP); traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN); traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN); traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP); } } else { v0 = tr[t->d1].lseg; v1 = MODULO_NEXT(t->rseg + 1, global.nseg); retval = SP_2DN_RIGHT; if ((dir == TR_FROM_DN) && (t->d1 == from)) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP); traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN); traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN); traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP); } else { mnew = make_new_monotone_poly(mcur, v0, v1); traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN); traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP); traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN); traverse_polygon(mnew, t->d1, trnum, 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); traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN); traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN); traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP); traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP); } else { mnew = make_new_monotone_poly(mcur, v0, v1); traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP); traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP); traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN); traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN); } } else if (_equal_to(&t->hi, &seg[t->rseg].v1) && _equal_to(&t->lo, &seg[t->lseg].v1)) { v0 = MODULO_NEXT(t->rseg + 1, global.nseg); v1 = MODULO_NEXT(t->lseg + 1, global.nseg); retval = SP_SIMPLE_LRUP; if (dir == TR_FROM_UP) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN); traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN); traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP); traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP); } else { mnew = make_new_monotone_poly(mcur, v0, v1); traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP); traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP); traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN); traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN); } } else /* no split possible */ { retval = SP_NOSPLIT; traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN); traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP); traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN); traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP); } } } return retval;}int triangulate_monotone_polygons(nmonpoly, op) int nmonpoly; int op[][3];{ register int i; point_t ymax, ymin; int p, vfirst, posmax, posmin, v; int vcount;#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; vfirst = mchain[mon[i]].vnum; ymax = ymin = vert[vfirst].pt; posmax = posmin = mon[i]; p = mchain[mon[i]].next; while ((v = mchain[p].vnum) != vfirst) { 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 (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(posmax, TRI_LHS, op); } else triangulate_single_polygon(posmax, TRI_RHS, op); } } #ifdef DEBUG for (i = 0; i < (global.nseg - 2); i++) fprintf(stderr, "tri #%d: (%d, %d, %d)\n", i, op[i][0], op[i][1], op[i][2]);#endif}/* A greedy corner-cutting algorithm to triangulate a y-monotone * polygon in O(n) time. * Joseph O-Rourke, Computational Geometry in C. */int triangulate_single_polygon(posmax, side, op) int posmax; int side; int op[][3];{ register int v; int rc[SEGSIZE], ri = 0; /* reflex chain */ int endv, tmp, vpos; if (side == TRI_RHS) /* RHS segment is a single segment */ { rc[0] = mchain[posmax].vnum; tmp = mchain[posmax].next; rc[1] = mchain[tmp].vnum; ri = 1; vpos = mchain[tmp].next; v = mchain[vpos].vnum; if ((endv = mchain[mchain[posmax].prev].vnum) == 0) endv = global.nseg; } else /* LHS is a single segment */ { tmp = mchain[posmax].next; rc[0] = mchain[tmp].vnum; tmp = mchain[tmp].next; rc[1] = mchain[tmp].vnum; ri = 1; vpos = mchain[tmp].next; v = mchain[vpos].vnum; endv = mchain[posmax].vnum; } while ((v != endv) || (ri > 1)) { if (ri > 0) /* reflex chain is non-empty */ { if (CROSS(vert[v].pt, vert[rc[ri - 1]].pt, vert[rc[ri]].pt) > 0) { /* convex corner: cut if off */ op[op_idx][0] = rc[ri - 1]; op[op_idx][1] = rc[ri]; op[op_idx][2] = v; op_idx++; ri--; } else /* non-convex */ { /* add v to the chain */ ri++; rc[ri] = v; vpos = mchain[vpos].next; v = mchain[vpos].vnum; } } else /* reflex-chain empty: add v to the */ { /* reflex chain and advance it */ rc[++ri] = v; vpos = mchain[vpos].next; v = mchain[vpos].vnum; } } /* end-while */ /* reached the bottom vertex. Add in the triangle formed */ op[op_idx][0] = rc[ri - 1]; op[op_idx][1] = rc[ri]; op[op_idx][2] = v; op_idx++; ri--; return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?