Ejemplo n.º 1
0
	void VarEdgeInserterDynUMLCore::BCandSPQRtreesUML::insertEdgePath(
		edge eOrig, const SList<adjEntry>& crossedEdges)
	{
		SList<edge> ti;
		SList<node> tj;
		for (adjEntry adj : crossedEdges) {
			ti.pushBack(adj->theEdge());
			tj.pushBack(adj->theEdge()->target());
		}

		m_pr.insertEdgePath(eOrig, crossedEdges);

		Graph::EdgeType typeOfEOrig = m_pr.typeOrig(eOrig);
		int costOfEOrig = m_costOrig ? eOrig ? (*m_costOrig)[eOrig] : 0 : 1;

		node v = m_pr.copy(eOrig->source());
		SListConstIterator<edge> it = ti.begin();
		SListConstIterator<node> jt = tj.begin();
		SListConstIterator<adjEntry> kt;
		for (kt = crossedEdges.begin(); it.valid(); ++it, ++jt, ++kt) {
			edge e = *it;
			node u = e->target();
			adjEntry a;
			for (a = u->firstAdj(); a->theEdge()->target() != *jt; a = a->succ())
				;
			edge f = a->theEdge();
			m_dynamicSPQRForest.updateInsertedNode(e, f);
			e = m_dynamicSPQRForest.rep(e);
			f = m_dynamicSPQRForest.rep(f);
			m_typeOf[f] = m_typeOf[e];
			m_cost[f] = m_cost[e];
			for (a = u->firstAdj(); a->theEdge()->source() != v; a = a->succ());
			f = a->theEdge();
			m_dynamicSPQRForest.updateInsertedEdge(f);
			f = m_dynamicSPQRForest.rep(f);
			m_typeOf[f] = typeOfEOrig;
			m_cost[f] = costOfEOrig;
			v = u;
		}
		node u = m_pr.copy(eOrig->target());
		adjEntry a;
		for (a = v->firstAdj(); a->theEdge()->target() != u; a = a->succ())
			;
		edge f = a->theEdge();
		m_dynamicSPQRForest.updateInsertedEdge(f);
		f = m_dynamicSPQRForest.rep(f);
		m_typeOf[f] = typeOfEOrig;
		m_cost[f] = costOfEOrig;
	}
Ejemplo n.º 2
0
node FaceSinkGraph::dfsStAugmentation(
	node v,                      // current node
	node parent,                 // its parent
	Graph &G,                    // original graph (not const)
	SList<edge> &augmentedEdges) // list of augmented edges
{
	bool isFace = (m_originalFace[v] != nullptr);
	node vf = (parent != nullptr) ? m_originalNode[parent] : nullptr;

	// since we already know that T is a tree we can omit the visited array
	for(adjEntry adj : v->adjEntries)
	{
		node w = adj->twinNode();

		if (w == parent) continue;

		if (isFace) {
			if (vf == nullptr) {
				vf = G.newNode();
			}

			edge ew = G.newEdge(m_originalNode[w],vf);
			augmentedEdges.pushBack(ew);
		}

		dfsStAugmentation(w,v,G,augmentedEdges);
	}

	return vf;
}
Ejemplo n.º 3
0
int main(void){
	SList<int> mylist;
	mylist.pushFront(10);
	mylist.pushFront(20);
	mylist.pushBack(30);

	for(auto it=mylist.begin();it!=mylist.end();++it){
		cout << *it << endl;
	}
	return 0;

}
Ejemplo n.º 4
0
//
// createSkeleton: creates a skeleton graph
//
DynamicSkeleton& DynamicSPQRTree::createSkeleton(node vT) const
{
	DynamicSkeleton& S = *OGDF_NEW DynamicSkeleton(this, vT);

	SList<node> inMapV;

	for (edge eH : m_tNode_hEdges[vT])
	{
		node sH = eH->source();
		node tH = eH->target();

		edge& eM = m_skelEdge[eH];
		node& sM = m_mapV[sH];
		node& tM = m_mapV[tH];

		if (!sM) {
			sM = S.m_M.newNode();
			S.m_origNode[sM] = sH;
			inMapV.pushBack(sH);
		}

		if (!tM) {
			tM = S.m_M.newNode();
			S.m_origNode[tM] = tH;
			inMapV.pushBack(tH);
		}

		eM = S.m_M.newEdge(sM, tM);
		S.m_origEdge[eM] = eH;
	}

	while (!inMapV.empty()) m_mapV[inMapV.popFrontRet()] = nullptr;

	S.m_referenceEdge = m_tNode_hRefEdge[vT];
	if (S.m_referenceEdge) S.m_referenceEdge = m_skelEdge[S.m_referenceEdge];

	m_sk[vT] = &S;
	return S;
}
Ejemplo n.º 5
0
// builds list of possible external faces (all faces in tree T containing
// the single source s) by a dfs traversal of T
void FaceSinkGraph::gatherExternalFaces(
	node v,                                // current node
	node parent,                           // its parent
	SList<face> &externalFaces)      // returns list of possible external faces
{
	if (m_containsSource[v])
		externalFaces.pushBack(m_originalFace[v]);

	// since we already know that T is a tree we can omit the visited array
	for(adjEntry adj : v->adjEntries)
	{
		node w = adj->twinNode();

		if (w != parent)
			gatherExternalFaces(w,v,externalFaces);
	}
}
Ejemplo n.º 6
0
// original variant of st-augmentation
// Inserts also new nodes representing faces into G.
void FaceSinkGraph::stAugmentation(
	node h,                       // node corresponding to external face
	Graph &G,                     // original graph (not const)
	SList<node> &augmentedNodes,  // list of augmented nodes
	SList<edge> &augmentedEdges)  // list of augmented edges
{
	SListPure<node> roots;
	for(node v : nodes) {
		node vOrig = m_originalNode[v];
		if (vOrig != nullptr && vOrig->indeg() > 0 && vOrig->outdeg() > 0)
			roots.pushBack(v);
	}

	node vh = dfsStAugmentation(h,nullptr,G,augmentedNodes,augmentedEdges);

	SListConstIterator<node> it;
	for(it = roots.begin(); it.valid(); ++it)
		dfsStAugmentation(*it,nullptr,G,augmentedNodes,augmentedEdges);

	augmentedEdges.pushBack(G.newEdge(m_source,vh));

}
Ejemplo n.º 7
0
	void VarEdgeInserterDynCore::insert(edge eOrig, SList<adjEntry>& eip)
	{
		eip.clear();
		node s = m_pr.copy(eOrig->source());
		node t = m_pr.copy(eOrig->target());

		// find path from s to t in BC-tree
		// call of blockInsert() is done when we have found the path
		// if no path is found, s and t are in different connected components
		// and thus an empty edge insertion path is correct!
		DynamicSPQRForest& dSPQRF = m_pBC->dynamicSPQRForest();
		SList<node>& path = dSPQRF.findPath(s, t);
		if (!path.empty()) {
			SListIterator<node> it = path.begin();
			node repS = dSPQRF.repVertex(s, *it);
			for (SListIterator<node> jt = it; it.valid(); ++it) {
				node repT = (++jt).valid() ? dSPQRF.cutVertex(*jt, *it) : dSPQRF.repVertex(t, *it);

				// less than 3 nodes requires no crossings (cannot build SPQR-tree
				// for a graph with less than 3 nodes!)
				if (dSPQRF.numberOfNodes(*it) > 3) {
					List<adjEntry> L;
					blockInsert(repS, repT, L); // call biconnected case

					// transform crossed edges to edges in G
					for (adjEntry kt : L) {
						edge e = kt->theEdge();
						eip.pushBack(e->adjSource() == kt ? dSPQRF.original(e)->adjSource()
							: dSPQRF.original(e)->adjTarget());
					}
				}
				if (jt.valid()) repS = dSPQRF.cutVertex(*it, *jt);
			}
		}
		delete &path;
	}
Ejemplo n.º 8
0
void UpwardPlanarSubgraphSimple::call(GraphCopy &GC, List<edge> &delEdges)
{
	const Graph &G = GC.original();
	delEdges.clear();

	// We construct an auxiliary graph H which represents the current upward
	// planar subgraph.
	Graph H;
	NodeArray<node> mapToH(G,nullptr);
	NodeArray<node> mapToG(H,nullptr);

	for(node v : G.nodes)
		mapToG[ mapToH[v] = H.newNode() ] = v;


	// We currently support only single-source acyclic digraphs ...
	node s;
	hasSingleSource(G,s);

	OGDF_ASSERT(s != 0);
	OGDF_ASSERT(isAcyclic(G));

	// We start with a spanning tree of G rooted at the single source.
	NodeArray<bool> visitedNode(G,false);
	SListPure<edge> treeEdges;
	dfsBuildSpanningTree(s,treeEdges,visitedNode);


	// Mark all edges in the spanning tree so they can be skipped in the
	// loop below and add (copies of) them to H.
	EdgeArray<bool> visitedEdge(G,false);
	SListConstIterator<edge> it;
	for(it = treeEdges.begin(); it.valid(); ++it) {
		edge eG = *it;
		visitedEdge[eG] = true;
		H.newEdge(mapToH[eG->source()],mapToH[eG->target()]);
	}


	// Add subsequently the remaining edges to H and test if the resulting
	// graph is still upward planar. If not, remove the edge again from H
	// and add it to delEdges.

	SList<Tuple2<node,node> > augmented;
	GraphCopySimple graphAcyclicTest(G);

	for(edge eG : G.edges)
	{
		// already treated ?
		if(visitedEdge[eG] == true)
			continue;

		// insert edge into H
		edge eH = H.newEdge(mapToH[eG->source()],mapToH[eG->target()]);

		node superSink;
		SList<edge> augmentedEdges;
		if (UpwardPlanarity::upwardPlanarAugment_singleSource(H,superSink,augmentedEdges) == false) {
			// if H is no longer upward planar, remove eG from subgraph
			H.delEdge(eH);
			delEdges.pushBack(eG);

		} else {
			// add augmented edges as node-pair to tmpAugmented and remove
			// all augmented edges from H again
			SList<Tuple2<node,node> > tmpAugmented;
			SListConstIterator<edge> it;
			for(it = augmentedEdges.begin(); it.valid(); ++it) {
				node v = mapToG[(*it)->source()];
				node w = mapToG[(*it)->target()];

				if (v && w)
					tmpAugmented.pushBack(Tuple2<node,node>(v,w));

				H.delEdge(*it);
			}

			if (mapToG[superSink] == nullptr)
				H.delNode(superSink);

			//****************************************************************
			// The following is a simple workaround to assure the following
			// property of the upward planar subgraph:
			//   The st-augmented upward planar subgraph plus the edges not
			//   in the subgraph must be acyclic. (This is a special property
			//   of the embedding, not the augmentation.)
			// The upward-planar embedding function gives us ANY upward-planar
			// embedding. We check if the property above holds with this
			// embedding. If it doesn't, we have actually no idea if another
			// embedding would do.
			// The better solution would be to incorporate the acyclicity
			// property into the upward-planarity test, but this is compicated.
			//****************************************************************

			// test if original graph plus augmented edges is still acyclic
			if(checkAcyclic(graphAcyclicTest,tmpAugmented) == true) {
				augmented = tmpAugmented;

			} else {
				// if not, remove eG from subgraph
				H.delEdge(eH);
				delEdges.pushBack(eG);
			}
		}

	}

	// remove edges not in the subgraph from GC
	ListConstIterator<edge> itE;
	for(itE = delEdges.begin(); itE.valid(); ++itE)
		GC.delEdge(GC.copy(*itE));

	// add augmented edges to GC
	SListConstIterator<Tuple2<node,node> > itP;
	for(itP = augmented.begin(); itP.valid(); ++itP) {
		node v = (*itP).x1();
		node w = (*itP).x2();

		GC.newEdge(GC.copy(v),GC.copy(w));
	}

	// add super sink to GC
	node sGC = nullptr;
	SList<node> sinks;
	for(node v : GC.nodes) {
		if(v->indeg() == 0)
			sGC = v;
		if(v->outdeg() == 0)
			sinks.pushBack(v);
	}

	node superSinkGC = GC.newNode();
	SListConstIterator<node> itV;
	for(itV = sinks.begin(); itV.valid(); ++itV)
		GC.newEdge(*itV,superSinkGC);

	// add st-edge to GC, so that we now have a planar st-digraph
	GC.newEdge(sGC,superSinkGC);

	OGDF_ASSERT(isAcyclic(GC));
	OGDF_ASSERT(isPlanar(GC));
}
Ejemplo n.º 9
0
void DynamicSPQRForest::createSPQR (node vB) const
{
	Graph GC;
	NodeArray<node> origNode(GC,0);
	EdgeArray<edge> origEdge(GC,0);
	SListConstIterator<edge> iH;

	for (iH=m_bNode_hEdges[vB].begin(); iH.valid(); ++iH)
		m_htogc[(*iH)->source()] = m_htogc[(*iH)->target()] = 0;

	for (iH=m_bNode_hEdges[vB].begin(); iH.valid(); ++iH) {
		edge eH = *iH;
		node sH = eH->source();
		node tH = eH->target();
		node& sGC = m_htogc[sH];
		node& tGC = m_htogc[tH];
		if (!sGC) { sGC = GC.newNode(); origNode[sGC] = sH; }
		if (!tGC) { tGC = GC.newNode(); origNode[tGC] = tH; }
		origEdge[GC.newEdge(sGC,tGC)] = eH;
	}

	TricComp tricComp(GC);

	const GraphCopySimple& GCC = *tricComp.m_pGC;

	EdgeArray<node> partnerNode(GCC,0);
	EdgeArray<edge> partnerEdge(GCC,0);

	for (int i=0; i<tricComp.m_numComp; ++i) {
		const TricComp::CompStruct &C = tricComp.m_component[i];

		if (C.m_edges.empty()) continue;

		node vT = m_T.newNode();
		m_tNode_owner[vT] = vT;

		switch(C.m_type) {
			case TricComp::bond:
				m_tNode_type[vT] = PComp;
				m_bNode_numP[vB]++;
				break;
			case TricComp::polygon:
				m_tNode_type[vT] = SComp;
				m_bNode_numS[vB]++;
				break;
			case TricComp::triconnected:
				m_tNode_type[vT] = RComp;
				m_bNode_numR[vB]++;
				break;
		}

		for (ListConstIterator<edge> iGCC=C.m_edges.begin(); iGCC.valid(); ++iGCC) {
			edge eGCC = *iGCC;
			edge eH = GCC.original(eGCC);
			if (eH) eH = origEdge[eH];
			else {
				node uH = origNode[GCC.original(eGCC->source())];
				node vH = origNode[GCC.original(eGCC->target())];
				eH = m_H.newEdge(uH,vH);

				if (!partnerNode[eGCC]) {
					partnerNode[eGCC] = vT;
					partnerEdge[eGCC] = eH;
				}
				else {
					m_T.newEdge(partnerNode[eGCC],vT);
					m_hEdge_twinEdge[eH] = partnerEdge[eGCC];
					m_hEdge_twinEdge[partnerEdge[eGCC]] = eH;
				}
			}
			m_hEdge_position[eH] = m_tNode_hEdges[vT].pushBack(eH);
			m_hEdge_tNode[eH] = vT;
		}
	}

	m_bNode_SPQR[vB] = m_hEdge_tNode[origEdge[GC.firstEdge()]];
	m_tNode_hRefEdge[m_bNode_SPQR[vB]] = 0;

	SList<node> lT;
	lT.pushBack(m_bNode_SPQR[vB]);
	lT.pushBack(0);
	while (!lT.empty()) {
		node vT = lT.popFrontRet();
		node wT = lT.popFrontRet();
		for (ListConstIterator<edge> iH=m_tNode_hEdges[vT].begin(); iH.valid(); ++iH) {
			edge eH = *iH;
			edge fH = m_hEdge_twinEdge[eH];
			if (!fH) continue;
			node uT = m_hEdge_tNode[fH];
			if (uT==wT) m_tNode_hRefEdge[vT] = eH;
			else {
				lT.pushBack(uT);
				lT.pushBack(vT);
			}
		}
	}
}
Ejemplo n.º 10
0
edge DynamicSPQRTree::updateInsertedEdge(edge eG)
{
	SList<node> marked;
	node sH = m_gNode_hNode[eG->source()];
	node tH = m_gNode_hNode[eG->target()];
	for (adjEntry aH : sH->adjEdges) {
		edge fH = aH->theEdge();
		node vT = spqrproper(fH);
		if (fH->opposite(sH) == tH) {
			if (m_tNode_type[vT] == PComp) {
				DynamicSPQRForest::updateInsertedEdge(eG);
				if (m_sk[vT]) {
					edge eH = m_gEdge_hEdge[eG];
					edge fM = m_skelEdge[fH];
					node sM = fM->source();
					node tM = fM->target();
					if (eH->source() == m_sk[vT]->m_origNode[tM]) {
						node uM = sM; sM = tM; tM = uM;
					}
					m_skelEdge[eH] = m_sk[vT]->getGraph().newEdge(sM, tM);
					m_sk[vT]->m_origEdge[m_skelEdge[eH]] = eH;
				}
				return eG;
			}
			else if (!m_hEdge_twinEdge[fH]) {
				DynamicSPQRForest::updateInsertedEdge(eG);
				if (m_sk[vT]) {
					edge gH = m_hEdge_twinEdge[m_tNode_hEdges[m_hEdge_tNode[fH]].front()];
					m_skelEdge[gH] = m_skelEdge[fH];
					m_sk[vT]->m_origEdge[m_skelEdge[gH]] = gH;
				}
				return eG;
			}
			else {
				m_tNode_isMarked[vT] = true;
				marked.pushBack(vT);
			}
		}
		else {
			m_tNode_isMarked[vT] = true;
			marked.pushBack(vT);
		}
	}
	int count = 0;
	node found[2];
	for (adjEntry aH : tH->adjEdges) {
		edge fH = aH->theEdge();
		node vT = spqrproper(fH);
		if (!m_tNode_isMarked[vT]) continue;
		found[count++] = vT;
		m_tNode_isMarked[vT] = false;
	}
	while (!marked.empty()) m_tNode_isMarked[marked.popFrontRet()] = false;
	if (count == 0) {
		node rT;
		SList<node>& pT = findPathSPQR(sH, tH, rT);
		for (node vT : pT) {
			if (m_sk[vT]) {
				delete m_sk[vT];
				m_sk[vT] = nullptr;
			}
		}
		delete &pT;
	}
	else if (count == 1) {
		node vT = found[0];
		if (m_sk[vT]) {
			delete m_sk[vT];
			m_sk[vT] = nullptr;
		}
	}
	return DynamicSPQRForest::updateInsertedEdge(eG);
}
Ejemplo n.º 11
0
void GEMLayout::call(GraphAttributes &AG)
{
	const Graph &G = AG.constGraph();
	if(G.empty())
		return;

	// all edges straight-line
	AG.clearAllBends();

	GraphCopy GC;
	GC.createEmpty(G);

	// compute connected component of G
	NodeArray<int> component(G);
	int numCC = connectedComponents(G,component);

	// intialize the array of lists of nodes contained in a CC
	Array<List<node> > nodesInCC(numCC);

	for(node v : G.nodes)
		nodesInCC[component[v]].pushBack(v);

	EdgeArray<edge> auxCopy(G);
	Array<DPoint> boundingBox(numCC);

	int i;
	for(i = 0; i < numCC; ++i)
	{
		GC.initByNodes(nodesInCC[i],auxCopy);

		GraphCopyAttributes AGC(GC,AG);
		for(node vCopy : GC.nodes) {
			node vOrig = GC.original(vCopy);
			AGC.x(vCopy) = AG.x(vOrig);
			AGC.y(vCopy) = AG.y(vOrig);
		}

		SList<node> permutation;

		// initialize node data
		m_impulseX.init(GC,0);
		m_impulseY.init(GC,0);
		m_skewGauge.init(GC,0);
		m_localTemperature.init(GC,m_initialTemperature);

		// initialize other data
		m_globalTemperature = m_initialTemperature;
		m_barycenterX = 0;
		m_barycenterY = 0;
		for(node v : GC.nodes) {
			m_barycenterX += weight(v) * AGC.x(v);
			m_barycenterY += weight(v) * AGC.y(v);
		}
		m_cos = cos(m_oscillationAngle / 2.0);
		m_sin = sin(Math::pi / 2 + m_rotationAngle / 2.0);

		// main loop
		int counter = m_numberOfRounds;
		while(OGDF_GEOM_ET.greater(m_globalTemperature,m_minimalTemperature) && counter--) {

			// choose nodes by random permutations
			if(permutation.empty()) {
				for(node v : GC.nodes)
					permutation.pushBack(v);
				permutation.permute(m_rng);
			}
			node v = permutation.popFrontRet();

			// compute the impulse of node v
			computeImpulse(GC,AGC,v);

			// update node v
			updateNode(GC,AGC,v);

		}

		node vFirst = GC.firstNode();
		double minX = AGC.x(vFirst), maxX = AGC.x(vFirst),
			minY = AGC.y(vFirst), maxY = AGC.y(vFirst);

		for(node vCopy : GC.nodes) {
			node v = GC.original(vCopy);
			AG.x(v) = AGC.x(vCopy);
			AG.y(v) = AGC.y(vCopy);

			if(AG.x(v)-AG.width (v)/2 < minX) minX = AG.x(v)-AG.width(v) /2;
			if(AG.x(v)+AG.width (v)/2 > maxX) maxX = AG.x(v)+AG.width(v) /2;
			if(AG.y(v)-AG.height(v)/2 < minY) minY = AG.y(v)-AG.height(v)/2;
			if(AG.y(v)+AG.height(v)/2 > maxY) maxY = AG.y(v)+AG.height(v)/2;
		}

		minX -= m_minDistCC;
		minY -= m_minDistCC;

		for(node vCopy : GC.nodes) {
			node v = GC.original(vCopy);
			AG.x(v) -= minX;
			AG.y(v) -= minY;
		}

		boundingBox[i] = DPoint(maxX - minX, maxY - minY);
	}

	Array<DPoint> offset(numCC);
	TileToRowsCCPacker packer;
	packer.call(boundingBox,offset,m_pageRatio);

	// The arrangement is given by offset to the origin of the coordinate
	// system. We still have to shift each node and edge by the offset
	// of its connected component.

	for(i = 0; i < numCC; ++i)
	{
		const List<node> &nodes = nodesInCC[i];

		const double dx = offset[i].m_x;
		const double dy = offset[i].m_y;

		// iterate over all nodes in ith CC
		ListConstIterator<node> it;
		for(node v : nodes)
		{
			AG.x(v) += dx;
			AG.y(v) += dy;
		}
	}


	// free node data
	m_impulseX.init();
	m_impulseY.init();
	m_skewGauge.init();
	m_localTemperature.init();
}
Ejemplo n.º 12
0
void PlanRep::expandLowDegreeVertices(OrthoRep &OR)
{
	for(node v : nodes)
	{
		if (!(isVertex(v)) || expandAdj(v) != nullptr)
			continue;

		SList<edge> adjEdges;
		SListPure<Tuple2<node,int> > expander;

		node u = v;
		bool firstTime = true;

		setExpandedNode(v, v);

		for(adjEntry adj : v->adjEdges) {
			adjEdges.pushBack(adj->theEdge());

			if(!firstTime)
				u = newNode();

			setExpandedNode(u, v);
			typeOf(u) = Graph::lowDegreeExpander;
			expander.pushBack(Tuple2<node,int>(u,OR.angle(adj)));
			firstTime = false;
		}

		SListConstIterator<Tuple2<node,int>> itn = expander.begin().succ();

		for (SListConstIterator<edge> it = adjEdges.begin().succ(); it.valid(); ++it)
		{
			// Did we allocate enough dummy nodes?
			OGDF_ASSERT(itn.valid());

			if ((*it)->source() == v)
				moveSource(*it,(*itn).x1());
			else
				moveTarget(*it,(*itn).x1());
			++itn;
		}

		adjEntry adjPrev = v->firstAdj();
		itn = expander.begin();
		int nBends = (*itn).x2();

		for (++itn; itn.valid(); ++itn)
		{
			edge e = newEdge(adjPrev,(*itn).x1()->firstAdj());

			OR.bend(e->adjSource()).set(convexBend,nBends);
			OR.bend(e->adjTarget()).set(reflexBend,nBends);
			OR.angle(adjPrev) = 1;
			OR.angle(e->adjSource()) = 2;
			OR.angle(e->adjTarget()) = 1;

			nBends = (*itn).x2();

			typeOf(e) = association; //???
			setExpansionEdge(e, 2);

			adjPrev = (*itn).x1()->firstAdj();
		}

		edge e = newEdge(adjPrev,v->lastAdj());
		typeOf(e) = association; //???
		setExpansionEdge(e, 2);

		expandAdj(v) = e->adjSource();

		OR.bend(e->adjSource()).set(convexBend,nBends);
		OR.bend(e->adjTarget()).set(reflexBend,nBends);
		OR.angle(adjPrev) = 1;
		OR.angle(e->adjSource()) = 2;
		OR.angle(e->adjTarget()) = 1;

	}
}//expandlowdegreevertices
Ejemplo n.º 13
0
void PlanRep::expand(bool lowDegreeExpand)
{
	for(node v : nodes)
	{

		// Replace vertices with high degree by cages and
		// replace degree 4 vertices with two generalizations
		// adjacent in the embedding list by a cage.
		if ((v->degree() > 4)  && (typeOf(v) != Graph::dummy) && !lowDegreeExpand)
		{
			edge e;

			//Set the type of the node v. It remains in the graph
			// as one of the nodes of the expanded face.
			typeOf(v) = Graph::highDegreeExpander;

			// Scan the list of edges of v to find the adjacent edges of v
			// according to the planar embedding. All except one edge
			// will get a new adjacent node
			SList<edge> adjEdges;
			{forall_adj_edges(e,v)
				adjEdges.pushBack(e);
			}

			//The first edge remains at v. remove it from the list.
			e = adjEdges.popFrontRet();

			// Create the list of high degree expanders
			// We need degree(v)-1 of them to construct a face.
			// and set expanded Node to v
			setExpandedNode(v, v);
			SListPure<node> expander;
			for (int i = 0; i < v->degree()-1; i++)
			{
				node u = newNode();
				typeOf(u) = Graph::highDegreeExpander;
				setExpandedNode(u, v);
				expander.pushBack(u);
			}

			// We move the target node of each ingoing generalization of v to a new
			// node stored in expander.
			// Note that, for each such edge e, the target node of the original
			// edge is then different from the original of the target node of e
			// (the latter is 0 because u is a new (dummy) node)
			SListConstIterator<node> itn;

			NodeArray<adjEntry> ar(*this);

			itn = expander.begin();

			for (edge ei : adjEdges)
			{
				// Did we allocate enough dummy nodes?
				OGDF_ASSERT(itn.valid());

				if (ei->source() == v)
					moveSource(ei,*itn);
				else
					moveTarget(ei,*itn);
				ar[*itn] = (*itn)->firstAdj();
				++itn;
			}
			ar[v] = v->firstAdj();

			// Now introduce the circular list of new edges
			// forming the border of the merge face. Keep the embedding.
			adjEntry adjPrev = v->firstAdj();

//			cout <<endl << "INTRODUCING CIRCULAR EDGES" << endl;
			for (node n : expander)
			{
//				cout << adjPrev << " " << (*itn)->firstAdj() << endl;
				e = Graph::newEdge(adjPrev,n->firstAdj());
				setExpansionEdge(e, 2);//can be removed if edgetypes work properly

				setExpansion(e);
				setAssociation(e);

				typeOf(e) = association; //???

				if (!expandAdj(v))
					expandAdj(v) = e->adjSource();
				adjPrev = n->firstAdj();
			}

			e = newEdge(adjPrev,v->lastAdj());

			typeOf(e) = association; //???
			setExpansionEdge(e, 2);//can be removed if edgetypes work properly
			setAssociation(e);

		}//highdegree

		// Replace all vertices with degree > 2 by cages.
		else if (v->degree() >= 2  && typeOf(v) != Graph::dummy &&
				 lowDegreeExpand)
		{
			edge e;

			//Set the type of the node v. It remains in the graph
			// as one of the nodes of the expanded face.
			typeOf(v) = Graph::lowDegreeExpander; //high??

			// Scan the list of edges of v to find the adjacent edges of v
			// according to the planar embedding. All except one edge
			// will get a new adjacent node
			SList<edge> adjEdges;
			{forall_adj_edges(e,v)
				adjEdges.pushBack(e);
			}

			//The first edge remains at v. remove it from the list.
			// Check if it is a generalization.
			e = adjEdges.popFrontRet();

			// Create the list of high degree expanders
			// We need degree(v)-1 of them to construct a face.
			// and set expanded Node to v
			setExpandedNode(v, v);
			SListPure<node> expander;
			for (int i = 0; i < v->degree()-1; i++)
			{
				node u = newNode();
				typeOf(u) = Graph::highDegreeExpander;
				setExpandedNode(u, v);
				expander.pushBack(u);
			}

			// We move the target node of each ingoing generalization of v to a new
			// node stored in expander.
			// Note that, for each such edge e, the target node of the original
			// edge is then different from the original of the target node of e
			// (the latter is 0 because u is a new (dummy) node)

			NodeArray<adjEntry> ar(*this);

			SListConstIterator<node> itn = expander.begin();

			for (edge ei : adjEdges)
			{
				// Did we allocate enough dummy nodes?
				OGDF_ASSERT(itn.valid());

				if (ei->source() == v)
					moveSource(ei,*itn);
				else
					moveTarget(ei,*itn);
				ar[*itn] = (*itn)->firstAdj();
				++itn;
			}
			ar[v] = v->firstAdj();

			// Now introduce the circular list of new edges
			// forming the border of the merge face. Keep the embedding.
			adjEntry adjPrev = v->firstAdj();

			for (node n : expander)
			{
				e = newEdge(adjPrev,n->firstAdj());
				if (!expandAdj(v)) expandAdj(v) = e->adjSource();
				typeOf(e) = association; //???
				setExpansionEdge(e, 2);

				//new types
				setAssociation(e); //should be dummy type?
				setExpansion(e);

				adjPrev = n->firstAdj();
			}
			e = newEdge(adjPrev,v->lastAdj());
			typeOf(e) = association; //???
			setExpansionEdge(e, 2);
		}

	}

}//expand