示例#1
0
void FaceSinkGraph::doInit()
{
	const ConstCombinatorialEmbedding &E = *m_pE;

	NodeArray<node> sinkSwitch(E,nullptr); // corresponding node in F (if any)
	NodeArray<bool> isSinkSwitch(E,true);

	NodeArray<int> visited(E,-1);
	int faceNo = -1;
	for(face f : E.faces)
	{
		faceNo++;
		node faceNode = newNode();
		m_originalFace[faceNode] = f;

		SListPure<node> nodesInF;

		adjEntry adj1 = f->firstAdj(), adj = adj1;
		do {
			node v = adj->theNode();
			// if the graph is not biconnected, then node v can visited more than once
			if (visited[v] != faceNo) {
				nodesInF.pushBack(v);
				visited[v] = faceNo;
			}

			if (v == m_source)
				m_containsSource[faceNode] = true;

			isSinkSwitch[adj->theEdge()->source()] = false;

			adj = adj->twin()->cyclicPred();
		} while (adj != adj1);

		SListConstIterator<node> it;
		for(it = nodesInF.begin(); it.valid(); ++it)
		{
			node v = *it;
			if(isSinkSwitch[v])	{
				if (sinkSwitch[v] == nullptr) {
					node vF = newNode();
					m_originalNode[vF] = v;
					sinkSwitch[v] = vF;
				}

				newEdge(faceNode,sinkSwitch[v]);
			}
		}

		for(it = nodesInF.begin(); it.valid(); ++it)
			isSinkSwitch[*it] = true;
	}
}
示例#2
0
void SubgraphPlanarizer::CrossingStructure::restore(PlanRep &PG, int cc)
{
	//PG.initCC(cc);
	
	Array<node> id2Node(0,m_numCrossings-1,0);
	
	SListPure<edge> edges;
	PG.allEdges(edges);

	for(SListConstIterator<edge> itE = edges.begin(); itE.valid(); ++itE)
	{
		edge ePG = *itE;
		edge e = PG.original(ePG);
		
		SListConstIterator<int> it;
		for(it = m_crossings[e].begin(); it.valid(); ++it)
		{
			node x = id2Node[*it];
			edge ePGOld = ePG;
			ePG = PG.split(ePG);
			node y = ePG->source();
			
			if(x == 0) {
				id2Node[*it] = y;
			} else {
				PG.moveTarget(ePGOld, x);
				PG.moveSource(ePG, x);
				PG.delNode(y);
			}
		}
	}
}
void FaceSinkGraph::doInit()
{
	const ConstCombinatorialEmbedding &E = *m_pE;

	NodeArray<node> sinkSwitch(E,0); // corresponding node in F (if any)
	NodeArray<bool> isSinkSwitch(E,true);

	face f;
	forall_faces(f,E)
	{
		node faceNode = newNode();
		m_originalFace[faceNode] = f;

		SListPure<node> nodesInF;

		adjEntry adj1 = f->firstAdj(), adj = adj1;
		do {
			node v = adj->theNode();
			nodesInF.pushBack(v);

			if (v == m_source)
				m_containsSource[faceNode] = true;

			isSinkSwitch[adj->theEdge()->source()] = false;

			adj = adj->twin()->cyclicPred();
		} while (adj != adj1);

		SListConstIterator<node> it;
		for(it = nodesInF.begin(); it.valid(); ++it)
		{
			node v = *it;
			if(isSinkSwitch[v])	{
				if (sinkSwitch[v] == 0) {
					node vF = newNode();
					m_originalNode[vF] = v;
					sinkSwitch[v] = vF;
				}

				newEdge(faceNode,sinkSwitch[v]);
			}
		}

		for(it = nodesInF.begin(); it.valid(); ++it)
			isSinkSwitch[*it] = true;
	}
示例#4
0
KuratowskiConstraint::KuratowskiConstraint(ABA_MASTER *master, int nEdges, SListPure<nodePair> &ks) :
	ABA_CONSTRAINT(master, 0, ABA_CSENSE::Less, nEdges-1, true, false, true)
{
	SListConstIterator<nodePair> it;
	for (it = ks.begin(); it.valid(); ++it) {
		m_subdivision.pushBack(*it);
	}
}
示例#5
0
// Initializes a PQTree by a set of leaves that will korrespond to
// the set of Keys stored in leafKeys.
int PlanarPQTree::Initialize(SListPure<PlanarLeafKey<IndInfo*>*> &leafKeys)
{
	SListIterator<PlanarLeafKey<IndInfo*>* >  it;
	SListPure<PQLeafKey<edge,IndInfo*,bool>*> castLeafKeys;
	for (it = leafKeys.begin(); it.valid(); ++it)
		castLeafKeys.pushBack((PQLeafKey<edge,IndInfo*,bool>*) *it);

	return PQTree<edge,IndInfo*,bool>::Initialize(castLeafKeys);
}
示例#6
0
// Reduction reduced a set of leaves determined by their keys stored 
// in leafKeys. Integer redNumber is for debugging only.
bool PlanarPQTree::Reduction(SListPure<PlanarLeafKey<indInfo*>*> &leafKeys)
{
	SListIterator<PlanarLeafKey<indInfo*>* >  it;
	SListPure<PQLeafKey<edge,indInfo*,bool>*> castLeafKeys;
	for (it = leafKeys.begin(); it.valid(); ++it)
		castLeafKeys.pushBack((PQLeafKey<edge,indInfo*,bool>*) *it);

	return PQTree<edge,indInfo*,bool>::Reduction(castLeafKeys);
}
void UpwardPlanarSubgraphSimple::call(const Graph &G, List<edge> &delEdges)
{
	delEdges.clear();

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

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


	// 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.

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

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

		if (UpwardPlanarity::isUpwardPlanar_singleSource(H) == false) {
			H.delEdge(eH);
			delEdges.pushBack(eG);
		}
	}

}
// Reduction reduced a set of leaves determined by their keys stored 
// in leafKeys. Integer redNumber is for debugging only.
bool PlanarSubgraphPQTree::
Reduction(SListPure<PlanarLeafKey<whaInfo*>*> &leafKeys,
		  SList<PQLeafKey<edge,whaInfo*,bool>*> &eliminatedKeys,
		  int redNumber)
{
	SListPure<PQLeafKey<edge,whaInfo*,bool>*> castLeafKeys;

	SListIterator<PlanarLeafKey<whaInfo*>* >  it;
	for (it = leafKeys.begin(); it.valid(); ++it)
	{
		castLeafKeys.pushBack((PQLeafKey<edge,whaInfo*,bool>*) *it);
		#ifdef OGDF_DEBUG
		if (int(ogdf::debugLevel) >= int(dlHeavyChecks))
		{		
			cout << (*it)->print() << endl;
		}
		#endif
	}

	determineMinRemoveSequence(castLeafKeys,eliminatedKeys);
	removeEliminatedLeaves(eliminatedKeys);

	SListIterator<PQLeafKey<edge,whaInfo*,bool>* >  itn = castLeafKeys.begin();
	SListIterator<PQLeafKey<edge,whaInfo*,bool>* >  itp = itn++;
	for (; itn.valid();)
	{
		if ((*itn)->nodePointer()->status()== WHA_DELETE) 
		{
			itn++;
			castLeafKeys.delSucc(itp);
		}
		else
			itp = itn++;
	}
	
	if ((*castLeafKeys.begin())->nodePointer()->status() == WHA_DELETE)
		castLeafKeys.popFront();

	
	return Reduce(castLeafKeys,redNumber);
}
// Function ReplaceFullRoot either replaces the full root 
// or one full child of a partial root of a pertinent subtree
// by a single P-node  with leaves corresponding the keys stored in leafKeys.
void PlanarSubgraphPQTree::
ReplaceFullRoot(SListPure<PlanarLeafKey<whaInfo*>*> &leafKeys)
{

	PQLeaf<edge,whaInfo*,bool>          *leafPtr     = 0; // dummy
	PQInternalNode<edge,whaInfo*,bool>	*nodePtr     = 0; // dummy
	//PQNodeKey<edge,whaInfo*,bool>	    *nodeInfoPtr = 0; // dummy
	PQNode<edge,whaInfo*,bool>		    *currentNode = 0; // dummy
	SListIterator<PlanarLeafKey<whaInfo*>* >  it;

	if (!leafKeys.empty() && leafKeys.front() == leafKeys.back())
	{
		//ReplaceFullRoot: replace pertinent root by a single leaf
		leafPtr = OGDF_NEW PQLeaf<edge,whaInfo*,bool>(m_identificationNumber++,
                    EMPTY,(PQLeafKey<edge,whaInfo*,bool>*)leafKeys.front());
		exchangeNodes(m_pertinentRoot,(PQNode<edge,whaInfo*,bool>*) leafPtr);
		if (m_pertinentRoot == m_root)
			m_root = (PQNode<edge,whaInfo*,bool>*) leafPtr;      
	}
	else if (!leafKeys.empty()) // at least two leaves
	{
		//replace pertinent root by a $P$-node
		if ((m_pertinentRoot->type() == P_NODE) || 
			(m_pertinentRoot->type() == Q_NODE))
		{
			nodePtr = (PQInternalNode<edge,whaInfo*,bool>*)m_pertinentRoot;
			nodePtr->type(P_NODE);
			nodePtr->status(PERTROOT);
			nodePtr->childCount(0);
			while (!fullChildren(m_pertinentRoot)->empty())
			{	
				currentNode = fullChildren(m_pertinentRoot)->popFrontRet();
				removeChildFromSiblings(currentNode);
			}
		}      
		else if (m_pertinentRoot->type() == LEAF)
		{
			nodePtr = OGDF_NEW PQInternalNode<edge,whaInfo*,bool>(m_identificationNumber++,
														 P_NODE,EMPTY);
			exchangeNodes(m_pertinentRoot,nodePtr);
		}
		SListPure<PQLeafKey<edge,whaInfo*,bool>*> castLeafKeys;
		for (it = leafKeys.begin(); it.valid(); ++it)
			castLeafKeys.pushBack((PQLeafKey<edge,whaInfo*,bool>*) *it);
		addNewLeavesToTree(nodePtr,castLeafKeys);
	}
  
}
示例#10
0
bool isParallelFree(const Graph &G)
{
    if (G.numberOfEdges() <= 1) return true;

    SListPure<edge> edges;
    parallelFreeSort(G,edges);

    SListConstIterator<edge> it = edges.begin();
    edge ePrev = *it, e;
    for(it = ++it; it.valid(); ++it, ePrev = e) {
        e = *it;
        if (ePrev->source() == e->source() && ePrev->target() == e->target())
            return false;
    }

    return true;
}
示例#11
0
int numParallelEdges(const Graph &G)
{
    if (G.numberOfEdges() <= 1) return 0;

    SListPure<edge> edges;
    parallelFreeSort(G,edges);

    int num = 0;
    SListConstIterator<edge> it = edges.begin();
    edge ePrev = *it, e;
    for(it = ++it; it.valid(); ++it, ePrev = e) {
        e = *it;
        if (ePrev->source() == e->source() && ePrev->target() == e->target())
            ++num;
    }

    return num;
}
示例#12
0
bool isParallelFreeUndirected(const Graph &G)
{
    if (G.numberOfEdges() <= 1) return true;

    SListPure<edge> edges;
    EdgeArray<int> minIndex(G), maxIndex(G);
    parallelFreeSortUndirected(G,edges,minIndex,maxIndex);

    SListConstIterator<edge> it = edges.begin();
    edge ePrev = *it, e;
    for(it = ++it; it.valid(); ++it, ePrev = e) {
        e = *it;
        if (minIndex[ePrev] == minIndex[e] && maxIndex[ePrev] == maxIndex[e])
            return false;
    }

    return true;
}
示例#13
0
// Function ReplaceFullRoot either replaces the full root 
// or one full child of a partial root of a pertinent subtree
// by a single P-node  with leaves corresponding the keys stored in leafKeys.
void PlanarPQTree::ReplaceFullRoot(SListPure<PlanarLeafKey<indInfo*>*> &leafKeys)
{
	if (!leafKeys.empty() && leafKeys.front() == leafKeys.back())
	{
		//ReplaceFullRoot: replace pertinent root by a single leaf
		PQLeaf<edge,indInfo*,bool> *leafPtr =
			OGDF_NEW PQLeaf<edge,indInfo*,bool>(m_identificationNumber++,
            EMPTY,(PQLeafKey<edge,indInfo*,bool>*)leafKeys.front());

		exchangeNodes(m_pertinentRoot,(PQNode<edge,indInfo*,bool>*) leafPtr);
		if (m_pertinentRoot == m_root)
			m_root = (PQNode<edge,indInfo*,bool>*) leafPtr;      
		m_pertinentRoot = 0;  // check for this emptyAllPertinentNodes
	}

	else if (!leafKeys.empty()) // at least two leaves
	{
		PQInternalNode<edge,indInfo*,bool> *nodePtr = 0; // dummy
		//replace pertinent root by a $P$-node
		if ((m_pertinentRoot->type() == PQNodeRoot::PNode) || 
			(m_pertinentRoot->type() == PQNodeRoot::QNode))
		{
			nodePtr = (PQInternalNode<edge,indInfo*,bool>*)m_pertinentRoot;
			nodePtr->type(PQNodeRoot::PNode);
			nodePtr->childCount(0);
			while (!fullChildren(m_pertinentRoot)->empty())
				removeChildFromSiblings(fullChildren(m_pertinentRoot)->popFrontRet());
		}      
		else if (m_pertinentRoot->type() == PQNodeRoot::leaf)
		{
			nodePtr = OGDF_NEW PQInternalNode<edge,indInfo*,bool>(m_identificationNumber++,
														 PQNodeRoot::PNode,EMPTY);
			exchangeNodes(m_pertinentRoot,nodePtr);
			m_pertinentRoot = 0;  // check for this emptyAllPertinentNodes
		}
		
		SListPure<PQLeafKey<edge,indInfo*,bool>*> castLeafKeys;
		SListIterator<PlanarLeafKey<indInfo*>* >  it;
		for (it = leafKeys.begin(); it.valid(); ++it)
			castLeafKeys.pushBack((PQLeafKey<edge,indInfo*,bool>*) *it);
		addNewLeavesToTree(nodePtr,castLeafKeys);
	}
}
示例#14
0
// builds expansion graph of i-th biconnected component of the original graph
void ExpansionGraph::init(int i)
{
	OGDF_ASSERT(0 <= i);
	OGDF_ASSERT(i <= m_component.high());

	// remove previous component
	for(node v : nodes) {
		node vOrig = m_vOrig[v];
		if (vOrig)
			m_vCopy[vOrig] = nullptr;
	}
	clear();


	// create new component
	SListConstIterator<edge> it;
	for(it = m_component[i].begin(); it.valid(); ++it)
	{
		edge e = *it;

		edge eCopy = newEdge(getCopy(e->source()),getCopy(e->target()));
		m_eOrig[eCopy] = e;
	}

	// expand vertices
	for(node v : nodes)
	{
		if (original(v) && v->indeg() >= 1 && v->outdeg() >= 1) {
			node vPrime = newNode();
			m_vRep[vPrime] = m_vOrig[v];

			SListPure<edge> edges;
			v->outEdges(edges);

			SListConstIterator<edge> it;
			for(it = edges.begin(); it.valid(); ++it)
				moveSource(*it,vPrime);

			newEdge(v,vPrime);
		}
	}
}
// test if graphAcyclicTest plus edges in tmpAugmented is acyclic
// removes added edges again
bool UpwardPlanarSubgraphSimple::checkAcyclic(
	GraphCopySimple &graphAcyclicTest,
	SList<Tuple2<node,node> > &tmpAugmented)
{
	SListPure<edge> added;

	SListConstIterator<Tuple2<node,node> > it;
	for(it = tmpAugmented.begin(); it.valid(); ++it)
		added.pushBack(graphAcyclicTest.newEdge(
			graphAcyclicTest.copy((*it).x1()),
			graphAcyclicTest.copy((*it).x2())));

	bool acyclic = isAcyclic(graphAcyclicTest);

	SListConstIterator<edge> itE;
	for(itE = added.begin(); itE.valid(); ++itE)
		graphAcyclicTest.delEdge(*itE);

	return acyclic;
}
示例#16
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));

}
示例#17
0
void OptimalRanking::call (const Graph& G, NodeArray<int> &rank)
{
	List<edge> R;

	m_subgraph.get().call(G,R);

	EdgeArray<bool> reversed(G,false);
	for (edge e : R)
		reversed[e] = true;
	R.clear();

	EdgeArray<int> length(G,1);

	if(m_separateMultiEdges) {
		SListPure<edge> edges;
		EdgeArray<int> minIndex(G), maxIndex(G);
		parallelFreeSortUndirected(G, edges, minIndex, maxIndex);

		SListConstIterator<edge> it = edges.begin();
		if(it.valid())
		{
			int prevSrc = minIndex[*it];
			int prevTgt = maxIndex[*it];

			for(it = it.succ(); it.valid(); ++it) {
				edge e = *it;
				if (minIndex[e] == prevSrc && maxIndex[e] == prevTgt)
					length[e] = 2;
				else {
					prevSrc = minIndex[e];
					prevTgt = maxIndex[e];
				}
			}
		}
	}

	EdgeArray<int> cost(G,1);
	doCall(G, rank, reversed, length, cost);
}
示例#18
0
// builds expansion graph of graph G
// for debugging purposes only
void ExpansionGraph::init(const Graph &G)
{
	// remove previous component
	for(node v : nodes) {
		node vOrig = m_vOrig[v];
		if (vOrig)
			m_vCopy[vOrig] = nullptr;
	}
	clear();


	// create new component
	for(node v : G.nodes)
		getCopy(v);

	for(edge e : G.edges)
	{
		edge eCopy = newEdge(getCopy(e->source()),getCopy(e->target()));
		m_eOrig[eCopy] = e;
	}

	// expand vertices
	for(node v : nodes)
	{
		if (original(v) && v->indeg() >= 1 && v->outdeg() >= 1) {
			node vPrime = newNode();

			SListPure<edge> edges;
			v->outEdges(edges);

			SListConstIterator<edge> it;
			for(it = edges.begin(); it.valid(); ++it)
				moveSource(*it,vPrime);

			newEdge(v,vPrime);
		}
	}
}
示例#19
0
// remove "arcs" from visibArcs which we already have in the constraint graph
// (as basic arcs)
void CompactionConstraintGraphBase::removeRedundantVisibArcs(
	SListPure<Tuple2<node,node> > &visibArcs)
{
	// bucket sort list of all edges
	SListPure<edge> all;
	allEdges(all);
	parallelFreeSort(*this,all);

	// bucket sort visibArcs
	BucketFirstIndex bucketSrc;
	visibArcs.bucketSort(0,maxNodeIndex(),bucketSrc);

	BucketSecondIndex bucketTgt;
	visibArcs.bucketSort(0,maxNodeIndex(),bucketTgt);

	// now, in both lists, arcs are sorted by increasing target index,
	// and arcs with the same target index by increasing source index.
	SListConstIterator<edge> itAll = all.begin();
	SListIterator<Tuple2<node,node> > it, itNext, itPrev;

	// for each arc in visibArcs, we check if it is also contained in list all
	for(it = visibArcs.begin(); it.valid(); it = itNext)
	{
		// required since we delete from the list we traverse
		itNext = it.succ();
		int i = (*it).x1()->index();
		int j = (*it).x2()->index();

		// skip all arcs with smaller target index
		while(itAll.valid() && (*itAll)->target()->index() < j)
			++itAll;

		// no more arcs => no more duplicates, so return
		if (!itAll.valid()) break;

		// if target index is j, we also skip all arcs with target index i
		// and source index smaller than i
		while(itAll.valid() && (*itAll)->target()->index() == j && (*itAll)->source()->index() < i)
			++itAll;

		// no more arcs => no more duplicates, so return
		if (!itAll.valid()) break;

		// if (i,j) is already present, we delete it from visibArcs
		if ((*itAll)->source()->index() == i &&
			(*itAll)->target()->index() == j)
		{
			//visibArcs.del(it);
			if (itPrev.valid())
				visibArcs.delSucc(itPrev);
			else
				visibArcs.popFront();
		} else
			itPrev = it;
	}//for visibArcs

	//****************************CHECK for
	//special treatment for cage visibility
	//two cases: input node cage: just compare arbitrary node
	//           merger cage: check first if there are mergers
	itPrev = nullptr;
	for(it = visibArcs.begin(); it.valid(); it = itNext)
	{

		itNext = it.succ();

		OGDF_ASSERT(!m_path[(*it).x1()].empty());
		OGDF_ASSERT(!m_path[(*it).x1()].empty());

		node boundRepresentant1 = m_path[(*it).x1()].front();
		node boundRepresentant2 = m_path[(*it).x2()].front();
		node en1 = m_pPR->expandedNode(boundRepresentant1);
		node en2 = m_pPR->expandedNode(boundRepresentant2);
		//do not allow visibility constraints in fixed cages
		//due to non-planarity with middle position constraints

		if ( ( en1 && en2 ) && ( en1 == en2) )
		{
			if (itPrev.valid()) visibArcs.delSucc(itPrev);
			else visibArcs.popFront();
		}
		else
		{
			//check if its a genmergerspanning vis arc, merge cases later
			node firstn = nullptr, secondn = nullptr;
			for (node n : m_path[(*it).x1()])
			{
				node en = m_pPR->expandedNode(n);
				if (!en) continue;
				if (!(m_pPR->typeOf(n) == Graph::generalizationExpander)) continue;
				else { firstn = en; break; }
			}//for
			for (node n : m_path[(*it).x2()])
			{
				node en = m_pPR->expandedNode(n);
				if (!en) continue;
				if (!(m_pPR->typeOf(n) == Graph::generalizationExpander)) continue;
				else { secondn = en; break; }
			}//for
			if ((firstn && secondn) && (firstn == secondn))
			{
				if (itPrev.valid()) visibArcs.delSucc(itPrev);
				else visibArcs.popFront();
			}
			else itPrev = it;
		}
	}//for visibArcs

}
示例#20
0
文件: PlanRep.cpp 项目: lncosie/ogdf
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
示例#21
0
文件: PlanRep.cpp 项目: lncosie/ogdf
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
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));
}
示例#23
0
	//--------------------------------------------------------------------
	// actual algorithm call
	//--------------------------------------------------------------------
	Module::ReturnType FixEdgeInserterCore::call(
		const Array<edge> &origEdges,
		bool keepEmbedding,
		RemoveReinsertType rrPost,
		double percentMostCrossed)
	{
		double T;
		usedTime(T);

		Module::ReturnType retValue = Module::retFeasible;
		m_runsPostprocessing = 0;

		if(!keepEmbedding) m_pr.embed();
		OGDF_ASSERT(m_pr.representsCombEmbedding() == true);

		if (origEdges.size() == 0)
			return Module::retOptimal;  // nothing to do

		// initialization
		CombinatorialEmbedding E(m_pr);  // embedding of PG

		init(E);
		constructDual(E);

		// m_delFaces and m_newFaces are used by removeEdge()
		// if we can't allocate memory for them, we throw an exception
		if (rrPost != rrNone) {
			m_delFaces = new FaceSetSimple(E);
			if (m_delFaces == nullptr)
				OGDF_THROW(InsufficientMemoryException);

			m_newFaces = new FaceSetPure(E);
			if (m_newFaces == nullptr) {
				delete m_delFaces;
				OGDF_THROW(InsufficientMemoryException);
			}

		// no postprocessing -> no removeEdge()
		} else {
			m_delFaces = nullptr;
			m_newFaces = nullptr;
		}

		SListPure<edge> currentOrigEdges;
		if(rrPost == rrIncremental) {
			for(edge e : m_pr.edges)
				currentOrigEdges.pushBack(m_pr.original(e));
		}

		// insertion of edges
		bool doIncrementalPostprocessing =
			( rrPost == rrIncremental || rrPost == rrIncInserted );
		for(int i = origEdges.low(); i <= origEdges.high(); ++i)
		{
			edge eOrig = origEdges[i];
			storeTypeOfCurrentEdge(eOrig);
			//int eSubGraph = 0;  // edgeSubGraphs-data of eOrig
			//if(edgeSubGraphs!=0) eSubGraph = (*edgeSubGraphs)[eOrig];

			SList<adjEntry> crossed;
			if(m_pCost != nullptr) {
				findWeightedShortestPath(E, eOrig, crossed);
			} else {
				findShortestPath(E, eOrig, crossed);
			}

			insertEdge(E, eOrig, crossed);

			if(doIncrementalPostprocessing) {
				currentOrigEdges.pushBack(eOrig);

				bool improved;
				do {
					++m_runsPostprocessing;
					improved = false;

					for (edge eOrigRR : currentOrigEdges)
					{
						int pathLength = (m_pCost != nullptr) ? costCrossed(eOrigRR) : (m_pr.chain(eOrigRR).size() - 1);
						if (pathLength == 0) continue; // cannot improve

						removeEdge(E, eOrigRR);

						storeTypeOfCurrentEdge(eOrigRR);

						// try to find a better insertion path
						SList<adjEntry> crossed;
						if(m_pCost != nullptr) {
							findWeightedShortestPath(E, eOrigRR, crossed);
						} else {
							findShortestPath(E, eOrigRR, crossed);
						}

						// re-insert edge (insertion path cannot be longer)
						insertEdge(E, eOrigRR, crossed);

						int newPathLength = (m_pCost != nullptr) ? costCrossed(eOrigRR) : (m_pr.chain(eOrigRR).size() - 1);
						OGDF_ASSERT(newPathLength <= pathLength);

						if(newPathLength < pathLength)
							improved = true;
					}
				} while (improved);
			}
		}

		if(!doIncrementalPostprocessing) {
			// postprocessing (remove-reinsert heuristc)
			const int m = m_pr.original().numberOfEdges();
			SListPure<edge> rrEdges;

			switch(rrPost)
			{
			case rrAll:
			case rrMostCrossed:
				for(int i = m_pr.startEdge(); i < m_pr.stopEdge(); ++i)
					rrEdges.pushBack(m_pr.e(i));
				break;

			case rrInserted:
				for(int i = origEdges.low(); i <= origEdges.high(); ++i)
					rrEdges.pushBack(origEdges[i]);
				break;

			case rrNone:
			case rrIncremental:
			case rrIncInserted:
				break;
			}

			// marks the end of the interval of rrEdges over which we iterate
			// initially set to invalid iterator which means all edges
			SListConstIterator<edge> itStop;

			bool improved;
			do {
				// abort postprocessing if time limit reached
				if (m_timeLimit >= 0 && m_timeLimit <= usedTime(T)) {
					retValue = Module::retTimeoutFeasible;
					break;
				}

				++m_runsPostprocessing;
				improved = false;

				if(rrPost == rrMostCrossed)
				{
					FEICrossingsBucket bucket(&m_pr);
					rrEdges.bucketSort(bucket);

					const int num = int(0.01 * percentMostCrossed * m);
					itStop = rrEdges.get(num);
				}

				SListConstIterator<edge> it;
				for(it = rrEdges.begin(); it != itStop; ++it)
				{
					edge eOrig = *it;

					int pathLength = (m_pCost != nullptr) ? costCrossed(eOrig) : (m_pr.chain(eOrig).size() - 1);
					if (pathLength == 0) continue; // cannot improve

					removeEdge(E, eOrig);

					storeTypeOfCurrentEdge(eOrig);

					// try to find a better insertion path
					SList<adjEntry> crossed;
					if(m_pCost != nullptr) {
						findWeightedShortestPath(E, eOrig, crossed);
					} else {
						findShortestPath(E, eOrig, crossed);
					}

					// re-insert edge (insertion path cannot be longer)
					insertEdge(E, eOrig, crossed);

					// we cannot find a shortest path that is longer than before!
					int newPathLength = (m_pCost != nullptr) ? costCrossed(eOrig) : (m_pr.chain(eOrig).size() - 1);
					OGDF_ASSERT(newPathLength <= pathLength);

					if(newPathLength < pathLength)
						improved = true;
				}
			} while (improved);
		}

		// verify computed planarization
		OGDF_ASSERT(m_pr.representsCombEmbedding());

		// free resources
		cleanup();

		return retValue;
	}
示例#24
0
//---------------------------------------------------------
// actual call (called by all variations of call)
//   crossing of generalizations is forbidden if forbidCrossingGens = true
//   edge costs are obeyed if costOrig != 0
//
Module::ReturnType FixedEmbeddingInserter::doCall(
	PlanRep &PG,
	const List<edge> &origEdges,
	bool forbidCrossingGens,
	const EdgeArray<int>  *costOrig,
	const EdgeArray<bool> *forbiddenEdgeOrig,
	const EdgeArray<unsigned int> *edgeSubGraph)
{
  
	double T;
	usedTime(T);
	
	ReturnType retValue = retFeasible;
	m_runsPostprocessing = 0;

	PG.embed(); 
	OGDF_ASSERT(PG.representsCombEmbedding() == true);

	if (origEdges.size() == 0)
		return retOptimal;  // nothing to do

	// initialization
	CombinatorialEmbedding E(PG);  // embedding of PG

	m_dual.clear();
	m_primalAdj.init(m_dual);
	m_nodeOf.init(E);

	// construct dual graph
	m_primalIsGen.init(m_dual,false);

	OGDF_ASSERT(forbidCrossingGens == false || forbiddenEdgeOrig == 0);

	if(forbidCrossingGens)
		constructDualForbidCrossingGens((const PlanRepUML&)PG,E);
	else
		constructDual(PG,E,forbiddenEdgeOrig);

	// m_delFaces and m_newFaces are used by removeEdge()
	// if we can't allocate memory for them, we throw an exception
	if (removeReinsert() != rrNone) {
		m_delFaces = new FaceSetSimple(E);
		if (m_delFaces == 0)
			OGDF_THROW(InsufficientMemoryException);

		m_newFaces = new FaceSetPure(E);
		if (m_newFaces == 0) {
			delete m_delFaces;
			OGDF_THROW(InsufficientMemoryException);
		}

	// no postprocessing -> no removeEdge()
	} else {
		m_delFaces = 0;
		m_newFaces = 0;
	}

	SListPure<edge> currentOrigEdges;
	if(removeReinsert() == rrIncremental) {
		edge e;
		forall_edges(e,PG)
			currentOrigEdges.pushBack(PG.original(e));
	}

	// insertion of edges
	ListConstIterator<edge> it;
	for(it = origEdges.begin(); it.valid(); ++it)
	{
		edge eOrig = *it;

		int eSubGraph = 0;  // edgeSubGraph-data of eOrig
		if(edgeSubGraph!=0) eSubGraph = (*edgeSubGraph)[eOrig];

		SList<adjEntry> crossed;
		if(costOrig != 0) {
			findShortestPath(PG, E, *costOrig,
				PG.copy(eOrig->source()),PG.copy(eOrig->target()),
				forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrig) : Graph::association,
				crossed, edgeSubGraph, eSubGraph);
		} else {
			findShortestPath(E,
				PG.copy(eOrig->source()),PG.copy(eOrig->target()),
				forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrig) : Graph::association,
				crossed);
		}

		insertEdge(PG,E,eOrig,crossed,forbidCrossingGens,forbiddenEdgeOrig);
		
		if(removeReinsert() == rrIncremental) {
			currentOrigEdges.pushBack(eOrig);

			bool improved;
			do {
				++m_runsPostprocessing;
				improved = false;
				
				SListConstIterator<edge> itRR;
				for(itRR = currentOrigEdges.begin(); itRR.valid(); ++itRR)
				{
					edge eOrigRR = *itRR;
		
					int pathLength;
					if(costOrig != 0)
						pathLength = costCrossed(eOrigRR,PG,*costOrig,edgeSubGraph);
					else
						pathLength = PG.chain(eOrigRR).size() - 1;
					if (pathLength == 0) continue; // cannot improve
		
					removeEdge(PG,E,eOrigRR,forbidCrossingGens,forbiddenEdgeOrig);
		
					// try to find a better insertion path
					SList<adjEntry> crossed;
					if(costOrig != 0) {
						int eSubGraph = 0;  // edgeSubGraph-data of eOrig
						if(edgeSubGraph!=0) eSubGraph = (*edgeSubGraph)[eOrigRR];

						findShortestPath(PG, E, *costOrig,
							PG.copy(eOrigRR->source()),PG.copy(eOrigRR->target()),
							forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrigRR) : Graph::association,
							crossed, edgeSubGraph, eSubGraph);
					} else {
						findShortestPath(E,
							PG.copy(eOrigRR->source()),PG.copy(eOrigRR->target()),
							forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrigRR) : Graph::association,
							crossed);
					}
					
					// re-insert edge (insertion path cannot be longer)
					insertEdge(PG,E,eOrigRR,crossed,forbidCrossingGens,forbiddenEdgeOrig);
		
					int newPathLength = (costOrig != 0) ? costCrossed(eOrigRR,PG,*costOrig,edgeSubGraph) : (PG.chain(eOrigRR).size() - 1);
					OGDF_ASSERT(newPathLength <= pathLength);
					
					if(newPathLength < pathLength)
						improved = true;
				}
			} while (improved);
		}
	}

	const Graph &G = PG.original();
	if(removeReinsert() != rrIncremental) {
		// postprocessing (remove-reinsert heuristc)
		SListPure<edge> rrEdges;
	
		switch(removeReinsert())
		{
		case rrAll:
		case rrMostCrossed: {
				const List<node> &origInCC = PG.nodesInCC();
				ListConstIterator<node> itV;
	
				for(itV = origInCC.begin(); itV.valid(); ++itV) {
					node vG = *itV;
					adjEntry adj;
					forall_adj(adj,vG) {
						if ((adj->index() & 1) == 0) continue;
						edge eG = adj->theEdge();
						rrEdges.pushBack(eG);
					}
				}
			}
			break;
	
		case rrInserted:
			for(ListConstIterator<edge> it = origEdges.begin(); it.valid(); ++it)
				rrEdges.pushBack(*it);
			break;

		case rrNone:
		case rrIncremental:
			break;
		}
	
		// marks the end of the interval of rrEdges over which we iterate
		// initially set to invalid iterator which means all edges
		SListConstIterator<edge> itStop;
	
		bool improved;
		do {
			// abort postprocessing if time limit reached
			if (m_timeLimit >= 0 && m_timeLimit <= usedTime(T)) {
				retValue = retTimeoutFeasible;
				break;
			}
				
			++m_runsPostprocessing;
			improved = false;
	
			if(removeReinsert() == rrMostCrossed)
			{
				FEICrossingsBucket bucket(&PG);
				rrEdges.bucketSort(bucket);
	
				const int num = int(0.01 * percentMostCrossed() * G.numberOfEdges());
				itStop = rrEdges.get(num);
			}
	
			SListConstIterator<edge> it;
			for(it = rrEdges.begin(); it != itStop; ++it)
			{
				edge eOrig = *it;
							
				// remove only if crossings on edge;
				// in especially: forbidden edges are never handled by postprocessing
				//   since there are no crossings on such edges
				int pathLength;
				if(costOrig != 0)
					pathLength = costCrossed(eOrig,PG,*costOrig,edgeSubGraph);
				else
					pathLength = PG.chain(eOrig).size() - 1;
				if (pathLength == 0) continue; // cannot improve
	
				removeEdge(PG,E,eOrig,forbidCrossingGens,forbiddenEdgeOrig);
	
				// try to find a better insertion path
				SList<adjEntry> crossed;
				if(costOrig != 0) {
					int eSubGraph = 0;  // edgeSubGraph-data of eOrig
					if(edgeSubGraph!=0) eSubGraph = (*edgeSubGraph)[eOrig];

					findShortestPath(PG, E, *costOrig,
						PG.copy(eOrig->source()),PG.copy(eOrig->target()),
						forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrig) : Graph::association,
						crossed, edgeSubGraph, eSubGraph);
				} else {
					findShortestPath(E,
						PG.copy(eOrig->source()),PG.copy(eOrig->target()),
						forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrig) : Graph::association,
						crossed);
				}
	
				// re-insert edge (insertion path cannot be longer)
				insertEdge(PG,E,eOrig,crossed,forbidCrossingGens,forbiddenEdgeOrig);
	
				int newPathLength = (costOrig != 0) ? costCrossed(eOrig,PG,*costOrig,edgeSubGraph) : (PG.chain(eOrig).size() - 1);
				OGDF_ASSERT(newPathLength <= pathLength);
				
				if(newPathLength < pathLength)
					improved = true;
			}
		} while(improved); // iterate as long as we improve
	}
示例#25
0
// separate pertinent nodes in the lists of possible different minor-types
void FindKuratowskis::splitInMinorTypes(
			const SListPure<adjEntry>& externalFacePath,
			int marker)
{
	// mark nodes, which are before stopX or behind stopY in CCW-traversal and add
	// all extern nodes strictly between stopX and stopY to list
	// externE for minor E (pertinent nodes are considered because of the
	// position of z left or right of w)
	SListConstIterator<adjEntry> itExtern;
	SListIterator<WInfo> it = k.wNodes.begin();
	node x;
	bool between = false;
	SListPure<WInfo*> infoList;
	SListIterator<WInfo*> itList;
	ExternE externEdummy;
	// compute list of externE nodes
	for (itExtern=externalFacePath.begin(); itExtern.valid(); ++itExtern) {
		x = (*itExtern)->theNode();
		if (x==k.stopX || x==k.stopY) {
			between = (between==false) ? true : false;
		} else {
			if (!between) {
				m_wasHere[x]=marker;
			} else {
				if (pBM->externallyActive(x,k.V_DFI)) {
					externEdummy.theNode = x;

					// check minor type B and save extern linkage
					if (it.valid() && (*it).w==x &&
							!m_pertinentRoots[x].empty() &&
							m_lowPoint[m_nodeFromDFI[-m_dfi[m_pertinentRoots[x].back()]]]
							< k.V_DFI) {
						WInfo& info(*it);

						// checking minor type B
						info.minorType |= WInfo::B;
						// mark extern node for later extraction
						externEdummy.startnodes.pushBack(0);
						// create externE-list
						k.externE.pushBack(externEdummy);
						// save extern linkage
						info.externEStart = k.externE.rbegin();
						info.externEEnd = k.externE.rbegin();
					} else {
						// create externE-list
						externEdummy.startnodes.clear();
						k.externE.pushBack(externEdummy);
					}

					// save for each wNode the first externally active successor
					// on the external face
					for (itList = infoList.begin(); itList.valid(); ++itList)
						(*itList)->firstExternEAfterW = x;
					infoList.clear();


				}

				// get appropriate WInfo
				if (it.valid() && (*it).w==x) {
					infoList.pushBack(&(*it));
					++it;
				}
			}
		}
	}

	// divide wNodes in different minor types
	// avoids multiple computation of the externE range
	itExtern = externalFacePath.begin();
	SListIterator<ExternE> itExternE = k.externE.begin();
	WInfo* oldInfo = NULL;
	for (it=k.wNodes.begin(); it.valid(); ++it) {
		WInfo& info(*it);

		// checking minor type A
		if (k.RReal!=k.V) info.minorType |= WInfo::A;

		// if a XYPath exists
		if (info.highestXYPath!=NULL) {
			if (m_wasHere[info.highestXYPath->front()->theNode()]==marker)
				info.pxAboveStopX = true;
			if (m_wasHere[info.highestXYPath->back()->theNode()]==marker)
				info.pyAboveStopY = true;

			// checking minor type C
			if (info.pxAboveStopX || info.pyAboveStopY)
				info.minorType |= WInfo::C;

			// checking minor type D
			if (info.zPath!=NULL) info.minorType |= WInfo::D;

			// checking minor type E
			if (!k.externE.empty()) {
				node t;

				// compute valid range of externE-nodes in linear time
				if (oldInfo!=NULL && info.highestXYPath==oldInfo->highestXYPath) {
					// found the same highestXYPath as before
					info.externEStart = oldInfo->externEStart;
					info.externEEnd = oldInfo->externEEnd;
					if (oldInfo->minorType & WInfo::E) info.minorType |= WInfo::E;
				} else {
					// compute range of a new highestXYPath
					node px;
					if (info.pxAboveStopX) px = k.stopX;
						else px = info.highestXYPath->front()->theNode();
					node py;
					if (info.pyAboveStopY) py = k.stopY;
						else py = info.highestXYPath->back()->theNode();
					while ((*itExtern)->theNode() != px) ++itExtern;
					t = (*(++itExtern))->theNode();
					node start = NULL;
					node end = NULL;
					while (t != py) {
						if (pBM->externallyActive(t,k.V_DFI)) {
							if (start==NULL) start = t;
							end = t;
						}
						t = (*(++itExtern))->theNode();
					}
					if (start != NULL) {
						while ((*itExternE).theNode != start) ++itExternE;
						info.externEStart = itExternE;
						// mark node to extract external subgraph later
						(*itExternE).startnodes.pushBack(0);
						node temp = start;
						while (temp != end) {
							temp = (*++itExternE).theNode;
							// mark node to extract external subgraph later
							(*itExternE).startnodes.pushBack(0);
						}
						info.externEEnd = itExternE;
						info.minorType |= WInfo::E;
					}
					oldInfo = &info;
				}
			}
		}

		/*
		// use this to find special kuratowski-structures
		if ((info.minorType & (WInfo::A|WInfo::B|WInfo::C|WInfo::D|WInfo::E)) ==
			(WInfo::A|WInfo::B|WInfo::C|WInfo::D|WInfo::E)) {
			char t; cin >> t;
		}
		*/
	}

	// extract the externalSubgraph of all saved externally active nodes
	// exclude the already extracted minor b-types
	#ifdef OGDF_DEBUG
	int visited = m_nodeMarker+1;
	#endif
	for (itExternE=k.externE.begin(); itExternE.valid(); ++itExternE) {
		if ((*itExternE).startnodes.empty()) continue;

		ExternE& externE(*itExternE);
		externE.startnodes.clear();
		if (m_bundles) {
			OGDF_ASSERT(m_wasHere[externE.theNode] < visited);
			extractExternalSubgraphBundles(externE.theNode,k.V_DFI,
										k.externalSubgraph,++m_nodeMarker);
		} else {
			extractExternalSubgraph(externE.theNode,k.V_DFI,externE.startnodes,
															externE.endnodes);
			SListIterator<int> itInt;
			SListPure<edge> dummy;
			for (itInt = externE.startnodes.begin(); itInt.valid(); ++itInt)
				externE.externalPaths.pushBack(dummy);
		}
	}
}
示例#26
0
void planarBiconnectedGraph(Graph &G, int n, int m, bool multiEdges)
{
	if (n < 3) n = 3;
	if (m < n) m = n;
	if (m > 3*n-6) m = 3*n-6;

	int ke = n-3, kf = m-n;

	G.clear();
	
	Array<edge> edges(m);
	Array<face> bigFaces(m);
	//random_source S;

	// we start with a triangle
	node v1 = G.newNode(), v2 = G.newNode(), v3 = G.newNode();
	edges[0] = G.newEdge(v1,v2);
	edges[1] = G.newEdge(v2,v3);
	edges[2] = G.newEdge(v3,v1);

	CombinatorialEmbedding E(G);
	FaceArray<int> posBigFaces(E);
	int nBigFaces = 0, nEdges = 3;

	while(ke+kf > 0) {
		int p = randomNumber(1,ke+kf);

		if (nBigFaces == 0 || p <= ke) {
			edge e  = edges[randomNumber(0,nEdges-1)];
			face f  = E.rightFace(e->adjSource());
			face fr = E.rightFace(e->adjTarget());

			edges[nEdges++] = E.split(e);

			if (f->size() == 4) {
				posBigFaces[f] = nBigFaces;
				bigFaces[nBigFaces++] = f;
			}
			if (fr->size() == 4) {
				posBigFaces[fr] = nBigFaces;
				bigFaces[nBigFaces++] = fr;
			}

			ke--;

		} else {
			int pos = randomNumber(0,nBigFaces-1);
			face f = bigFaces[pos];
			int df = f->size();
			int i = randomNumber(0,df-1), j = randomNumber(2,df-2);

			adjEntry adj1;
			for (adj1 = f->firstAdj(); i > 0; adj1 = adj1->faceCycleSucc())
				i--;

			adjEntry adj2;
			for (adj2 = adj1; j > 0; adj2 = adj2->faceCycleSucc())
				j--;

			edge e = E.splitFace(adj1,adj2);
			edges[nEdges++] = e;

			face f1 = E.rightFace(e->adjSource());
			face f2 = E.rightFace(e->adjTarget());

			bigFaces[pos] = f1;
			posBigFaces[f1] = pos;
			if (f2->size() >= 4) {
				posBigFaces[f2] = nBigFaces;
				bigFaces[nBigFaces++] = f2;
			}
			if (f1->size() == 3) {
				bigFaces[pos] = bigFaces[--nBigFaces];
			}

			kf--;
		}
	}

	if (multiEdges == false) {
		SListPure<edge> allEdges;
		EdgeArray<int> minIndex(G), maxIndex(G);

		parallelFreeSortUndirected(G,allEdges,minIndex,maxIndex);

		SListConstIterator<edge> it = allEdges.begin();
		edge ePrev = *it, e;
		for(it = ++it; it.valid(); ++it, ePrev = e) {
			e = *it;
			if (minIndex[ePrev] == minIndex[e] &&
				maxIndex[ePrev] == maxIndex[e])
			{
				G.move(e,
					e->adjTarget()->faceCycleSucc()->twin(), ogdf::before,
					e->adjSource()->faceCycleSucc()->twin(), ogdf::before);
			}
		}

	}
}
示例#27
0
void planarCNBGraph(Graph &G, int n, int m,	int b)	
{
	G.clear();
	if (b <= 0) b = 1;
	if (n <= 0) n = 1;
	if ((m <= 0) || (m > 3*n-6)) m = 3*n-6;
	
	node cutv;
	G.newNode();
	
	for (int nB=1; nB<=b; nB++){
		cutv = G.chooseNode();
		// set number of nodes for the current created block
		int actN = randomNumber(1, n);
		
		node v1 = G.newNode();
		
		if (actN <= 1){
			G.newEdge(v1, cutv);
		}
		else
			if (actN == 2){
				node v2 = G.newNode();
				G.newEdge(v1, v2);
				
				int rnd = randomNumber(1, 2);
				edge newE;
				int rnd2 = randomNumber(1, 2);
				if (rnd == 1){
					newE = G.newEdge(v1, cutv);
				}
				else{
					newE = G.newEdge(v2, cutv);
				}
				if (rnd2 == 1){
					G.contract(newE);
				}
			}
			else{
				// set number of edges for the current created block
				int actM;
				if (m > 3*actN-6)
					actM = randomNumber(1, 3*actN-6);
				else
					actM = randomNumber(1, m);
				if (actM < actN)
					actM = actN;
				
				int ke = actN-3, kf = actM-actN;
				
				Array<node> nodes(actN);
				Array<edge> edges(actM);
				Array<face> bigFaces(actM);
					
				// we start with a triangle
				node v2 = G.newNode(), v3 = G.newNode();
				nodes[0] = v1;
				nodes[1] = v2;
				nodes[2] = v3;
				edges[0] = G.newEdge(v1,v2);
				edges[1] = G.newEdge(v2,v3);
				edges[2] = G.newEdge(v3,v1);
				
				int actInsertedNodes = 3;
				
				CombinatorialEmbedding E(G);
				FaceArray<int> posBigFaces(E);
				int nBigFaces = 0, nEdges = 3;
				
				while(ke+kf > 0) {
					int p = randomNumber(1,ke+kf);
			
					if (nBigFaces == 0 || p <= ke) {
						int eNr = randomNumber(0,nEdges-1);
						edge e  = edges[eNr];
						face f  = E.rightFace(e->adjSource());
						face fr = E.rightFace(e->adjTarget());
						
						node u = e->source();
						node v = e->target();
						
						edges[nEdges++] = E.split(e);
						
						if (e->source() != v && e->source() != u)
							nodes[actInsertedNodes++] = e->source();
						else
							nodes[actInsertedNodes++] = e->target();

						if (f->size() == 4) {
							posBigFaces[f] = nBigFaces;
							bigFaces[nBigFaces++] = f;
						}
						if (fr->size() == 4) {
							posBigFaces[fr] = nBigFaces;
							bigFaces[nBigFaces++] = fr;
						}
			
						ke--;
					}
					else {						
						int pos = randomNumber(0,nBigFaces-1);
						face f = bigFaces[pos];
						int df = f->size();
						int i = randomNumber(0,df-1), j = randomNumber(2,df-2);
			
						adjEntry adj1;
						for (adj1 = f->firstAdj(); i > 0; adj1 = adj1->faceCycleSucc())
							i--;
			
						adjEntry adj2;
						for (adj2 = adj1; j > 0; adj2 = adj2->faceCycleSucc())
							j--;
			
						edge e = E.splitFace(adj1,adj2);
						edges[nEdges++] = e;
						
						face f1 = E.rightFace(e->adjSource());
						face f2 = E.rightFace(e->adjTarget());
			
						bigFaces[pos] = f1;
						posBigFaces[f1] = pos;
						if (f2->size() >= 4) {
							posBigFaces[f2] = nBigFaces;
							bigFaces[nBigFaces++] = f2;
						}
						if (f1->size() == 3) {
							bigFaces[pos] = bigFaces[--nBigFaces];
						}
						
						kf--;
					}
				}
						
				// delete multi edges
				SListPure<edge> allEdges;
				EdgeArray<int> minIndex(G), maxIndex(G);
		
				parallelFreeSortUndirected(G,allEdges,minIndex,maxIndex);
		
				SListConstIterator<edge> it = allEdges.begin();
				edge ePrev = *it, e;
				for(it = ++it; it.valid(); ++it, ePrev = e) {
					e = *it;
					if (minIndex[ePrev] == minIndex[e] &&
						maxIndex[ePrev] == maxIndex[e])
					{
						G.move(e,
							e->adjTarget()->faceCycleSucc()->twin(), ogdf::before,
							e->adjSource()->faceCycleSucc()->twin(), ogdf::before);
					}
				}
				
				node cutv2 = nodes[randomNumber(0,actN-1)];
				
				int rnd = randomNumber(1,2);
				edge newE = G.newEdge(cutv2, cutv);
				if (rnd == 1){
					G.contract(newE);
				}
			}
	}
};
示例#28
0
	//--------------------------------------------------------------------
	// actual algorithm call
	//--------------------------------------------------------------------
	Module::ReturnType VarEdgeInserterDynCore::call(
		const Array<edge> &origEdges,
		RemoveReinsertType rrPost,
		double percentMostCrossed)
	{
		double T;
		usedTime(T);

		Module::ReturnType retValue = Module::retFeasible;
		m_runsPostprocessing = 0;

		if (origEdges.size() == 0)
			return Module::retOptimal;  // nothing to do

		SListPure<edge> currentOrigEdges;

		if (rrPost == rrIncremental) {
			for (edge e : m_pr.edges)
				currentOrigEdges.pushBack(m_pr.original(e));

			// insertion of edges
			for (int i = origEdges.low(); i <= origEdges.high(); ++i)
			{
				edge eOrig = origEdges[i];
				storeTypeOfCurrentEdge(eOrig);

				m_pBC = createBCandSPQRtrees();
				SList<adjEntry> eip;
				insert(eOrig, eip);
				m_pr.insertEdgePath(eOrig, eip);
				delete m_pBC;

				currentOrigEdges.pushBack(eOrig);

				bool improved;
				do {
					++m_runsPostprocessing;
					improved = false;

					for (edge eOrigRR : currentOrigEdges)
					{
						int pathLength = (m_pCost != nullptr) ? costCrossed(eOrigRR) : (m_pr.chain(eOrigRR).size() - 1);
						if (pathLength == 0) continue; // cannot improve

						m_pr.removeEdgePath(eOrigRR);

						storeTypeOfCurrentEdge(eOrigRR);

						m_pBC = createBCandSPQRtrees();
						SList<adjEntry> eip;
						insert(eOrigRR, eip);
						m_pr.insertEdgePath(eOrigRR, eip);
						delete m_pBC;

						int newPathLength = (m_pCost != nullptr) ? costCrossed(eOrigRR) : (m_pr.chain(eOrigRR).size() - 1);
						OGDF_ASSERT(newPathLength <= pathLength);

						if (newPathLength < pathLength)
							improved = true;
					}
				} while (improved);
			}

		}
		else {

			// insertion of edges
			m_pBC = createBCandSPQRtrees();

			for (int i = origEdges.low(); i <= origEdges.high(); ++i)
			{
				edge eOrig = origEdges[i];
				storeTypeOfCurrentEdge(eOrig);

				SList<adjEntry> eip;
				insert(eOrig, eip);
				m_pBC->insertEdgePath(eOrig, eip);
			}

			delete m_pBC;

			// postprocessing (remove-reinsert heuristc)
			const int m = m_pr.original().numberOfEdges();
			SListPure<edge> rrEdges;

			switch (rrPost)
			{
			case rrAll:
			case rrMostCrossed:
				for (int i = m_pr.startEdge(); i < m_pr.stopEdge(); ++i)
					rrEdges.pushBack(m_pr.e(i));
				break;

			case rrInserted:
				for (int i = origEdges.low(); i <= origEdges.high(); ++i)
					rrEdges.pushBack(origEdges[i]);
				break;

			case rrNone:
			case rrIncremental:
			case rrIncInserted:
				break;
			}

			// marks the end of the interval of rrEdges over which we iterate
			// initially set to invalid iterator which means all edges
			SListConstIterator<edge> itStop;

			bool improved;
			do {
				// abort postprocessing if time limit reached
				if (m_timeLimit >= 0 && m_timeLimit <= usedTime(T)) {
					retValue = Module::retTimeoutFeasible;
					break;
				}

				++m_runsPostprocessing;
				improved = false;

				if (rrPost == rrMostCrossed)
				{
					VEICrossingsBucket bucket(&m_pr);
					rrEdges.bucketSort(bucket);

					const int num = int(0.01 * percentMostCrossed * m);
					itStop = rrEdges.get(num);
				}

				SListConstIterator<edge> it;
				for (it = rrEdges.begin(); it != itStop; ++it)
				{
					edge eOrig = *it;

					int pathLength = (m_pCost != nullptr) ? costCrossed(eOrig) : (m_pr.chain(eOrig).size() - 1);
					if (pathLength == 0) continue; // cannot improve

					m_pr.removeEdgePath(eOrig);

					storeTypeOfCurrentEdge(eOrig);

					m_pBC = createBCandSPQRtrees();
					SList<adjEntry> eip;
					insert(eOrig, eip);
					m_pr.insertEdgePath(eOrig, eip);
					delete m_pBC;

					// we cannot find a shortest path that is longer than before!
					int newPathLength = (m_pCost != nullptr) ? costCrossed(eOrig) : (m_pr.chain(eOrig).size() - 1);
					OGDF_ASSERT(newPathLength <= pathLength);

					if (newPathLength < pathLength)
						improved = true;
				}

			} while (improved);
		}


#ifdef OGDF_DEBUG
		bool isPlanar =
#endif
			planarEmbed(m_pr);

		OGDF_ASSERT(isPlanar);

		m_pr.removePseudoCrossings();
		OGDF_ASSERT(m_pr.representsCombEmbedding());

		return retValue;
	}
示例#29
0
void print_edge_list(SListPure<edge> & list)
{
  for (SListPure<edge>::iterator it = list.begin(); it.valid(); ++it)
    print_edge(*it);
  printf("\n");
}
示例#30
0
void EmbedPQTree::ReplaceFullRoot(
	SListPure<PlanarLeafKey<indInfo*>*> &leafKeys,
	SListPure<PQBasicKey<edge,indInfo*,bool>*> &frontier,
	node v,
	bool addIndicator,
	PQNode<edge,indInfo*,bool> *opposite)
{
	EmbedIndicator *newInd = 0; 

	front(m_pertinentRoot,frontier);
	if (addIndicator)
	{
		indInfo *newInfo = OGDF_NEW indInfo(v);
		embedKey *nodeInfoPtr = OGDF_NEW embedKey(newInfo);
		newInd = OGDF_NEW EmbedIndicator(m_identificationNumber++,
			(PQNodeKey<edge,indInfo*,bool>*)nodeInfoPtr);
		newInd->setNodeInfo(nodeInfoPtr);
		nodeInfoPtr->setNodePointer(newInd);
	}

	if (!leafKeys.empty() && leafKeys.front() == leafKeys.back())
	{
		//ReplaceFullRoot: replace pertinent root by a single leaf
		if (addIndicator)
		{
			opposite = m_pertinentRoot->getNextSib(opposite);
			if (!opposite) // m_pertinentRoot is endmost child
			{
				addNodeToNewParent(m_pertinentRoot->parent(),newInd,
								   m_pertinentRoot,opposite);
			}
			else 
				addNodeToNewParent(0,newInd,m_pertinentRoot,opposite);

			// Setting the sibling pointers into opposite direction of
			// scanning the front allows to track swaps of the indicator
			newInd->changeSiblings(m_pertinentRoot,0);
			newInd->changeSiblings(opposite,0);
			newInd->putSibling(m_pertinentRoot,LEFT);
			newInd->putSibling(opposite,RIGHT);
		}
		PQLeaf<edge,indInfo*,bool> *leafPtr =
			OGDF_NEW PQLeaf<edge,indInfo*,bool>(m_identificationNumber++,
			EMPTY,(PQLeafKey<edge,indInfo*,bool>*)leafKeys.front());
		exchangeNodes(m_pertinentRoot,(PQNode<edge,indInfo*,bool>*) leafPtr);
 		if (m_pertinentRoot == m_root)
			m_root = (PQNode<edge,indInfo*,bool>*) leafPtr;      
		m_pertinentRoot = 0;  // check for this emptyAllPertinentNodes
	}

	else if (!leafKeys.empty()) // at least two leaves
	{
		//replace pertinent root by a $P$-node
		if (addIndicator)
		{
			opposite = m_pertinentRoot->getNextSib(opposite);
			if (!opposite) // m_pertinentRoot is endmost child
			{
				addNodeToNewParent(m_pertinentRoot->parent(),newInd,
								   m_pertinentRoot,opposite);
			}
			else 
				addNodeToNewParent(0,newInd,m_pertinentRoot,opposite);

			// Setting the sibling pointers into opposite direction of
			// scanning the front allows to track swaps of the indicator
			newInd->changeSiblings(m_pertinentRoot,0);
			newInd->changeSiblings(opposite,0);
			newInd->putSibling(m_pertinentRoot,LEFT);
			newInd->putSibling(opposite,RIGHT);
		}

		PQInternalNode<edge,indInfo*,bool> *nodePtr = 0; // dummy
		if ((m_pertinentRoot->type() == PQNodeRoot::PNode) || 
			(m_pertinentRoot->type() == PQNodeRoot::QNode))
		{
			nodePtr = (PQInternalNode<edge,indInfo*,bool>*)m_pertinentRoot;
			nodePtr->type(PQNodeRoot::PNode);
			nodePtr->childCount(0);
			while (!fullChildren(m_pertinentRoot)->empty())
			{	
				PQNode<edge,indInfo*,bool> *currentNode =
					fullChildren(m_pertinentRoot)->popFrontRet();
				removeChildFromSiblings(currentNode);
			}
		}      
		else if (m_pertinentRoot->type() == PQNodeRoot::leaf)
		{
			nodePtr = OGDF_NEW PQInternalNode<edge,indInfo*,bool>(m_identificationNumber++,
														 PQNodeRoot::PNode,EMPTY);
			exchangeNodes(m_pertinentRoot,nodePtr);
			m_pertinentRoot = 0;  // check for this emptyAllPertinentNodes
		}
	
		SListPure<PQLeafKey<edge,indInfo*,bool>*> castLeafKeys;
		SListIterator<PlanarLeafKey<indInfo*>* > it;
		for (it = leafKeys.begin(); it.valid(); ++it)
			castLeafKeys.pushBack((PQLeafKey<edge,indInfo*,bool>*) *it);
		addNewLeavesToTree(nodePtr,castLeafKeys);
	}  
}