Пример #1
0
int tessComputeInterior( TESStesselator *tess )
/*
* tessComputeInterior( tess ) computes the planar arrangement specified
* by the given contours, and further subdivides this arrangement
* into regions.  Each region is marked "inside" if it belongs
* to the polygon, according to the rule given by tess->windingRule.
* Each interior region is guaranteed be monotone.
*/
{
	TESSvertex *v, *vNext;

	/* Each vertex defines an event for our sweep line.  Start by inserting
	* all the vertices in a priority queue.  Events are processed in
	* lexicographic order, ie.
	*
	*	e1 < e2  iff  e1.x < e2.x || (e1.x == e2.x && e1.y < e2.y)
	*/
	RemoveDegenerateEdges( tess );
	if ( !InitPriorityQ( tess ) ) return 0; /* if error */
	InitEdgeDict( tess );

	while( (v = (TESSvertex *)pqExtractMin( tess->pq )) != NULL ) {
		for( ;; ) {
			vNext = (TESSvertex *)pqMinimum( tess->pq );
			if( vNext == NULL || ! VertEq( vNext, v )) break;

			/* Merge together all vertices at exactly the same location.
			* This is more efficient than processing them one at a time,
			* simplifies the code (see ConnectLeftDegenerate), and is also
			* important for correct handling of certain degenerate cases.
			* For example, suppose there are two identical edges A and B
			* that belong to different contours (so without this code they would
			* be processed by separate sweep events).  Suppose another edge C
			* crosses A and B from above.  When A is processed, we split it
			* at its intersection point with C.  However this also splits C,
			* so when we insert B we may compute a slightly different
			* intersection point.  This might leave two edges with a small
			* gap between them.  This kind of error is especially obvious
			* when using boundary extraction (TESS_BOUNDARY_ONLY).
			*/
			vNext = (TESSvertex *)pqExtractMin( tess->pq );
			SpliceMergeVertices( tess, v->anEdge, vNext->anEdge );
		}
		SweepEvent( tess, v );
	}

	/* Set tess->event for debugging purposes */
	tess->event = ((ActiveRegion *) dictKey( dictMin( tess->dict )))->eUp->Org;
	DebugEvent( tess );
	DoneEdgeDict( tess );
	DonePriorityQ( tess );

	if ( !RemoveDegenerateFaces( tess, tess->mesh ) ) return 0;
	tessMeshCheckMesh( tess->mesh );

	return 1;
}
Пример #2
0
static void DoneEdgeDict( TESStesselator *tess )
{
	ActiveRegion *reg;

	while( (reg = (ActiveRegion *)dictKey( dictMin( tess->dict ))) != NULL ) {
		/*
		* At the end of all processing, the dictionary should contain
		* only the two sentinel edges, plus at most one "fixable" edge
		* created by ConnectRightVertex().
		*/
		if( ! reg->sentinel ) {
			assert( reg->fixUpperEdge );
      //assert( ++fixedEdges == 1 );
		}
		assert( reg->windingNumber == 0 );
		DeleteRegion( tess, reg );
		/*    tessMeshDelete( reg->eUp );*/
	}
	dictDeleteDict( &tess->alloc, tess->dict );
}
Пример #3
0
static void DoneEdgeDict( GLUtesselator *tess )
{
  ActiveRegion *reg;
  int fixedEdges = 0;

  /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */
  while( (reg = (ActiveRegion *)dictKey( dictMin( tess->dict ))) != NULL ) {
    /*
     * At the end of all processing, the dictionary should contain
     * only the two sentinel edges, plus at most one "fixable" edge
     * created by ConnectRightVertex().
     */
    if( ! reg->sentinel ) {
      assert( reg->fixUpperEdge );
      assert( ++fixedEdges == 1 );
    }
    assert( reg->windingNumber == 0 );
    DeleteRegion( tess, reg );
/*    __gl_meshDelete( reg->eUp );*/
  }
  dictDeleteDict( tess->dict );	/* __gl_dictListDeleteDict */
}
Пример #4
0
// Parameter phase only for tracing
SimplexResult Tableau::primalSimplex(int phase) {
  const int width           = getWidth();
  const int constraintCount = getConstraintCount();

  for(int r = 1; r <= constraintCount; r++) {
    const TableauRow &row = m_table[r];
    const int bv = row.m_basisVariable;
    const Real &a = row.m_a[bv];
    if(a == 0) {
      continue;
    }
    Real factor = getObjectFactor(bv) / a;
    if(factor == 0) {
      trace(TRACE_WARNINGS,_T("Warning:Cost factor[%s] = 0."), getVariableName(bv).cstr());
      continue;
    }
    for(int col = 0; col <= width; col++) {
      objectFactor(col) -= row.m_a[col] * factor;
    }
    objectFactor(bv) = 0;
  }

  bool looping = false;

  for(int iteration = 1;; iteration++) {
    if(isTracing(TRACE_ITERATIONS)) {
      trace(_T("Phase %d. Iteration %d"), phase, iteration);
      traceTableau();
//      traceBasis(_T("Current basis:"));
    }

    int pivotColumn;
    Real minCost = 1;

    if(looping) {
      for(int col = 1; col <= width; col++) {    // Apply Bland's anti-cycling rule step 1.
        const Real &cc = objectFactor(col);
        if(cc < -EPS) {
          minCost     = cc;
          pivotColumn = col;
          break;
        }
      }
    } else {                                     // else find pivot column the old way
      for(int col = 1; col <= width; col++) {
        const Real &cc = objectFactor(col);
        if(cc < minCost) {
          minCost     = cc;
          pivotColumn = col;
        }
      }
    }

    if(minCost >= -EPS) {
      return SIMPLEX_SOLUTION_OK;                // Optimal value found
    }

    int pivotRow  = -1;
    Real minRatio = 0;
    if(looping) {                                // apply Bland's anti-cycling rule step 2.
      for(int r = 1; r <= constraintCount; r++) {
        const Real &ar = m_table[r].m_a[pivotColumn];
        if(ar > 10*EPS) {
          const Real &br = getRightSide(r);
          const Real ratio = br / ar;
          if((pivotRow == -1) || (ratio < minRatio)) {
            minRatio = ratio;
            pivotRow = r;
          }
        }
      }
      if(pivotRow >= 0) {
        int minIndex = -1;
        for(int r = 1; r <= constraintCount; r++) {
          const Real &ar = m_table[r].m_a[pivotColumn];
          if(ar > 10*EPS) {
            const Real &br = getRightSide(r);
            const Real ratio = br / ar;
            if(ratio == minRatio) {
              const int index = m_table[r].m_basisVariable;
              if(minIndex == -1 || index < minIndex) {
                minIndex = index;
                pivotRow = r;
              }
            }
          }
        }
      }
    } else {                                     // else find pivot row the old way
      for(int r = 1; r <= constraintCount; r++) {
        const Real &ar = m_table[r].m_a[pivotColumn];
        if(ar > EPS) {
          const Real &br = getRightSide(r);
          const Real ratio = br / ar;
          if(pivotRow == -1 || ratio < minRatio) {
            minRatio = ratio;
            pivotRow = r;
          }
        }
      }
    }

    if(pivotRow == -1) {
      return SIMPLEX_SOLUTION_UNLIMITED;
    }

                                                 // Check for degeneracy
    traceDegeneracy(pivotRow, pivotColumn, minRatio);

    DictionaryKey dictKey(this);
    if(m_dictionarySet.contains(dictKey)) {
      looping = true;
      trace(TRACE_WARNINGS, _T("Looping. Applying Blands anti cycling rule."));
    } else {
      m_dictionarySet.add(dictKey);
    }

    pivot(pivotRow,pivotColumn,true);
  }
}
Пример #5
0
static void ConnectLeftVertex( TESStesselator *tess, TESSvertex *vEvent )
/*
* Purpose: connect a "left" vertex (one where both edges go right)
* to the processed portion of the mesh.  Let R be the active region
* containing vEvent, and let U and L be the upper and lower edge
* chains of R.  There are two possibilities:
*
* - the normal case: split R into two regions, by connecting vEvent to
*   the rightmost vertex of U or L lying to the left of the sweep line
*
* - the degenerate case: if vEvent is close enough to U or L, we
*   merge vEvent into that edge chain.  The subcases are:
*	- merging with the rightmost vertex of U or L
*	- merging with the active edge of U or L
*	- merging with an already-processed portion of U or L
*/
{
	ActiveRegion *regUp, *regLo, *reg;
	TESShalfEdge *eUp, *eLo, *eNew;
	ActiveRegion tmp;

	/* assert( vEvent->anEdge->Onext->Onext == vEvent->anEdge ); */

	/* Get a pointer to the active region containing vEvent */
	tmp.eUp = vEvent->anEdge->Sym;
	/* __GL_DICTLISTKEY */ /* tessDictListSearch */
	regUp = (ActiveRegion *)dictKey( dictSearch( tess->dict, &tmp ));
	regLo = RegionBelow( regUp );
	if( !regLo ) {
		// This may happen if the input polygon is coplanar.
		return;
	}
	eUp = regUp->eUp;
	eLo = regLo->eUp;

	/* Try merging with U or L first */
	if( EdgeSign( eUp->Dst, vEvent, eUp->Org ) == 0 ) {
		ConnectLeftDegenerate( tess, regUp, vEvent );
		return;
	}

	/* Connect vEvent to rightmost processed vertex of either chain.
	* e->Dst is the vertex that we will connect to vEvent.
	*/
	reg = VertLeq( eLo->Dst, eUp->Dst ) ? regUp : regLo;

	if( regUp->inside || reg->fixUpperEdge) {
		if( reg == regUp ) {
			eNew = tessMeshConnect( tess->mesh, vEvent->anEdge->Sym, eUp->Lnext );
			if (eNew == NULL) longjmp(tess->env,1);
		} else {
			TESShalfEdge *tempHalfEdge= tessMeshConnect( tess->mesh, eLo->Dnext, vEvent->anEdge);
			if (tempHalfEdge == NULL) longjmp(tess->env,1);

			eNew = tempHalfEdge->Sym;
		}
		if( reg->fixUpperEdge ) {
			if ( !FixUpperEdge( tess, reg, eNew ) ) longjmp(tess->env,1);
		} else {
			ComputeWinding( tess, AddRegionBelow( tess, regUp, eNew ));
		}
		SweepEvent( tess, vEvent );
	} else {
		/* The new vertex is in a region which does not belong to the polygon.
		* We don''t need to connect this vertex to the rest of the mesh.
		*/
		AddRightEdges( tess, regUp, vEvent->anEdge, vEvent->anEdge, NULL, TRUE );
	}
}