Esempio n. 1
0
void VisibilityLayout::constructVisibilityRepresentation(UpwardPlanRep &UPR)
{
	constructDualGraph(UPR);
	//makeSimple(D);
	//if (t_D->degree() <= 1)
	//	D.newEdge(s_D, t_D); // make biconnected


	//OGDF_ASSERT(isSimple(UPR));
	//OGDF_ASSERT(isBiconnected(UPR));
	//OGDF_ASSERT(isSimple(D));
	//OGDF_ASSERT(isBiconnected(D));

	//compute top. numbering
	NodeArray<int> topNumberUPR(UPR);
	NodeArray<int> topNumberD(D);

	topologicalNumbering(UPR, topNumberUPR);
	topologicalNumbering(D, topNumberD);

	nodeToVis.init(UPR);
	edgeToVis.init(UPR);

	for(node v : UPR.nodes) {
		NodeSegment vVis;

		//cout << "node : " << v << " stNum: " << topNumberUPR[v] << endl;

		if (v == UPR.getSuperSource() || v == UPR.getSuperSink()) {
			vVis.y = topNumberUPR[v];
			vVis.x_l = topNumberD[s_D];
			vVis.x_r = topNumberD[t_D]-1;
			nodeToVis[v] =vVis;
			continue;
		}

		vVis.y = topNumberUPR[v];
		face f_v = leftFace_node[v];
		node vD = faceToNode[f_v];
		vVis.x_l = topNumberD[vD];
		f_v = rightFace_node[v];
		vD = faceToNode[f_v];
		vVis.x_r = topNumberD[vD]-1;
		nodeToVis[v] =vVis;
	}

	for(edge e : UPR.edges) {
		EdgeSegment eVis;
		face f_v = leftFace_edge[e];
		node vD = faceToNode[f_v];
		eVis.x = topNumberD[vD];
		eVis.y_b = topNumberUPR[e->source()];
		eVis.y_t = topNumberUPR[e->target()];
		edgeToVis[e] = eVis;
	}
}
Esempio n. 2
0
void VisibilityLayout::call(GraphAttributes &GA)
{
	if (GA.constGraph().numberOfNodes() <= 1)
		return;

	//call upward planarizer
	UpwardPlanRep UPR;
	UPR.createEmpty(GA.constGraph());
	m_upPlanarizer.get().call(UPR);
	layout(GA, UPR);
}
Esempio n. 3
0
void DominanceLayout::call(GraphAttributes &GA)
{
	if (GA.constGraph().numberOfNodes() <= 1)
		return;

	OGDF_ASSERT(isSimpleUndirected(GA.constGraph()));
	//call upward planarizer
	UpwardPlanRep UPR;
	UPR.createEmpty(GA.constGraph());
	m_upPlanarizer->call(UPR);
	layout(GA, UPR);
}
Esempio n. 4
0
void UPRSupplier::supply(Graph& graph, UpwardPlanRep& retVal){
	node addedSource = graph.newNode();
	node addedSink = graph.newNode();
	if (outputDebug){
		cout << "\tAdded super source (" << addedSource->index() << ") and super sink (" << addedSink->index() << ")." << endl;
		cout << endl;
	}
	
	vector<edge> addedEdges;
	node n;
	forall_nodes(n, graph){
		if (n->indeg() == 0 && n != addedSource && n != addedSink) {
			edge e = graph.newEdge(addedSource, n);
			addedEdges.push_back(e);
		}
	}
	
	forall_nodes(n, graph){
		if (n->outdeg() == 0 && n != addedSource && n != addedSink) {
			edge e = graph.newEdge(n, addedSink);
			addedEdges.push_back(e);
		}
	}
	
	retVal.createEmpty(graph);
	assert(&retVal.original() == &graph);
	
	EdgeArray<int> cost (graph, this->normalCost);
	if (outputDebug)
		cout << "\tAssigning cost " << this->normalCost << " as default cost per edge" << endl;
	EdgeArray<bool> forbid (graph, false);
	
	for (vector<edge>::iterator it = addedEdges.begin(); it != addedEdges.end(); ++it){
		cost[*it] = this->sourceSinkCost;
		if (outputDebug)
			cout << "\tAssigning cost " << cost[*it] << " to " << *it << endl;
	}
	
	if (outputDebug)
		cout << endl;	
	
	SubgraphUpwardPlanarizer sup;
	FUPSSourceSink* fups = new FUPSSourceSink();
	
	fups->runs(this->runs);
	sup.setSubgraph(fups);
	
	sup.setInserter(new OutputUpwardEdgeInserter());
	
	sup.runs(this->runs);
	sup.call(retVal, &cost, &forbid);
}
Esempio n. 5
0
void UPRSupplier::revertUPR(UpwardPlanRep& upr, GraphAttributes& uga){
	upr.delNode(getSource(upr));
	upr.delNode(getSink(upr));
	upr.delNode(getSink(upr));
	node source = getSource(upr);
	node sink = getSink(upr);
	
	vector<edge> edgesToDelete;
	edge e;
	forall_edges(e, upr){
		if (upr.original(e)->source() == upr.original(source) || upr.original(e)->target() == upr.original(sink))
			edgesToDelete.push_back(e);
	}

	for (vector<edge>::iterator it = edgesToDelete.begin(); it != edgesToDelete.end(); ++it){
		upr.delEdge(*it);
	}
	upr.delNode(source);
	upr.delNode(sink);
	
	vector<node> nodesToUnsplit;
	node n;
	forall_nodes(n, upr){
		if (n->indeg() == 1 && n->outdeg() == 1 && upr.isDummy(n)){
			nodesToUnsplit.push_back(n);
		}
	}
	
	for (vector<node>::iterator it = nodesToUnsplit.begin(); it != nodesToUnsplit.end(); ++it){
		edge in = (*it)->firstAdj()->theEdge();
		edge out = (*it)->lastAdj()->theEdge();
		if (in->source() == *it)
			swap(in, out);
		DPolyline& inBends = uga.bends(in);
		DPolyline& outBends = uga.bends(out);
		inBends.popBack();
		double x = inBends.back().m_x;
		int counter = 0;
		for (ListIterator<DPoint> it = outBends.begin(); it != outBends.end(); ++it){
			if (counter < 2){
				DPoint p(x, (*it).m_y);
				inBends.pushBack(p);
				counter++;
			} else {
				inBends.pushBack(*it);
			}
		}
		upr.unsplit(in, out);
	}
	
}
Esempio n. 6
0
void DominanceLayout::findTransitiveEdges(const UpwardPlanRep &UPR, List<edge> &edges)
{
	// for st-graphs:
	// e = (u,v) transitive <=> ex. face f: e in f and u source-switch and v = sink-switch
	for(face f : UPR.getEmbedding().faces) {
		if (f == UPR.getEmbedding().externalFace())
			continue;

		for(adjEntry adj : f->entries)
		{
			node src = adj->theEdge()->source();
			node tgt = adj->theEdge()->target();
			if ( (adj->faceCycleSucc()->theEdge()->source() == src && adj->faceCyclePred()->theEdge()->target() == tgt)
				|| (adj->faceCycleSucc()->theEdge()->target() == tgt && adj->faceCyclePred()->theEdge()->source() == src))
			{
					edges.pushBack(adj->theEdge());
					break;
			}
		}
	}
}
Esempio n. 7
0
void DominanceLayout::labelY(const UpwardPlanRep &UPR, node v, int &count)
{
	yNodes.pushBack(v);
	yPreCoord[v] = count;
	count++;
	if (v != UPR.getSuperSink()) {
		adjEntry adj = lastout[v]->adjSource();
		do {
			node w = adj->theEdge()->target();
			if (adj->theEdge() == firstin[w])
				labelY(UPR, w, count);
			adj = adj->cyclicPred();
		} while (adj->cyclicSucc()->theEdge() != firstout[v]);
	}
}
Module::ReturnType OutputUpwardEdgeInserter::insertAll(UpwardPlanRep &UPR,
														List<edge> &toInsert,		
														EdgeArray<int>  &costOrig)
{
	if (toInsert.empty())
		return Module::retFeasible;

	List<edge> l;
	int size_new = toInsert.size();
	int size_old = 0;
	while (size_old != size_new) {
		size_old = size_new;
		while (!toInsert.empty()) {
			edge e_orig = toInsert.popFrontRet();
			SList<adjEntry> path;
			
			/*
			//debug
			cout << endl;
			cout << "  insertion path for e_orig :" << e_orig << ";  e_UPR: (" << UPR.copy(e_orig->source()) << "," 
				 << UPR.copy(e_orig->target()) << ")" << endl;
			*/

			minFIP(UPR, toInsert, costOrig, e_orig, path);						

			
			/*
			//--------------------------------------debug					
			forall_slistiterators(adjEntry, it, path) {
				cout << (*it)->theEdge() << ";  node: " << (*it)->theNode() << endl;
			}
			//--------------------------------------end debug
			*/
			
			List<edge> lEdges = toInsert, lTmp = l;
			lEdges.conc(lTmp);
			bool ok = isConstraintFeasible(UPR, lEdges, e_orig, path);						
			if (ok) {
				UPR.insertEdgePathEmbedded(e_orig, path, costOrig);				
				
				OGDF_ASSERT(isUpwardPlanar(UPR));			
				OGDF_ASSERT(isSimple(UPR));
				OGDF_ASSERT(isConnected(UPR));
				OGDF_ASSERT(hasSingleSource(UPR));

			}
			else 
				l.pushBack(e_orig);
			
			/*
			if (false) {
			//---------------------------------------------------debug		
			//UPR.outputFaces(UPR.getEmbedding());
			//UPR.writeGML("c:/temp/bug5.gml");

			LayerBasedUPRLayout uprLayout;
			Graph GTmp( (const Graph &) UPR);
			CombinatorialEmbedding embTmp(GTmp);
			node tTmp = 0;
			//GTmp.writeGML("c:/temp/bug4.gml");
			hasSingleSink(GTmp, tTmp);
			OGDF_ASSERT(tTmp != 0);
			embTmp.setExternalFace(embTmp.rightFace(tTmp->firstAdj()));
			//adjEntry adjTmp = GCTmp.copy(UPR.extFaceHandle->theEdge())->adjTarget();
			UpwardPlanRep upr_bug(embTmp);
			adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace());
			node s_upr_bug = upr_bug.newNode();
			upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug);
			upr_bug.m_isSourceArc.init(upr_bug, false);
			upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true;
			upr_bug.s_hat = s_upr_bug;
			upr_bug.augment();
		
			GraphAttributes GA_UPR_tmp(GTmp, GraphAttributes::nodeGraphics|
					GraphAttributes::edgeGraphics|
					GraphAttributes::nodeColor|
					GraphAttributes::edgeColor|
					GraphAttributes::nodeLabel|
					GraphAttributes::edgeLabel
					);
			GA_UPR_tmp.setAllHeight(30.0);
			GA_UPR_tmp.setAllWidth(30.0);	

			uprLayout.call(upr_bug, GA_UPR_tmp);				
			
			// label the nodes with their index
			node z;
			forall_nodes(z, GA_UPR_tmp.constGraph()) {			
				char str[255];
				sprintf_s(str, 255, "%d", z->index()); 	// convert to string	
				GA_UPR_tmp.labelNode(z) = str;		
				GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z);
				GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z);				
			}
			edge eee;
			forall_edges(eee, GA_UPR_tmp.constGraph()) {
				DPolyline &line = GA_UPR_tmp.bends(eee);
				ListIterator<DPoint> it;
				for(it = line.begin(); it.valid(); it++) {		
					(*it).m_y = -(*it).m_y;	
					(*it).m_x = -(*it).m_x;
				}
			}
			GA_UPR_tmp.writeGML("c:/temp/UPR_int.gml");	
			//cout << "face of UPR_int :" << endl;
			//upr_bug.outputFaces(upr_bug.getEmbedding());
			//end -----------------------------------------------debug
			}
			*/

		}
		size_new = l.size();
		toInsert = l;
		l.clear();
	}
	
	/*
	 * some edges cannot be inserted, so use heuristic insertion methods
	 */
	if (!toInsert.empty()) {

		//cout << endl << "\a\a\a\a\aheuristical call!! " << endl;

		edge e_orig = toInsert.popFrontRet();

		/*
		cout << endl;
		cout << "heuristical insertion path for e_orig :" << e_orig << ";  e_UPR: (" << UPR.copy(e_orig->source()) << "," 
			<< UPR.copy(e_orig->target()) << ")" <<  endl;
		*/

		
			/*
			if (false) {
			//---------------------------------------------------debug		
			//UPR.outputFaces(UPR.getEmbedding());
			//UPR.writeGML("c:/temp/bug5.gml");

			LayerBasedUPRLayout uprLayout;
			Graph GTmp( (const Graph &) UPR);
			CombinatorialEmbedding embTmp(GTmp);
			node tTmp = 0;
			//GTmp.writeGML("c:/temp/bug4.gml");
			hasSingleSink(GTmp, tTmp);
			OGDF_ASSERT(tTmp != 0);
			embTmp.setExternalFace(embTmp.rightFace(tTmp->firstAdj()));
			//adjEntry adjTmp = GCTmp.copy(UPR.extFaceHandle->theEdge())->adjTarget();
			UpwardPlanRep upr_bug(embTmp);
			adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace());
			node s_upr_bug = upr_bug.newNode();
			upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug);
			upr_bug.m_isSourceArc.init(upr_bug, false);
			upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true;
			upr_bug.s_hat = s_upr_bug;
			upr_bug.augment();
		
			GraphAttributes GA_UPR_tmp(GTmp, GraphAttributes::nodeGraphics|
					GraphAttributes::edgeGraphics|
					GraphAttributes::nodeColor|
					GraphAttributes::edgeColor|
					GraphAttributes::nodeLabel|
					GraphAttributes::edgeLabel
					);
			GA_UPR_tmp.setAllHeight(30.0);
			GA_UPR_tmp.setAllWidth(30.0);	

			uprLayout.call(upr_bug, GA_UPR_tmp);				
			
			// label the nodes with their index
			node z;
			forall_nodes(z, GA_UPR_tmp.constGraph()) {			
				char str[255];
				sprintf_s(str, 255, "%d", z->index()); 	// convert to string	
				GA_UPR_tmp.labelNode(z) = str;		
				GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z);
				GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z);				
			}
			edge eee;
			forall_edges(eee, GA_UPR_tmp.constGraph()) {
				DPolyline &line = GA_UPR_tmp.bends(eee);
				ListIterator<DPoint> it;
				for(it = line.begin(); it.valid(); it++) {		
					(*it).m_y = -(*it).m_y;	
					(*it).m_x = -(*it).m_x;
				}
			}
			GA_UPR_tmp.writeGML("c:/temp/UPR_int.gml");	
			//cout << "face of UPR_int :" << endl;
			//upr_bug.outputFaces(upr_bug.getEmbedding());
			//end -----------------------------------------------debug
			}
			*/		

		SList<adjEntry> path;
		constraintFIP(UPR, toInsert, costOrig, e_orig, path);	

		/*
		//--------------------------------------debug
		
		forall_slistiterators(adjEntry, it, path) {
			cout << (*it)->theEdge() << ";  node: " << (*it)->theNode() << endl;; 
		}
		//--------------------------------------end debug
		*/

		UPR.insertEdgePathEmbedded(e_orig, path, costOrig);		
		
		OGDF_ASSERT(isUpwardPlanar(UPR));

		return insertAll(UPR, toInsert, costOrig);
	}	
	return Module::retFeasible;
}
Esempio n. 9
0
void FUPSSimple::computeFUPS(UpwardPlanRep &UPR, List<edge> &delEdges)
{
	const Graph &G = UPR.original();
	GraphCopy FUPS(G);
	node s_orig;
	hasSingleSource(G, s_orig);
	List<edge> nonTreeEdges_orig;
	bool random = (m_nRuns != 0);

	getSpanTree(FUPS, nonTreeEdges_orig, random);

	CombinatorialEmbedding Gamma(FUPS);

	if (random)
		nonTreeEdges_orig.permute(); // random order

	adjEntry extFaceHandle = nullptr;

	//insert nonTreeEdges
	while (!nonTreeEdges_orig.empty()) {

	/*
	//------------------------------------debug
	GraphAttributes AG(FUPS, GraphAttributes::nodeGraphics|
						GraphAttributes::edgeGraphics|
						GraphAttributes::nodeColor|
						GraphAttributes::edgeColor|
						GraphAttributes::nodeLabel|
						GraphAttributes::edgeLabel
						);
	// label the nodes with their index
	for(node v : AG.constGraph().nodes) {
		AG.label(v) = to_string(v->index());
	}
	AG.writeGML("c:/temp/spannTree.gml");
	*/

		// make identical copy FUPSCopy of FUPS
		//and insert e_orig in FUPSCopy
		GraphCopy FUPSCopy((const GraphCopy &) FUPS);
		edge e_orig = nonTreeEdges_orig.popFrontRet();
		FUPSCopy.newEdge(e_orig);

		if (UpwardPlanarity::upwardPlanarEmbed_singleSource(FUPSCopy)) { //upward embedded the fups and check feasibility
			CombinatorialEmbedding Beta(FUPSCopy);

			//choose a arbitrary feasibel ext. face
			FaceSinkGraph fsg(Beta, FUPSCopy.copy(s_orig));
			SList<face> ext_faces;
			fsg.possibleExternalFaces(ext_faces);

			OGDF_ASSERT(!ext_faces.empty());

			Beta.setExternalFace(ext_faces.front());


#if 0
			//*************************** debug ********************************
			cout << endl << "FUPS : " << endl;
			for(face ff : Beta.faces) {
				cout << "face " << ff->index() << ": ";
				adjEntry adjNext = ff->firstAdj();
				do {
					cout << adjNext->theEdge() << "; ";
					adjNext = adjNext->faceCycleSucc();
				} while(adjNext != ff->firstAdj());
				cout << endl;
			}
			if (Beta.externalFace() != 0)
				cout << "ext. face of the graph is: " << Beta.externalFace()->index() << endl;
			else
				cout << "no ext. face set." << endl;
#endif

			GraphCopy M((const GraphCopy &) FUPSCopy); // use a identical copy of FUPSCopy to construct the merge graph of FUPSCopy
			adjEntry extFaceHandle_cur = getAdjEntry(Beta, FUPSCopy.copy(s_orig), Beta.externalFace());
			adjEntry adj_orig = FUPSCopy.original(extFaceHandle_cur->theEdge())->adjSource();

			List<edge> missingEdges = nonTreeEdges_orig, listTmp = delEdges;
			missingEdges.conc(listTmp);
			if (constructMergeGraph(M, adj_orig, missingEdges)) {
				FUPS = FUPSCopy;
				extFaceHandle = FUPS.copy(FUPSCopy.original(extFaceHandle_cur->theEdge()))->adjSource();
				continue;
			}
			else {
				//Beta is not feasible
				delEdges.pushBack(e_orig);
			}
		}
		else {
			// not ok, GC is not feasible
			delEdges.pushBack(e_orig);
		}
	}
	UpwardPlanRep fups_tmp (FUPS, extFaceHandle);
	UPR = fups_tmp;
}
Esempio n. 10
0
Module::ReturnType SubgraphUpwardPlanarizer::doCall(UpwardPlanRep &UPR,
		const EdgeArray<int>  &cost,
		const EdgeArray<bool> &forbid)
{
	const Graph &G = UPR.original();
	GraphCopy GC(G);

	//reverse some edges in order to obtain a DAG
	List<edge> feedBackArcSet;
	m_acyclicMod.get().call(GC, feedBackArcSet);
	for(edge e : feedBackArcSet) {
		GC.reverseEdge(e);
	}

	OGDF_ASSERT(isSimple(G));

	//mapping cost
	EdgeArray<int> cost_GC(GC);
	for(edge e : GC.edges) {
		if (forbid[GC.original(e)])
			cost_GC[e] = numeric_limits<int>::max();
		else
			cost_GC[e] = cost[GC.original(e)];
	}

	// tranform to single source graph by adding a super source s_hat and connect it with the other sources
	EdgeArray<bool> sourceArcs(GC, false);
	node s_hat = GC.newNode();
	for(node v : GC.nodes) {
		if (v->indeg() == 0 && v != s_hat) {
			edge e_tmp = GC.newEdge(s_hat, v);
			cost_GC[e_tmp] = 0; // crossings source arcs cause not cost
			sourceArcs[e_tmp] = true;
		}
	}


	/*
	//------------------------------------------------debug
	GraphAttributes AG_GC(GC, GraphAttributes::nodeGraphics|
						GraphAttributes::edgeGraphics|
						GraphAttributes::nodeColor|
						GraphAttributes::edgeColor|
						GraphAttributes::nodeLabel|
						GraphAttributes::edgeLabel
						);
	AG_GC.setAllHeight(30.0);
	AG_GC.setAllWidth(30.0);
	for(node z : AG_GC.constGraph().nodes) {
		AG_GC.label(z) = to_string(z->index());
	}
	AG_GC.writeGML("c:/temp/GC.gml");
	// --------------------------------------------end debug
	*/

	BCTree BC(GC);
	const Graph &bcTree = BC.bcTree();

	GraphCopy G_dummy;
	G_dummy.createEmpty(G);
	NodeArray<GraphCopy> biComps(bcTree, G_dummy); // bicomps of G; init with an empty graph
	UpwardPlanRep UPR_dummy;
	UPR_dummy.createEmpty(G);
	NodeArray<UpwardPlanRep> uprs(bcTree, UPR_dummy); // the upward planarized representation of the bicomps; init with an empty UpwarPlanRep

	constructComponentGraphs(BC, biComps);

	for(node v : bcTree.nodes) {

		if (BC.typeOfBNode(v) == BCTree::CComp)
			continue;

		GraphCopy &block = biComps[v];

		OGDF_ASSERT(m_subgraph.valid());

		// construct a super source for this block
		node s, s_block;
		hasSingleSource(block, s);
		s_block = block.newNode();
		block.newEdge(s_block, s); //connect s

		UpwardPlanRep bestUPR;

		//upward planarize if not upward planar
		if (!UpwardPlanarity::upwardPlanarEmbed_singleSource(block)) {

			for (int i = 0; i < m_runs; i++) {// i multistarts
				UpwardPlanRep UPR_tmp;
				UPR_tmp.createEmpty(block);
				List<edge> delEdges;

				m_subgraph.get().call(UPR_tmp, delEdges);

				OGDF_ASSERT( isSimple(UPR_tmp) );
				UPR_tmp.augment();

				//mark the source arcs of block
				UPR_tmp.m_isSourceArc[UPR_tmp.copy(s_block->firstAdj()->theEdge())] = true;
				for (adjEntry adj_tmp : UPR_tmp.copy(s_block->firstAdj()->theEdge()->target())->adjEntries) {
					edge e_tmp = UPR_tmp.original(adj_tmp->theEdge());
					if (e_tmp != nullptr && block.original(e_tmp) != nullptr && sourceArcs[block.original(e_tmp)])
						UPR_tmp.m_isSourceArc[adj_tmp->theEdge()] = true;
				}

				//assign "crossing cost"
				EdgeArray<int> cost_Block(block);
				for (edge e : block.edges) {
					if (block.original(e) == nullptr || GC.original(block.original(e)) == nullptr)
						cost_Block[e] = 0;
					else
						cost_Block[e] = cost_GC[block.original(e)];
				}

				/*
				if (false) {
					//---------------------------------------------------debug
					LayerBasedUPRLayout uprLayout;
					UpwardPlanRep upr_bug(UPR_tmp.getEmbedding());
					adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace());
					node s_upr_bug = upr_bug.newNode();
					upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug);
					upr_bug.m_isSourceArc.init(upr_bug, false);
					upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true;
					upr_bug.s_hat = s_upr_bug;
					upr_bug.augment();

					GraphAttributes GA_UPR_tmp(UPR_tmp, GraphAttributes::nodeGraphics|
							GraphAttributes::edgeGraphics|
							GraphAttributes::nodeColor|
							GraphAttributes::edgeColor|
							GraphAttributes::nodeLabel|
							GraphAttributes::edgeLabel
							);
					GA_UPR_tmp.setAllHeight(30.0);
					GA_UPR_tmp.setAllWidth(30.0);

					uprLayout.call(upr_bug, GA_UPR_tmp);

					// label the nodes with their index
					for(node z : GA_UPR_tmp.constGraph().nodes) {
						GA_UPR_tmp.label(z) = to_string(z->index());
						GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z);
						GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z);
					}
					for(edge eee : GA_UPR_tmp.constGraph().edges) {
						DPolyline &line = GA_UPR_tmp.bends(eee);
						ListIterator<DPoint> it;
						for(it = line.begin(); it.valid(); it++) {
							(*it).m_y = -(*it).m_y;
							(*it).m_x = -(*it).m_x;
						}
					}
					GA_UPR_tmp.writeGML("c:/temp/UPR_tmp_fups.gml");
					cout << "UPR_tmp/fups faces:";
					UPR_tmp.outputFaces(UPR_tmp.getEmbedding());
					//end -----------------------------------------------debug
				}
				*/

				delEdges.permute();
				m_inserter.get().call(UPR_tmp, cost_Block, delEdges);

				if (i != 0) {
					if (UPR_tmp.numberOfCrossings() < bestUPR.numberOfCrossings()) {
						//cout << endl << "new cr_nr:" << UPR_tmp.numberOfCrossings() << " old  cr_nr : " << bestUPR.numberOfCrossings() << endl;
						bestUPR = UPR_tmp;
					}
				}
				else
					bestUPR = UPR_tmp;
			}//for
		}
		else { //block is upward planar
			CombinatorialEmbedding Gamma(block);
			FaceSinkGraph fsg((const CombinatorialEmbedding &) Gamma, s_block);
			SList<face> faceList;
			fsg.possibleExternalFaces(faceList);
			Gamma.setExternalFace(faceList.front());

			UpwardPlanRep UPR_tmp(Gamma);
			UPR_tmp.augment();

			//mark the source arcs of  block
			UPR_tmp.m_isSourceArc[UPR_tmp.copy(s->firstAdj()->theEdge())] = true;
			for (adjEntry adj_tmp : UPR_tmp.copy(s->firstAdj()->theEdge()->target())->adjEntries) {
				edge e_tmp = UPR_tmp.original(adj_tmp->theEdge());
				if (e_tmp != nullptr && block.original(e_tmp) != nullptr && sourceArcs[block.original(e_tmp)])
					UPR_tmp.m_isSourceArc[adj_tmp->theEdge()] = true;
			}

			bestUPR = UPR_tmp;

			/*
			//debug
			//---------------------------------------------------debug
			GraphAttributes GA_UPR_tmp(UPR_tmp, GraphAttributes::nodeGraphics|
					GraphAttributes::edgeGraphics|
					GraphAttributes::nodeColor|
					GraphAttributes::edgeColor|
					GraphAttributes::nodeLabel|
					GraphAttributes::edgeLabel
					);
			GA_UPR_tmp.setAllHeight(30.0);
			GA_UPR_tmp.setAllWidth(30.0);

			// label the nodes with their index
			for(node z : GA_UPR_tmp.constGraph().nodes) {
				GA_UPR_tmp.label(z) = to_string(z->index());
				GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z);
				GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z);
			}
			for(edge eee : GA_UPR_tmp.constGraph().edges) {
				DPolyline &line = GA_UPR_tmp.bends(eee);
				ListIterator<DPoint> it;
				for(it = line.begin(); it.valid(); it++) {
					(*it).m_y = -(*it).m_y;
					(*it).m_x = -(*it).m_x;
				}
			}
			GA_UPR_tmp.writeGML("c:/temp/UPR_tmp_fups.gml");
			cout << "UPR_tmp/fups faces:";
			UPR_tmp.outputFaces(UPR_tmp.getEmbedding());
			//end -----------------------------------------------debug
			*/

		}
		uprs[v] = bestUPR;
	}

	// compute the number of crossings
	int nr_cr = 0;
	for(node v : bcTree.nodes) {
		if (BC.typeOfBNode(v) != BCTree::CComp)
			nr_cr = nr_cr + uprs[v].numberOfCrossings();
	}

	//merge all component to a graph
	node parent_BC = BC.bcproper(s_hat);
	NodeArray<bool> nodesDone(bcTree, false);
	dfsMerge(GC, BC, biComps, uprs, UPR, nullptr, parent_BC, nodesDone); // start with the component which contains the super source s_hat

	//augment to single sink graph
	UPR.augment();

	//set crossings
	UPR.crossings = nr_cr;


	//------------------------------------------------debug
	/*
	LayerBasedUPRLayout uprLayout;
	UpwardPlanRep upr_bug(UPR.getEmbedding());
	adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace());
	node s_upr_bug = upr_bug.newNode();
	upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug);
	upr_bug.m_isSourceArc.init(upr_bug, false);
	upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true;
	upr_bug.s_hat = s_upr_bug;
	upr_bug.augment();
	GraphAttributes AG(UPR, GraphAttributes::nodeGraphics|
						GraphAttributes::edgeGraphics|
						GraphAttributes::nodeColor|
						GraphAttributes::edgeColor|
						GraphAttributes::nodeLabel|
						GraphAttributes::edgeLabel
						);
	AG.setAllHeight(30.0);
	AG.setAllWidth(30.0);

	uprLayout.call(upr_bug, AG);

	for(node v : AG.constGraph().nodes) {
		int idx;
		idx = v->index();


		if (UPR.original(v) != 0)
			idx = UPR.original(v)->index();


		AG.label(v) = to_string(idx);
		if (UPR.isDummy(v))
			AG.fillColor(v) = "#ff0000";
		AG.y(v)=-AG.y(v);
	}
	// label the edges with their index
	for(edge e : AG.constGraph().edges) {
		AG.label(e) = to_string(e->index());
		if (UPR.isSourceArc(e))
			AG.strokeColor(e) = "#00ff00";
		if (UPR.isSinkArc(e))
			AG.strokeColor(e) = "#ff0000";

		DPolyline &line = AG.bends(e);
		ListIterator<DPoint> it;
		for(it = line.begin(); it.valid(); it++) {
			(*it).m_y = -(*it).m_y;
		}
	}
	AG.writeGML("c:/temp/upr_res.gml");
	//cout << "UPR_RES";
	//UPR.outputFaces(UPR.getEmbedding());
	//cout << "Mapping :" << endl;
	//for(node v : UPR.nodes) {
	//	if (UPR.original(v) != 0) {
	//		cout << "node UPR  " << v << "   node G  " << UPR.original(v) << endl;
	//	}
	//}
	// --------------------------------------------end debug
	*/

	OGDF_ASSERT(hasSingleSource(UPR));
	OGDF_ASSERT(isSimple(UPR));
	OGDF_ASSERT(isAcyclic(UPR));
	OGDF_ASSERT(UpwardPlanarity::isUpwardPlanar_singleSource(UPR));

/*
	for(edge eee : UPR.original().edges) {
		if (UPR.isReversed(eee))
			cout << endl << eee << endl;
	}
*/
	return Module::retFeasible;
}
Esempio n. 11
0
void SubgraphUpwardPlanarizer::merge(
	const GraphCopy &GC,
	UpwardPlanRep &UPR_res,
	const GraphCopy &block,
	UpwardPlanRep &UPR)
{
	node startUPR = UPR.getSuperSource()->firstAdj()->theEdge()->target();
	node startRes;

	node startG = GC.original(block.original(UPR.original(startUPR)));

	bool empty = UPR_res.empty();

	if (empty) {

		OGDF_ASSERT(startG == 0);

		// contruct a node in UPR_res assocciated with startUPR
		startRes = UPR_res.newNode();
		UPR_res.m_isSinkArc.init(UPR_res, false);
		UPR_res.m_isSourceArc.init(UPR_res, false);
		UPR_res.s_hat = startRes;
	}
	else {
		startRes = UPR_res.copy(startG);
	}

	OGDF_ASSERT(startRes != 0);

	// compute the adjEntry position (in UPR_res) of the cutvertex startRes
	adjEntry pos = nullptr;
	if (!empty) {
		adjEntry adj_ext = nullptr, adj_int = nullptr;
		for(adjEntry run : startRes->adjEntries) {
			if (UPR_res.getEmbedding().rightFace(run) == UPR_res.getEmbedding().externalFace()) {
				adj_ext = run;
				break;
			}
			if (run->theEdge()->source() == startRes)
				adj_int = run;
		}
		// cutvertex is a sink in UPR_res
		if (adj_ext == nullptr && adj_int == nullptr) {
			pos = UPR_res.sinkSwitchOf(startRes);
		}
		else {
			if (adj_ext == nullptr)
				pos = adj_int;
			else
				pos = adj_ext;
		}
		OGDF_ASSERT(pos != 0);
	}

	// construct for each node (except the two super sink and the super source) of UPR a associated of UPR to UPR_res
	NodeArray<node> nodeUPR2UPR_res(UPR, nullptr);
	nodeUPR2UPR_res[startUPR] = startRes;
	for(node v : UPR.nodes) {

		// allready constructed or is super sink or super source
		if (v == startUPR || v == UPR.getSuperSink() || v == UPR.getSuperSink()->firstAdj()->theEdge()->source() || v == UPR.getSuperSource())
			continue;

		node vNew;
		if (UPR.original(v) != nullptr ) {
			node vG = GC.original(block.original((UPR.original(v))));
			if (vG != nullptr)
				vNew = UPR_res.newNode(vG);
			else
				vNew = UPR_res.newNode(); //vG is the super source
		}
		else // crossing dummy, no original node
			vNew = UPR_res.newNode();
		nodeUPR2UPR_res[v] = vNew;
	}

	//add edges of UPR to UPR_res
	EdgeArray<edge> edgeUPR2UPR_res(UPR, nullptr);
	for(edge e : block.edges) {

		if (e->source()->indeg()==0) // the artificial edge with the super source
			continue;

		List<edge> chains = UPR.chain(e);
		edge eG = nullptr, eGC = block.original(e);
		eG = GC.original(eGC);

		OGDF_ASSERT(!chains.empty());

		//construct new edges in UPR_res
		for(edge eChain : chains) {
			node tgt = nodeUPR2UPR_res[eChain->target()];
			node src = nodeUPR2UPR_res[eChain->source()];
			edge eNew = UPR_res.newEdge(src, tgt);
			edgeUPR2UPR_res[eChain] = eNew;

			if (UPR.isSinkArc(UPR.copy(e)))
				UPR_res.m_isSinkArc[eNew] = true;
			if (UPR.isSourceArc(UPR.copy(e)))
				UPR_res.m_isSourceArc[eNew] = true;

			if (eG == nullptr) { // edge is associated with a sink arc
				UPR_res.m_eOrig[eNew] = nullptr;
				continue;
			}

			UPR_res.m_eOrig[eNew] = eG;
			if (chains.size() == 1) { // e is not split
				UPR_res.m_eCopy[eG].pushBack(eNew);
				UPR_res.m_eIterator[eNew] = UPR_res.m_eCopy[eG].begin();
				break;
			}
			UPR_res.m_eCopy[eG].pushBack(eNew);
			UPR_res.m_eIterator[eNew] = UPR_res.m_eCopy[eG].rbegin();
		}
	}


	///*
	//* embed the new component in UPR_res with respect to the embedding of UPR
	//*/

	// for the cut vertex
	if (!empty) {
		adjEntry run = UPR.getAdjEntry(UPR.getEmbedding(), startUPR, UPR.getEmbedding().externalFace());
		run = run->cyclicSucc();
		adjEntry adjStart = run;
		do {
			if (edgeUPR2UPR_res[run->theEdge()] != nullptr) {
				adjEntry adj_UPR_res = edgeUPR2UPR_res[run->theEdge()]->adjSource();
				UPR_res.moveAdjAfter(adj_UPR_res, pos);
				pos = adj_UPR_res;
			}
			run = run->cyclicSucc();
		} while(run != adjStart);
	}

	for(node v : UPR.nodes) {
		if (v == startUPR && !empty)
			continue;

		node v_UPR_res = nodeUPR2UPR_res[v];
		List<adjEntry> adj_UPR, adj_UPR_res;
		v->allAdjEntries(adj_UPR);

		// convert adj_UPR of v to adj_UPR_res of v_UPR_res
		for(adjEntry adj : adj_UPR) {
			edge e_res = edgeUPR2UPR_res[adj->theEdge()];
			if (e_res == nullptr) // associated edges in UPR_res
				continue;
			adjEntry adj_res = e_res->adjSource();
			if (adj_res->theNode() != v_UPR_res)
				adj_res = adj_res->twin();
			adj_UPR_res.pushBack(adj_res);
		}

		UPR_res.sort(v_UPR_res, adj_UPR_res);
	}

	/*
	//---------------------------------------------------debug
	if (!UPR_res.empty()) {
		GraphAttributes GA_UPR_res(UPR_res, GraphAttributes::nodeGraphics|
				GraphAttributes::edgeGraphics|
				GraphAttributes::nodeColor|
				GraphAttributes::edgeColor|
				GraphAttributes::nodeLabel|
				GraphAttributes::edgeLabel
				);
		GA_UPR_res.setAllHeight(30.0);
		GA_UPR_res.setAllWidth(30.0);
		// label the nodes with their index
		for(node z : GA_UPR_res.constGraph().nodes) {
			GA_UPR_res.label(z) = to_string(z->index());
		}
		GA_UPR_res.writeGML("c:/temp/UPR_res_tmp.gml");
		cout << "UPR_res_tmp faces:";
		UPR_res.outputFaces(UPR_res.getEmbedding());
	}

	GraphAttributes GA_UPR(UPR, GraphAttributes::nodeGraphics|
				GraphAttributes::edgeGraphics|
				GraphAttributes::nodeColor|
				GraphAttributes::edgeColor|
				GraphAttributes::nodeLabel|
				GraphAttributes::edgeLabel
				);
	GA_UPR.setAllHeight(30.0);
	GA_UPR.setAllWidth(30.0);
	// label the nodes with their index
	for(node z : GA_UPR.constGraph().nodes) {
		GA_UPR.label(z) = to_string(z->index());
	}
	GA_UPR.writeGML("c:/temp/UPR_tmp.gml");
	cout << "UPR_tmp faces:";
	UPR.outputFaces(UPR.getEmbedding());
	//end -----------------------------------------------debug
	*/

	// update UPR_res
	UPR_res.initMe();
}
Esempio n. 12
0
void UpwardPlanRep::copyMe(const UpwardPlanRep &UPR)
{
	NodeArray<node> vCopy;
	EdgeArray<edge> eCopy;

	Graph::construct(UPR, vCopy, eCopy);

	// initGC
	m_pGraph = UPR.m_pGraph;

	m_vOrig.init(*this, nullptr); m_eOrig.init(*this, nullptr);
	m_vCopy.init(*m_pGraph, nullptr); m_eCopy.init(*m_pGraph);
	m_eIterator.init(*this, nullptr);

	for (node v : UPR.nodes)
		m_vOrig[vCopy[v]] = UPR.m_vOrig[v];

	for (edge e : UPR.edges)
		m_eOrig[eCopy[e]] = UPR.m_eOrig[e];

	for (node v : nodes) {
		node w = m_vOrig[v];
		if (w != nullptr) m_vCopy[w] = v;
	}

	for(edge e : m_pGraph->edges) {
		ListConstIterator<edge> it;
		for (it = UPR.m_eCopy[e].begin(); it.valid(); ++it)
			m_eIterator[eCopy[*it]] = m_eCopy[e].pushBack(eCopy[*it]);
	}

	//GraphCopy::initGC(UPR,vCopy,eCopy);
	m_Gamma.init(*this);
	m_isSinkArc.init(*this, false);
	m_isSourceArc.init(*this, false);

	if (UPR.numberOfNodes() == 0)
		return;

	s_hat = vCopy[UPR.getSuperSource()];
	if (UPR.augmented())
		t_hat = vCopy[UPR.getSuperSink()];

	OGDF_ASSERT(UPR.extFaceHandle != nullptr);

	edge eC = eCopy[UPR.extFaceHandle->theEdge()];
	node vC = vCopy[UPR.extFaceHandle->theNode()];
	if (eC->adjSource()->theNode() == vC)
		extFaceHandle = eC->adjSource();
	else
		extFaceHandle = eC->adjTarget();

	m_Gamma.setExternalFace(m_Gamma.rightFace(extFaceHandle));

	for(edge e : UPR.edges) {
		edge a = eCopy[e];
		if (UPR.isSinkArc(e))
			m_isSinkArc[a] = true;
		if (UPR.isSourceArc(e))
			m_isSourceArc[a] = true;
	}

	computeSinkSwitches();
}
Esempio n. 13
0
void VisibilityLayout::layout(GraphAttributes &GA, const UpwardPlanRep &UPROrig)
{
	UpwardPlanRep UPR = UPROrig;

	//clear some data
	for(edge e : GA.constGraph().edges) {
		GA.bends(e).clear();
	}

	int minGridDist = 1;
	for(node v : GA.constGraph().nodes) {
		if (minGridDist < max(GA.height(v), GA.width(v)))
			minGridDist = (int) max(GA.height(v), GA.width(v));
	}
	minGridDist = max(minGridDist*2+1, m_grid_dist);

	CombinatorialEmbedding &gamma = UPR.getEmbedding();
	//add edge (s,t)
	adjEntry adjSrc = nullptr;
	for(adjEntry adj : UPR.getSuperSource()->adjEntries) {
		if (gamma.rightFace(adj) == gamma.externalFace())
			adjSrc = adj;
			break;
	}

	OGDF_ASSERT(adjSrc != nullptr);

	edge e_st = UPR.newEdge(adjSrc, UPR.getSuperSink()); // on the right
	gamma.computeFaces();
	gamma.setExternalFace(gamma.rightFace(e_st->adjSource()));

	constructVisibilityRepresentation(UPR);

	// the preliminary postion
	NodeArray<int> xPos(UPR);
	NodeArray<int> yPos(UPR);

	// node Position
	for(node v : UPR.nodes) {
		NodeSegment vVis = nodeToVis[v];
		int x = (int) (vVis.x_l + vVis.x_r)/2 ; // median positioning
		xPos[v] = x;
		yPos[v] = vVis.y;

		if (UPR.original(v) != nullptr) {
			node vOrig = UPR.original(v);
			//final position
			GA.x(vOrig) = x * minGridDist;
			GA.y(vOrig)	= vVis.y * minGridDist;
		}
	}

	//compute bendpoints
	for(edge e : GA.constGraph().edges) {
		const List<edge> &chain = UPR.chain(e);
		for(edge eUPR : chain) {
			EdgeSegment eVis = edgeToVis[eUPR];
			if (chain.size() == 1) {
				if ((yPos[eUPR->target()] - yPos[eUPR->source()]) > 1) {
					DPoint p1(eVis.x*minGridDist, (yPos[eUPR->source()]+1)*minGridDist);
					DPoint p2(eVis.x*minGridDist, (yPos[eUPR->target()]-1)*minGridDist);
					GA.bends(e).pushBack(p1);
					if (yPos[eUPR->source()]+1 != yPos[eUPR->target()]-1)
						GA.bends(e).pushBack(p2);
				}
			}
			else {
				//short edge
				if ((yPos[eUPR->target()] - yPos[eUPR->source()]) == 1) {
					if (UPR.original(eUPR->target()) == nullptr) {
						node tgtUPR = eUPR->target();
						DPoint p(xPos[tgtUPR]*minGridDist, yPos[tgtUPR]*minGridDist);
						GA.bends(e).pushBack(p);
					}
				}
				//long edge
				else {
					DPoint p1(eVis.x*minGridDist, (yPos[eUPR->source()]+1)*minGridDist);
					DPoint p2(eVis.x*minGridDist, (yPos[eUPR->target()]-1)*minGridDist);
					GA.bends(e).pushBack(p1);
					if (yPos[eUPR->source()]+1 != yPos[eUPR->target()]-1)
						GA.bends(e).pushBack(p2);
					if (UPR.original(eUPR->target()) == nullptr) {
						node tgtUPR = eUPR->target();
						DPoint p(xPos[tgtUPR]*minGridDist, yPos[tgtUPR]*minGridDist);
						GA.bends(e).pushBack(p);
					}
				}
			}
		}

		DPolyline &poly = GA.bends(e);
		DPoint pSrc(GA.x(e->source()), GA.y(e->source()));
		DPoint pTgt(GA.x(e->target()), GA.y(e->target()));
		poly.normalize(pSrc, pTgt);
	}
}
Esempio n. 14
0
void VisibilityLayout::constructDualGraph(UpwardPlanRep &UPR)
{
	CombinatorialEmbedding &gamma = UPR.getEmbedding();

	faceToNode.init(gamma, nullptr);
	leftFace_node.init(UPR, nullptr);
	rightFace_node.init(UPR, nullptr);
	leftFace_edge.init(UPR, nullptr);
	rightFace_edge.init(UPR, nullptr);

	//construct a node for each face f
	for(face f : gamma.faces) {
		faceToNode[f] = D.newNode();

		if (f == gamma.externalFace())
			s_D = faceToNode[f] ;

		//compute face switches
		node s = nullptr, t = nullptr;
		for(adjEntry adj : f->entries) {
			adjEntry adjNext = adj->faceCycleSucc();
			if (adjNext->theEdge()->source() == adj->theEdge()->source())
				s = adjNext->theEdge()->source();
			if (adjNext->theEdge()->target() == adj->theEdge()->target())
				t = adjNext->theEdge()->target();
		}
		OGDF_ASSERT(s);
		OGDF_ASSERT(t);

		//compute left and right face
		bool passSource = false;
		adjEntry adj;
		if (f == gamma.externalFace()) {
			adj = UPR.getSuperSink()->firstAdj();
			if (gamma.rightFace(adj) != gamma.externalFace())
				adj = adj->cyclicSucc();
		}
		else
			adj = UPR.getAdjEntry(gamma, t, f);

		adjEntry adjBegin = adj;
		do {
			node v = adj->theEdge()->source();
			if (!passSource) {
				if (v != s)
					leftFace_node[v] = f;
				leftFace_edge[adj->theEdge()] = f;
			}
			else {
				if (v != s)
					rightFace_node[v] = f;
				rightFace_edge[adj->theEdge()] = f;
			}
			if (adj->theEdge()->source() == s)
				passSource = true;
			adj = adj->faceCycleSucc();
		} while(adj != adjBegin);
	}
	t_D = D.newNode(); // the second (right) node associated with the external face

	//construct dual edges
	for(edge e : UPR.edges) {
		face f_r = rightFace_edge[e];
		face f_l = leftFace_edge[e];
		node u = faceToNode[f_l];
		node v = faceToNode[f_r];
		if (f_r == gamma.externalFace() || f_r == f_l)
			D.newEdge(u, t_D);
		else
			D.newEdge(u,v);
	}

	OGDF_ASSERT(isConnected(D));
}
Esempio n. 15
0
void DominanceLayout::layout(GraphAttributes &GA, const UpwardPlanRep &UPROrig)
{

	UpwardPlanRep UPR = UPROrig;

	//clear some data
	for(edge e : GA.constGraph().edges) {
		GA.bends(e).clear();
	}

	//compute and splite transitiv edges
	List<edge> splitMe;
	findTransitiveEdges(UPR, splitMe);

	for(edge eSplit : splitMe) {
		UPR.getEmbedding().split(eSplit);
	}

	// set up first-/lastout, first-/lastin
	firstout.init(UPR, nullptr);
	lastout.init(UPR, nullptr);
	firstin.init(UPR, nullptr);
	lastin.init(UPR, nullptr);

	node s = UPR.getSuperSource();
	node t = UPR.getSuperSink();

	firstout[t] = lastout[t] = nullptr;
	firstin[s] = lastin[s] = nullptr;
	firstin[t] = lastin[t] =t->firstAdj()->theEdge();
	adjEntry adjRun = s->firstAdj();
	while (UPR.getEmbedding().rightFace(adjRun) != UPR.getEmbedding().externalFace()) {
		adjRun = adjRun->cyclicSucc();
	}
	lastout[s] = adjRun->theEdge();
	firstout[s] = adjRun->cyclicSucc()->theEdge();

	for(node v : UPR.nodes) {
		if (v == t || v == s) continue;

		adjEntry adj = UPR.leftInEdge(v);
		firstin[v] = adj->theEdge();
		firstout[v] = adj->cyclicSucc()->theEdge();

		adjEntry adjRightIn = adj;
		while (adjRightIn->cyclicPred()->theEdge()->source() != v)
			adjRightIn = adjRightIn->cyclicPred();

		lastin[v] = adjRightIn->theEdge();
		lastout[v] = adjRightIn->cyclicPred()->theEdge();
	}


	//compute m_L and m_R for min. area drawing
	m_L = 0;
	m_R = 0;
	for(edge e : UPR.edges) {
		node src = e->source();
		node tgt = e->target();
		if (lastin[tgt] == e && firstout[src] == e)
			m_L++;
		if (firstin[tgt] == e && lastout[src] == e)
			m_R++;
	}

	// compute preleminary coordinate
	xPreCoord.init(UPR);
	yPreCoord.init(UPR);
	int count = 0;
	labelX(UPR, s, count);
	count = 0;
	labelY(UPR, s, count);

	// compaction
	compact(UPR, GA);

	// map coordinate to GA
	for(node v : GA.constGraph().nodes) {
		node vUPR = UPR.copy(v);
		GA.x(v) = xCoord[vUPR];
		GA.y(v) = yCoord[vUPR];
	}
	// add bends to original edges
	for(edge e : GA.constGraph().edges) {
		const List<edge> &chain = UPR.chain(e);
		for(edge eChain : chain) {
			node tgtUPR = eChain->target();
			if (tgtUPR != chain.back()->target()) {
				DPoint p(xCoord[tgtUPR], yCoord[tgtUPR]);
				GA.bends(e).pushBack(p);
			}
		}
	}


	//rotate the drawing
	for(node v : GA.constGraph().nodes) {
		double r = sqrt(GA.x(v)*GA.x(v) + GA.y(v)*GA.y(v));
		if (r == 0)
			continue;
		double alpha = asin(GA.y(v)/r);
		double yNew = sin(alpha + m_angle)*r;
		double xNew = cos(alpha + m_angle)*r;
		GA.x(v) = xNew;
		GA.y(v) = yNew;
	}

	for(edge e : GA.constGraph().edges) {
		DPolyline &poly = GA.bends(e);
		DPoint pSrc(GA.x(e->source()), GA.y(e->source()));
		DPoint pTgt(GA.x(e->target()), GA.y(e->target()));
		poly.normalize(pSrc, pTgt);

		for(DPoint &p : poly) {
			double r = p.distance(DPoint(0,0));

			if (r == 0)
				continue;

			double alpha = asin( p.m_y/r);
			double yNew = sin(alpha + m_angle)*r;
			double xNew = cos(alpha + m_angle)*r;
			p.m_x = xNew;
			p.m_y = yNew;
		}

	}
}