Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
static void DonePriorityQ( TESStesselator *tess )
{
	pqDeletePriorityQ( &tess->alloc, tess->pq );
}
Example #5
0
static void DonePriorityQ( GLUtesselator *tess )
{
  pqDeletePriorityQ( tess->pq ); /* __gl_pqSortDeletePriorityQ */
}
Example #6
0
static void DonePriorityQ( wrath_GLUtesselator *tess )
{
  pqDeletePriorityQ( tess->pq ); /* glu_wrath_gl_pqSortDeletePriorityQ */
}