static int EdgeLeq( GLUtesselator *tess, ActiveRegion *reg1, ActiveRegion *reg2 ) /* * Both edges must be directed from right to left (this is the canonical * direction for the upper edge of each region). * * The strategy is to evaluate a "t" value for each edge at the * current sweep line position, given by tess->event. The calculations * are designed to be very stable, but of course they are not perfect. * * Special case: if both edge destinations are at the sweep event, * we sort the edges by slope (they would otherwise compare equally). */ { GLUvertex *event = tess->event; GLUhalfEdge *e1, *e2; GLdouble t1, t2; e1 = reg1->eUp; e2 = reg2->eUp; if( e1->Dst == event ) { if( e2->Dst == event ) { /* Two edges right of the sweep line which meet at the sweep event. * Sort them by slope. */ if( VertLeq( e1->Org, e2->Org )) { return EdgeSign( e2->Dst, e1->Org, e2->Org ) <= 0; } return EdgeSign( e1->Dst, e2->Org, e1->Org ) >= 0; } return EdgeSign( e2->Dst, event, e2->Org ) <= 0; } if( e2->Dst == event ) { return EdgeSign( e1->Dst, event, e1->Org ) >= 0; } /* General case - compute signed distance *from* e1, e2 to event */ t1 = EdgeEval( e1->Dst, event, e1->Org ); t2 = EdgeEval( e2->Dst, event, e2->Org ); return (t1 >= t2); }
void __gl_edgeIntersect( GLUvertex *o1, GLUvertex *d1, GLUvertex *o2, GLUvertex *d2, GLUvertex *v ) /* Given edges (o1,d1) and (o2,d2), compute their point of intersection. * The computed point is guaranteed to lie in the intersection of the * bounding rectangles defined by each edge. */ { GLdouble z1, z2; /* This is certainly not the most efficient way to find the intersection * of two line segments, but it is very numerically stable. * * Strategy: find the two middle vertices in the VertLeq ordering, * and interpolate the intersection s-value from these. Then repeat * using the TransLeq ordering to find the intersection t-value. */ if( ! VertLeq( o1, d1 )) { Swap( o1, d1 ); } if( ! VertLeq( o2, d2 )) { Swap( o2, d2 ); } if( ! VertLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); } if( ! VertLeq( o2, d1 )) { /* Technically, no intersection -- do our best */ v->s = (o2->s + d1->s) / 2; } else if( VertLeq( d1, d2 )) { /* Interpolate between o2 and d1 */ z1 = EdgeEval( o1, o2, d1 ); z2 = EdgeEval( o2, d1, d2 ); if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } v->s = Interpolate( z1, o2->s, z2, d1->s ); } else { /* Interpolate between o2 and d2 */ z1 = EdgeSign( o1, o2, d1 ); z2 = -EdgeSign( o1, d2, d1 ); if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } v->s = Interpolate( z1, o2->s, z2, d2->s ); } /* Now repeat the process for t */ if( ! TransLeq( o1, d1 )) { Swap( o1, d1 ); } if( ! TransLeq( o2, d2 )) { Swap( o2, d2 ); } if( ! TransLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); } if( ! TransLeq( o2, d1 )) { /* Technically, no intersection -- do our best */ v->t = (o2->t + d1->t) / 2; } else if( TransLeq( d1, d2 )) { /* Interpolate between o2 and d1 */ z1 = TransEval( o1, o2, d1 ); z2 = TransEval( o2, d1, d2 ); if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } v->t = Interpolate( z1, o2->t, z2, d1->t ); } else { /* Interpolate between o2 and d2 */ z1 = TransSign( o1, o2, d1 ); z2 = -TransSign( o1, d2, d1 ); if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } v->t = Interpolate( z1, o2->t, z2, d2->t ); } }