/*--------------------------------------------------------------------- 'p': The segment lies wholly within the plane. 'q': The q endpoint is on the plane (but not 'p'). 'r': The r endpoint is on the plane (but not 'p'). '0': The segment lies strictly to one side or the other of the plane. '1': The segement intersects the plane, and 'p' does not hold. ---------------------------------------------------------------------*/ char SegPlaneInt( tPointi T, tPointd q, tPointd r, tPointd p, int *m) { tPointd N; double d; tPointd rq; double num, denom, t; int i; *m = PlaneCoeff( T, N, &d ); /*printf("m=%d; plane=(%lf,%lf,%lf,%lf)\n", m, N[X],N[Y],N[Z],d);*/ num = d - Dot( q, N ); SubVec( r, q, rq ); denom = Dot( rq, N ); /*printf("SegPlaneInt: num=%lf, denom=%lf\n", num, denom );*/ if ( denom == 0.0 ) { /* Segment is parallel to plane. */ if ( num == 0.0 ) /* q is on plane. */ return 'p'; else return '0'; } else t = num / denom; /*printf("SegPlaneInt: t=%lf \n", t );*/ for( i = 0; i < DIM; i++ ) p[i] = q[i] + t * ( r[i] - q[i] ); if ( (0.0 < t) && (t < 1.0) ) return '1'; else if ( num == 0.0 ) /* t == 0 */ return 'q'; else if ( num == denom ) /* t == 1 */ return 'r'; else return '0'; }
/*--------------------------------------------------------------------- ---------------------------------------------------------------------*/ void ConvexIntersect( tPolygoni P, tPolygoni Q, int n, int m ) /* P has n vertices, Q has m vertices. */ { int a, b; /* indices on P and Q (resp.) */ int a1, b1; /* a-1, b-1 (resp.) */ tPointi A, B; /* directed edges on P and Q (resp.) */ int cross; /* sign of z-component of A x B */ int bHA, aHB; /* b in H(A); a in H(b). */ tPointi Origin = {0,0}; /* (0,0) */ tPointd p; /* double point of intersection */ tPointd q; /* second point of intersection */ tInFlag inflag; /* {Pin, Qin, Unknown}: which inside */ int aa, ba; /* # advances on a & b indices (after 1st inter.) */ bool FirstPoint; /* Is this the first point? (used to initialize).*/ tPointd p0; /* The first point. */ int code; /* SegSegInt return code. */ /* Initialize variables. */ a = 0; b = 0; aa = 0; ba = 0; inflag = Unknown; FirstPoint = TRUE; do { /*printf("%%Before Advances:a=%d, b=%d; aa=%d, ba=%d; inflag=%d\n", a, b, aa, ba, inflag);*/ /* Computations of key variables. */ a1 = (a + n - 1) % n; b1 = (b + m - 1) % m; SubVec( P[a], P[a1], A ); SubVec( Q[b], Q[b1], B ); cross = AreaSign( Origin, A, B ); aHB = AreaSign( Q[b1], Q[b], P[a] ); bHA = AreaSign( P[a1], P[a], Q[b] ); printf("%%cross=%d, aHB=%d, bHA=%d\n", cross, aHB, bHA ); /* If A & B intersect, update inflag. */ code = SegSegInt( P[a1], P[a], Q[b1], Q[b], p, q ); printf("%%SegSegInt: code = %c\n", code ); if ( code == '1' || code == 'v' ) { if ( inflag == Unknown && FirstPoint ) { aa = ba = 0; FirstPoint = FALSE; p0[X] = p[X]; p0[Y] = p[Y]; printf("%8.2lf %8.2lf moveto\n", p0[X], p0[Y] ); } inflag = InOut( p, inflag, aHB, bHA ); printf("%%InOut sets inflag=%d\n", inflag); } /*-----Advance rules-----*/ /* Special case: A & B overlap and oppositely oriented. */ if ( ( code == 'e' ) && (Dot( A, B ) < 0) ) PrintSharedSeg( p, q ), exit(EXIT_SUCCESS); /* Special case: A & B parallel and separated. */ if ( (cross == 0) && ( aHB < 0) && ( bHA < 0 ) ) printf("%%P and Q are disjoint.\n"), exit(EXIT_SUCCESS); /* Special case: A & B collinear. */ else if ( (cross == 0) && ( aHB == 0) && ( bHA == 0 ) ) { /* Advance but do not output point. */ if ( inflag == Pin ) b = Advance( b, &ba, m, inflag == Qin, Q[b] ); else a = Advance( a, &aa, n, inflag == Pin, P[a] ); } /* Generic cases. */ else if ( cross >= 0 ) { if ( bHA > 0) a = Advance( a, &aa, n, inflag == Pin, P[a] ); else b = Advance( b, &ba, m, inflag == Qin, Q[b] ); } else /* if ( cross < 0 ) */{ if ( aHB > 0) b = Advance( b, &ba, m, inflag == Qin, Q[b] ); else a = Advance( a, &aa, n, inflag == Pin, P[a] ); } printf("%%After advances:a=%d, b=%d; aa=%d, ba=%d; inflag=%d\n", a, b, aa, ba, inflag); /* Quit when both adv. indices have cycled, or one has cycled twice. */ } while ( ((aa < n) || (ba < m)) && (aa < 2*n) && (ba < 2*m) ); if ( !FirstPoint ) /* If at least one point output, close up. */ printf("%8.2lf %8.2lf lineto\n", p0[X], p0[Y] ); /* Deal with special cases: not implemented. */ if ( inflag == Unknown) printf("%%The boundaries of P and Q do not cross.\n"); }
/*--------------------------------------------------------------------- Print: Prints out the vertices and the faces. Uses the vnum indices corresponding to the order in which the vertices were input. Output is in PostScript format. ---------------------------------------------------------------------*/ void Print( void ) { /* Pointers to vertices, edges, faces. */ tVertex v; tEdge e; tFace f; int xmin, ymin, xmax, ymax; int a[3], b[3]; /* used to compute normal vector */ /* Counters for Euler's formula. */ int V = 0, E = 0 , F = 0; /* Note: lowercase==pointer, uppercase==counter. */ /*-- find X min & max --*/ v = vertices; xmin = xmax = v->v[X]; do { if( v->v[X] > xmax ) xmax = v->v[X]; else if( v->v[X] < xmin ) xmin = v->v[X]; v = v->next; } while ( v != vertices ); /*-- find Y min & max --*/ v = vertices; ymin = ymax = v->v[Y]; do { if( v->v[Y] > ymax ) ymax = v->v[Y]; else if( v->v[Y] < ymin ) ymin = v->v[Y]; v = v->next; } while ( v != vertices ); /* PostScript header */ printf("%%!PS\n"); printf("%%%%BoundingBox: %d %d %d %d\n", xmin, ymin, xmax, ymax); printf(".00 .00 setlinewidth\n"); printf("%d %d translate\n", -xmin+72, -ymin+72 ); /* The +72 shifts the figure one inch from the lower left corner */ /* Vertices. */ v = vertices; do { if( v->mark ) V++; v = v->next; } while ( v != vertices ); printf("\n%%%% Vertices:\tV = %d\n", V); printf("%%%% index:\tx\ty\tz\n"); do { printf( "%%%% %5d:\t%d\t%d\t%d\n", v->vnum, v->v[X], v->v[Y], v->v[Z] ); v = v->next; } while ( v != vertices ); /* Faces. */ /* visible faces are printed as PS output */ f = faces; do { ++F; f = f ->next; } while ( f != faces ); printf("\n%%%% Faces:\tF = %d\n", F ); printf("%%%% Visible faces only: \n"); do { /* Print face only if it is visible: if normal vector >= 0 */ SubVec( f->vertex[1]->v, f->vertex[0]->v, a ); SubVec( f->vertex[2]->v, f->vertex[1]->v, b ); if(( a[0] * b[1] - a[1] * b[0] ) >= 0 ) { printf("%%%% vnums: %d %d %d\n", f->vertex[0]->vnum, f->vertex[1]->vnum, f->vertex[2]->vnum); printf("newpath\n"); printf("%d\t%d\tmoveto\n", f->vertex[0]->v[X], f->vertex[0]->v[Y] ); printf("%d\t%d\tlineto\n", f->vertex[1]->v[X], f->vertex[1]->v[Y] ); printf("%d\t%d\tlineto\n", f->vertex[2]->v[X], f->vertex[2]->v[Y] ); printf("closepath stroke\n\n"); } f = f->next; } while ( f != faces ); /* prints a list of all faces */ printf("%%%% List of all faces: \n"); printf("%%%%\tv0\tv1\tv2\t(vertex indices)\n"); do { printf("%%%%\t%d\t%d\t%d\n", f->vertex[0]->vnum, f->vertex[1]->vnum, f->vertex[2]->vnum ); f = f->next; } while ( f != faces ); /* Edges. */ e = edges; do { E++; e = e->next; } while ( e != edges ); printf("\n%%%% Edges:\tE = %d\n", E ); /* Edges not printed out (but easily added). */ printf("\nshowpage\n\n"); check = TRUE; CheckEuler( V, E, F ); }