Пример #1
0
//---------------------------------------------------------
// Compute x-coordinates (LP-based approach) (for graphs)
//---------------------------------------------------------
void OptimalHierarchyLayout::computeXCoordinates(
	const Hierarchy& H,
	GraphCopyAttributes &AGC)
{
	const GraphCopy &GC = H;
	const int k = H.size();

	//
	// preprocessing: determine nodes that are considered as virtual
	//
	NodeArray<bool> isVirtual(GC);

	int i;
	for(i = 0; i < k; ++i)
	{
		const Level &L = H[i];
		int last = -1;
		for(int j = 0; j < L.size(); ++j)
		{
			node v = L[j];

			if(H.isLongEdgeDummy(v) == true) {
				isVirtual[v] = true;

				node u = v->firstAdj()->theEdge()->target();
				if(u == v) u = v->lastAdj()->theEdge()->target();

				if(H.isLongEdgeDummy(u) == true) {
					int down = H.pos(u);
					if(last != -1 && last > down) {
						isVirtual[v] = false;
					} else {
						last = down;
					}
				}
			} else
				isVirtual[v] = false;
		}
	}

	//
	// determine variables of LP
	//
	int nSegments     = 0; // number of vertical segments
	int nRealVertices = 0; // number of real vertices
	int nEdges        = 0; // number of edges not in vertical segments
	int nBalanced     = 0; // number of real vertices with deg > 1 for which
	                       // balancing constraints may be applied

	NodeArray<int> vIndex(GC,-1); // for real node: index of x[v]
	                              // for dummy: index of corresponding segment
	NodeArray<int> bIndex(GC,-1); // (relative) index of b[v]
	EdgeArray<int> eIndex(GC,-1); // for edge not in vertical segment:
	                              //   its index
	Array<int> count(GC.numberOfEdges());  // counts the number of dummy vertices
	                              // in corresponding segment that are not at
	                              // position 0

	for(i = 0; i < k; ++i)
	{
		const Level &L = H[i];
		for(int j = 0; j < L.size(); ++j) {
			node v = L[j];
			if(isVirtual[v] == true)
				continue;

			// we've found a real vertex
			vIndex[v] = nRealVertices++;
			if(v->degree() > 1)
				bIndex[v] = nBalanced++;

			// consider all outgoing edges
			edge e;
			forall_adj_edges(e,v) {
				node w = e->target();
				if(w == v)
					continue;

				// we've found an edge not belonging to a vetical segment
				eIndex[e] = nEdges++;

				if(isVirtual[w] == false)
					continue;

				// we've found a vertical segment
				count[nSegments] = 0;
				do {
					vIndex[w] = nSegments;
					const int high = H[H.rank(w)].high();
					if(high > 0) {
						if (H.pos(w) == 0 || H.pos(w) == high)
							++count[nSegments];
						else
							count[nSegments] += 2;
					}

					// next edge / dummy in segment
					e = e->adjTarget()->cyclicSucc()->theEdge();
					w = e->target();
				} while(isVirtual[w]);

				// edge following vertical segment
                eIndex[e] = nEdges++;

				++nSegments;
			}
		}
	}
//---------------------------------------------------------
// Compute x-coordinates (LP-based approach) (for cluster graphs)
//---------------------------------------------------------
void OptimalHierarchyClusterLayout::computeXCoordinates(
	const ExtendedNestingGraph& H,
	ClusterGraphCopyAttributes &AGC)
{
	const ClusterGraphCopy &CG = H.getClusterGraph();

	const int k = H.numberOfLayers();

	//
	// preprocessing: determine nodes that are considered as virtual
	//
	m_isVirtual.init(H);

	int i;
	for(i = 0; i < k; ++i)
	{
		int last = -1;

		// Process nodes on layer i from left to right
		Stack<const LHTreeNode*> S;
		S.push(H.layerHierarchyTree(i));
		while(!S.empty())
		{
			const LHTreeNode *vNode = S.pop();

			if(vNode->isCompound()) {
				for(int j = vNode->numberOfChildren()-1; j >= 0; --j)
					S.push(vNode->child(j));

			} else {
				node v = vNode->getNode();

				if(H.isLongEdgeDummy(v) == true) {
					m_isVirtual[v] = true;

					edge e = v->firstAdj()->theEdge();
					if(e->target() == v)
						e = v->lastAdj()->theEdge();
					node u = e->target();

					if(H.verticalSegment(e) == false)
						continue;

					if(H.isLongEdgeDummy(u) == true) {
						int down = H.pos(u);
						if(last != -1 && last > down) {
							m_isVirtual[v] = false;
						} else {
							last = down;
						}
					}
				} else {
					m_isVirtual[v] = false;
				}
			}
		}
	}

	//
	// determine variables of LP
	//
	int nSegments     = 0; // number of vertical segments
	int nRealVertices = 0; // number of real vertices
	int nEdges        = 0; // number of edges not in vertical segments
	int nBalanced     = 0; // number of real vertices with deg > 1 for which balancing constraints may be applied

	m_vIndex.init(H,-1); // for real node: index of x[v] for dummy: index of corresponding segment
	NodeArray<int> bIndex(H,-1); // (relative) index of b[v]
	EdgeArray<int> eIndex(H,-1); // for edge not in vertical segment: its index
	Array<int> count(H.numberOfEdges());	// counts the number of dummy vertices
											// in corresponding segment that are not at
											// position 0

	int nSpacingConstraints = 0;
	for(i = 0; i < k; ++i)
	{
		Stack<const LHTreeNode*> S;
		S.push(H.layerHierarchyTree(i));
		while(!S.empty())
		{
			const LHTreeNode *vNode = S.pop();

			if(vNode->isCompound()) {
				cluster c = vNode->originalCluster();

				if(H.isVirtual(c) == false)
					nSpacingConstraints += (c == CG.rootCluster()) ? 1 : 2;

				for(int j = vNode->numberOfChildren()-1; j >= 0; --j)
					S.push(vNode->child(j));

			} else {
				node v = vNode->getNode();

				// ignore dummy nodes and nodes representing cluster
				// (top or bottom) border
				if(H.type(v) == ExtendedNestingGraph::ntClusterBottom || H.type(v) == ExtendedNestingGraph::ntClusterTop)
					continue;

				++nSpacingConstraints;

				// ignore dummy nodes
				if(m_isVirtual[v] == true)
					continue;

				// we've found a real vertex
				m_vIndex[v] = nRealVertices++;
				if(v->degree() > 1)
					bIndex[v] = nBalanced++;

				// consider all outgoing edges
				edge e;
				forall_adj_edges(e,v) {
					node w = e->target();
					if(w == v)
						continue;

					// we've found an edge not belonging to a vetical segment
					eIndex[e] = nEdges++;

					if(m_isVirtual[w] == false)
						continue;

					do {
						// we've found a vertical segment
						count[nSegments] = 0;
						do {
							m_vIndex[w] = nSegments;
							count[nSegments] += 2;

							// next edge / dummy in segment
							e = e->adjTarget()->cyclicSucc()->theEdge();
							w = e->target();
						} while(m_isVirtual[w] && H.verticalSegment(e));

						++nSegments;

						// edge following vertical segment
						eIndex[e] = nEdges++;

					} while(m_isVirtual[w]);
				}
			}
		}
	}