// pullTight.C

// John Ringland 
//	8/22/95
//	10/25/95  Updated. Compiled but not tested.
//	1/2/96	  collapseEdge needs some scrutiny!
//	3/7/96    Yep! Initial tests of Homeo show
//		  incorrect behavior in collapsEdge.
//		  theMap.deleteDE is wrong.	 
//		  Fixed call-by-reference problem.
//	4/4/96	  Added directedCollapseEdge.

void Homeo::pullTight()		// public
{

	theFingers.markInvalid();	// Finger update not yet coded.

	Boolean done=0,did1,did2;
	while(!done)
	{	
		while( did1=pullTight_type1() )
		{
			// Pulling tight can cause an image to
			// become empty. An edge with empty image
			// will be collapsed.
//cout << "Pull tight, type 1: collapsing any edges with empty image" << endl;
//cout << (*this) << endl;
			collapseEdgesWithEmptyImage();
//cout << (*this) << endl;
		}

		while( did2=pullTight_type2() )
		{	
//cout << "Pull tight, type 2" << endl;
			collapseEdgesWithEmptyImage();
		}

		done = (!did1) && (!did2);
	}
//cout << "Leaving pullTight()" << endl;
}


Boolean Homeo::pullTight_type1()	// private
{
		// This is where there is a vertex of the graph
		// for which the derivative of every edge in the
		// link is the same as all the others.
		// We remove that common derivative from each image.

		// First, find a vertex with Dg(E_i) same for all i.

//cout << "Entered pullTight_type1()" << endl;

	SetIterator<Vertex> iv(theGraph);
	for( iv.init();  iv.ok(); iv.advance() )
	{	
//cout << "   Checking vertex " << iv.current() << endl;
		assert( iv.current().length() != 0 );
		CircListIterator<DE> ie(iv.current());
		ie.init(); 
		DE der( theMap.derivative(ie.ahead()) );
		Boolean derivIsConstant=1;
		for( ++ie ; ie.ok(); ++ie )
		{
			if( theMap.derivative(ie.ahead()) != der )
			{
				derivIsConstant = 0;
				break;
			}
		}
		if( derivIsConstant ) 
		{
//cout << "      Derivative of all edges of " << iv.current() 
//		<< "is " << der << endl;
cout << "  Tightening at vertex " << iv.current() << 
	", (all derivatives are " << der << ")." << endl;
			for( ie.init(); ie.ok(); ++ie)
			{
				theMap.popDg(ie.ahead());
			}
//cout << " Leaving pullTight_type1(). New map " << endl << theMap << endl;
			return 1;
		}
	}
cout << "  There is no vertex with constant derivative." << endl;
	return 0;	// No vertex with constant derivative.
}

Boolean Homeo::pullTight_type2()	// private
{
		// This is where the image of an edge contains
		// an "e ebar" for some DE e.
		// We remove the backtrack from the image.

//cout << "pullTight_type2() (deleteAllBacktracking)" << endl;
	Boolean didSomething=theMap.deleteAllBacktracking();
	if(didSomething) return 1;
//cout << "Nothing to do." << endl;
	return 0;
}


Boolean Homeo::collapseEdgesWithEmptyImage()
{
//cout << "Entered collapseEdgesWithEmptyImage()" << endl;
	Boolean didSomething=0;
	SetIterator<MapElement> i(theMap);
	for(i.init();i.ok();)
	{
//cout << "   Looking at image " << i.current().image() << endl;
		if(i.current().image().length()==0)
		{
//cout << "Edge " << i.current().source() << " has empty image" << endl;
			collapseEdge(i.current().source());
//cout << (*this) << endl;
			didSomething=1;
			i.init();
		}
		else   i.advance();
	}
	return didSomething;	
}

void Homeo::collapseEdge(DE e)
{
				// Warning. It is assumed that appropriate
				// steps have been taken to deal with the
				// image of edge e, since it will be
				// discarded by this function!

	theEquator.evacuateEdge(e,theGraph);
 
	theMap.deleteDE(e);

	theGraph.mergeAlong(e);

	theNameManager.removeEdge(e.name());
}

void Homeo::directedCollapseEdge(DE e)
{
				// Warning. It is assumed that appropriate
				// steps have been taken to deal with the
				// image of edge e, since it will be
				// discarded by this function!

	theEquator.evacuateEdgeThruTerminus(e,theGraph);
 
	theMap.deleteDE(e);

	theGraph.mergeAlong(e);

	theNameManager.removeEdge(e.name());
}









