Beispiel #1
0
	void SimpleEmbedder::call(Graph& G, adjEntry& adjExternal)
	{
		OGDF_ASSERT(isPlanar(G));

		//----------------------------------------------------------
		//
		// determine embedding of G
		//

		// We currently compute any embedding and choose the maximal face
		// as external face

		// if we use FixedEmbeddingInserterOld, we have to re-use the computed
		// embedding, otherwise crossing nodes can turn into "touching points"
		// of edges (alternatively, we could compute a new embedding and
		// finally "remove" such unnecessary crossings).
		adjExternal = nullptr;
		if(!G.representsCombEmbedding())
			planarEmbed(G);

		if (G.numberOfEdges() > 0)
		{
			CombinatorialEmbedding E(G);
			//face fExternal = E.maximalFace();
			face fExternal = findBestExternalFace(G, E);
			adjExternal = fExternal->firstAdj();
		}
	}
//-----------------------------------------------------------------------------
// call function: compute an UML layout for graph umlGraph
//-----------------------------------------------------------------------------
void PlanarizationLayoutUML::call(UMLGraph &umlGraph)
{
	m_nCrossings = 0;

	if(umlGraph.constGraph().empty())
		return;

	// check necessary preconditions
	preProcess(umlGraph);

	//---------------------------------------------------
	// preprocessing: insert a merger for generalizations
	umlGraph.insertGenMergers();

	PlanRepUML pr(umlGraph);
	const int numCC = pr.numberOfCCs();

	// (width,height) of the layout of each connected component
	Array<DPoint> boundingBox(numCC);


	// alignment section (should not be here, because planarlayout should
	// not know about the meaning of layouter options and should not cope
	// with them), move later
	// we have to distinguish between cc's with and without generalizations
	// if the alignment option is set
	int l_layoutOptions = m_planarLayouter.get().getOptions();
	bool l_align = ((l_layoutOptions & umlOpAlign) > 0);
	//end alignment section

	//------------------------------------------
	//now planarize CCs and apply drawing module
	for(int i = 0; i < numCC; ++i)
	{
		//---------------------------------------
		// 1. crossing minimization
		//---------------------------------------

		// alignment: check wether gens exist, special treatment is necessary
		bool l_gensExist = false; // set this for all CC's, start with first gen,
		//this setting can be mixed among CC's without problems

		EdgeArray<Graph::EdgeType> savedType(pr);
		EdgeArray<Graph::EdgeType> savedOrigType(pr.original()); //for deleted copies

		EdgeArray<int> costOrig(pr.original(), 1);
		//edgearray for reinserter call: which edge may never be crossed?
		EdgeArray<bool> noCrossingEdge(pr.original(), false);

		edge e;
		forall_edges(e,pr)
		{
			edge eOrig = pr.original(e);

			if (pr.typeOf(e) == Graph::generalization)
			{
				if (l_align) l_gensExist = true;
				OGDF_ASSERT(!eOrig || !(noCrossingEdge[eOrig]));

				// high cost to allow alignment without crossings
				if (l_align && (
					(eOrig && (pr.typeOf(e->target()) == Graph::generalizationMerger))
						|| pr.alignUpward(e->adjSource())
					))
				 costOrig[eOrig] = 10;

			}
		}

		int cr;
		m_crossMin.get().call(pr, i, cr, &costOrig);
		m_nCrossings += cr;


		//---------------------------------------
		// 2. embed resulting planar graph
		//---------------------------------------

		// We currently compute any embedding and choose the maximal face as external face

		// if we use FixedEmbeddingInserter, we have to re-use the computed
		// embedding, otherwise crossing nodes can turn into "touching points"
		// of edges (alternatively, we could compute a new embedding and
		// finally "remove" such unnecessary crossings).
		if(!pr.representsCombEmbedding())
			planarEmbed(pr);

		adjEntry adjExternal = 0;
		if(pr.numberOfEdges() > 0) {
			CombinatorialEmbedding E(pr);
			face fExternal = findBestExternalFace(pr,E);
			adjExternal = fExternal->firstAdj();
		}


		//---------------------------------------------------------
		// 3. compute layout of planarized representation
		//---------------------------------------------------------

		Layout drawing(pr);

		// distinguish between CC's with/without generalizations
		// this changes the input layout modules options!
		if (l_gensExist)
			m_planarLayouter.get().setOptions(l_layoutOptions);
		else
			m_planarLayouter.get().setOptions((l_layoutOptions & ~umlOpAlign));

		// call the Layouter for the CC's UMLGraph
		m_planarLayouter.get().call(pr, adjExternal, drawing);

		// copy layout into umlGraph
		// Later, we move nodes and edges in each connected component, such
		// that no two overlap.

		for(int j = pr.startNode(); j < pr.stopNode(); ++j) {
			node vG = pr.v(j);

			umlGraph.x(vG) = drawing.x(pr.copy(vG));
			umlGraph.y(vG) = drawing.y(pr.copy(vG));

			adjEntry adj;
			forall_adj(adj,vG) {
				if ((adj->index() & 1) == 0) continue;
				edge eG = adj->theEdge();

				drawing.computePolylineClear(pr,eG,umlGraph.bends(eG));
			}
		}

		// the width/height of the layout has been computed by the planar
		// layout algorithm; required as input to packing algorithm
		boundingBox[i] = m_planarLayouter.get().getBoundingBox();
	}//for cc's