static int InitPriorityQ( TESStesselator *tess ) /* * Insert all vertices into the priority queue which determines the * order in which vertices cross the sweep line. */ { PriorityQ *pq; TESSvertex *v, *vHead; int vertexCount = 0; vHead = &tess->mesh->vHead; for( v = vHead->next; v != vHead; v = v->next ) { vertexCount++; } /* Make sure there is enough space for sentinels. */ vertexCount += MAX( 8, tess->alloc.extraVertices ); pq = tess->pq = pqNewPriorityQ( &tess->alloc, vertexCount, (int (*)(PQkey, PQkey)) tesvertLeq ); if (pq == NULL) return 0; vHead = &tess->mesh->vHead; for( v = vHead->next; v != vHead; v = v->next ) { v->pqHandle = pqInsert( &tess->alloc, pq, v ); if (v->pqHandle == INV_HANDLE) break; } if (v != vHead || !pqInit( &tess->alloc, pq ) ) { pqDeletePriorityQ( &tess->alloc, tess->pq ); tess->pq = NULL; return 0; } return 1; }
static int InitPriorityQ( GLUtesselator *tess ) /* * Insert all vertices into the priority queue which determines the * order in which vertices cross the sweep line. */ { PriorityQ *pq; GLUvertex *v, *vHead; /* __gl_pqSortNewPriorityQ */ pq = tess->pq = pqNewPriorityQ( (int (*)(PQkey, PQkey)) __gl_vertLeq ); if (pq == NULL) return 0; vHead = &tess->mesh->vHead; for( v = vHead->next; v != vHead; v = v->next ) { v->pqHandle = pqInsert( pq, v ); /* __gl_pqSortInsert */ if (v->pqHandle == LONG_MAX) break; } if (v != vHead || !pqInit( pq ) ) { /* __gl_pqSortInit */ pqDeletePriorityQ(tess->pq); /* __gl_pqSortDeletePriorityQ */ tess->pq = NULL; return 0; } return 1; }
static int CheckForIntersect( TESStesselator *tess, ActiveRegion *regUp ) /* * Check the upper and lower edges of the given region to see if * they intersect. If so, create the intersection and add it * to the data structures. * * Returns TRUE if adding the new intersection resulted in a recursive * call to AddRightEdges(); in this case all "dirty" regions have been * checked for intersections, and possibly regUp has been deleted. */ { ActiveRegion *regLo = RegionBelow(regUp); TESShalfEdge *eUp = regUp->eUp; TESShalfEdge *eLo = regLo->eUp; TESSvertex *orgUp = eUp->Org; TESSvertex *orgLo = eLo->Org; TESSvertex *dstUp = eUp->Dst; TESSvertex *dstLo = eLo->Dst; TESSreal tMinUp, tMaxLo; TESSvertex isect, *orgMin; TESShalfEdge *e; assert( ! VertEq( dstLo, dstUp )); assert( EdgeSign( dstUp, tess->event, orgUp ) <= 0 ); assert( EdgeSign( dstLo, tess->event, orgLo ) >= 0 ); assert( orgUp != tess->event && orgLo != tess->event ); assert( ! regUp->fixUpperEdge && ! regLo->fixUpperEdge ); if( orgUp == orgLo ) return FALSE; /* right endpoints are the same */ tMinUp = MIN( orgUp->t, dstUp->t ); tMaxLo = MAX( orgLo->t, dstLo->t ); if( tMinUp > tMaxLo ) return FALSE; /* t ranges do not overlap */ if( VertLeq( orgUp, orgLo )) { if( EdgeSign( dstLo, orgUp, orgLo ) > 0 ) return FALSE; } else { if( EdgeSign( dstUp, orgLo, orgUp ) < 0 ) return FALSE; } /* At this point the edges intersect, at least marginally */ DebugEvent( tess ); tesedgeIntersect( dstUp, orgUp, dstLo, orgLo, &isect ); /* The following properties are guaranteed: */ assert( MIN( orgUp->t, dstUp->t ) <= isect.t ); assert( isect.t <= MAX( orgLo->t, dstLo->t )); assert( MIN( dstLo->s, dstUp->s ) <= isect.s ); assert( isect.s <= MAX( orgLo->s, orgUp->s )); if( VertLeq( &isect, tess->event )) { /* The intersection point lies slightly to the left of the sweep line, * so move it until it''s slightly to the right of the sweep line. * (If we had perfect numerical precision, this would never happen * in the first place). The easiest and safest thing to do is * replace the intersection by tess->event. */ isect.s = tess->event->s; isect.t = tess->event->t; } /* Similarly, if the computed intersection lies to the right of the * rightmost origin (which should rarely happen), it can cause * unbelievable inefficiency on sufficiently degenerate inputs. * (If you have the test program, try running test54.d with the * "X zoom" option turned on). */ orgMin = VertLeq( orgUp, orgLo ) ? orgUp : orgLo; if( VertLeq( orgMin, &isect )) { isect.s = orgMin->s; isect.t = orgMin->t; } if( VertEq( &isect, orgUp ) || VertEq( &isect, orgLo )) { /* Easy case -- intersection at one of the right endpoints */ (void) CheckForRightSplice( tess, regUp ); return FALSE; } if( (! VertEq( dstUp, tess->event ) && EdgeSign( dstUp, tess->event, &isect ) >= 0) || (! VertEq( dstLo, tess->event ) && EdgeSign( dstLo, tess->event, &isect ) <= 0 )) { /* Very unusual -- the new upper or lower edge would pass on the * wrong side of the sweep event, or through it. This can happen * due to very small numerical errors in the intersection calculation. */ if( dstLo == tess->event ) { /* Splice dstLo into eUp, and process the new region(s) */ if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); if ( !tessMeshSplice( tess->mesh, eLo->Sym, eUp ) ) longjmp(tess->env,1); regUp = TopLeftRegion( tess, regUp ); if (regUp == NULL) longjmp(tess->env,1); eUp = RegionBelow(regUp)->eUp; FinishLeftRegions( tess, RegionBelow(regUp), regLo ); AddRightEdges( tess, regUp, eUp->Oprev, eUp, eUp, TRUE ); return TRUE; } if( dstUp == tess->event ) { /* Splice dstUp into eLo, and process the new region(s) */ if (tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); if ( !tessMeshSplice( tess->mesh, eUp->Lnext, eLo->Oprev ) ) longjmp(tess->env,1); regLo = regUp; regUp = TopRightRegion( regUp ); e = RegionBelow(regUp)->eUp->Rprev; regLo->eUp = eLo->Oprev; eLo = FinishLeftRegions( tess, regLo, NULL ); AddRightEdges( tess, regUp, eLo->Onext, eUp->Rprev, e, TRUE ); return TRUE; } /* Special case: called from ConnectRightVertex. If either * edge passes on the wrong side of tess->event, split it * (and wait for ConnectRightVertex to splice it appropriately). */ if( EdgeSign( dstUp, tess->event, &isect ) >= 0 ) { RegionAbove(regUp)->dirty = regUp->dirty = TRUE; if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); eUp->Org->s = tess->event->s; eUp->Org->t = tess->event->t; } if( EdgeSign( dstLo, tess->event, &isect ) <= 0 ) { regUp->dirty = regLo->dirty = TRUE; if (tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); eLo->Org->s = tess->event->s; eLo->Org->t = tess->event->t; } /* leave the rest for ConnectRightVertex */ return FALSE; } /* General case -- split both edges, splice into new vertex. * When we do the splice operation, the order of the arguments is * arbitrary as far as correctness goes. However, when the operation * creates a new face, the work done is proportional to the size of * the new face. We expect the faces in the processed part of * the mesh (ie. eUp->Lface) to be smaller than the faces in the * unprocessed original contours (which will be eLo->Oprev->Lface). */ if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); if (tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); if ( !tessMeshSplice( tess->mesh, eLo->Oprev, eUp ) ) longjmp(tess->env,1); eUp->Org->s = isect.s; eUp->Org->t = isect.t; eUp->Org->pqHandle = pqInsert( &tess->alloc, tess->pq, eUp->Org ); if (eUp->Org->pqHandle == INV_HANDLE) { pqDeletePriorityQ( &tess->alloc, tess->pq ); tess->pq = NULL; longjmp(tess->env,1); } GetIntersectData( tess, eUp->Org, orgUp, dstUp, orgLo, dstLo ); RegionAbove(regUp)->dirty = regUp->dirty = regLo->dirty = TRUE; return FALSE; }
static void DonePriorityQ( TESStesselator *tess ) { pqDeletePriorityQ( &tess->alloc, tess->pq ); }
static void DonePriorityQ( GLUtesselator *tess ) { pqDeletePriorityQ( tess->pq ); /* __gl_pqSortDeletePriorityQ */ }
static void DonePriorityQ( wrath_GLUtesselator *tess ) { pqDeletePriorityQ( tess->pq ); /* glu_wrath_gl_pqSortDeletePriorityQ */ }