Beispiel #1
0
void GEMLayout::updateNode(GraphCopy &G, GraphCopyAttributes &AG,node v) {
	//const Graph &G = AG.constGraph();
	int n = G.numberOfNodes();
	double impulseLength;

	impulseLength = length(m_newImpulseX,m_newImpulseY);
	if(OGDF_GEOM_ET.greater(impulseLength,0.0)) {

		// scale impulse by node temperature
		m_newImpulseX *= m_localTemperature[v] / impulseLength;
		m_newImpulseY *= m_localTemperature[v] / impulseLength;

		// move node
		AG.x(v) += m_newImpulseX;
		AG.y(v) += m_newImpulseY;

		// adjust barycenter
		m_barycenterX += weight(v) * m_newImpulseX;
		m_barycenterY += weight(v) * m_newImpulseY;

		impulseLength = length(m_newImpulseX,m_newImpulseY)
						* length(m_impulseX[v],m_impulseY[v]);
		if(OGDF_GEOM_ET.greater(impulseLength,0.0)) {

			m_globalTemperature -= m_localTemperature[v] / n;

			// compute sine and cosine of angle between old and new impulse
			double sinBeta,cosBeta;
			sinBeta = (m_newImpulseX * m_impulseX[v]
				- m_newImpulseY * m_impulseY[v])
					/ impulseLength;
			cosBeta = (m_newImpulseX * m_impulseX[v]
				+ m_newImpulseY * m_impulseY[v])
					/ impulseLength;

			// check for rotation
			if(OGDF_GEOM_ET.greater(sinBeta,m_sin))
				m_skewGauge[v] += m_rotationSensitivity;

			// check for oscillation
			if(OGDF_GEOM_ET.greater(length(cosBeta),m_cos))
				m_localTemperature[v] *=
					(1 + cosBeta * m_oscillationSensitivity);

			// cool down according to skew gauge
			m_localTemperature[v] *= (1.0 - length(m_skewGauge[v]));
			if(OGDF_GEOM_ET.geq(m_localTemperature[v],m_initialTemperature))
				m_localTemperature[v] = m_initialTemperature;

			// adjust global temperature
			m_globalTemperature += m_localTemperature[v] / n;
		}

		// save impulse
		m_impulseX[v] = m_newImpulseX;
		m_impulseY[v] = m_newImpulseY;
	}
}
Beispiel #2
0
void GEMLayout::computeImpulse(GraphCopy &G, GraphCopyAttributes &AG,node v) {
	//const Graph &G = AG.constGraph();
	int n = G.numberOfNodes();

	double deltaX,deltaY,delta,deltaSqu;
	double desiredLength,desiredSqu;

	// add double node radius to desired edge length
	desiredLength = m_desiredLength + length(AG.getHeight(v),AG.getWidth(v));
	desiredSqu = desiredLength * desiredLength;

	// compute attraction to center of gravity
	m_newImpulseX = (m_barycenterX / n - AG.x(v)) * m_gravitationalConstant;
	m_newImpulseY = (m_barycenterY / n - AG.y(v)) * m_gravitationalConstant;

	// disturb randomly
	int maxIntDisturbance = (int)(m_maximalDisturbance * 10000);
	std::uniform_int_distribution<> dist(-maxIntDisturbance,maxIntDisturbance);
	m_newImpulseX += (dist(m_rng) / 10000.0);
	m_newImpulseY += (dist(m_rng) / 10000.0);

	// compute repulsive forces
	for(node u : G.nodes)
		if(u != v ) {
			deltaX = AG.x(v) - AG.x(u);
			deltaY = AG.y(v) - AG.y(u);
			delta = length(deltaX,deltaY);
			if(OGDF_GEOM_ET.greater(delta,0.0)) {
				deltaSqu = delta * delta;
				m_newImpulseX += deltaX * desiredSqu / deltaSqu;
				m_newImpulseY += deltaY * desiredSqu / deltaSqu;
			}
	}

	// compute attractive forces
	for(adjEntry adj : v->adjEntries) {
		node u = adj->twinNode();
		deltaX = AG.x(v) - AG.x(u);
		deltaY = AG.y(v) - AG.y(u);
		delta = length(deltaX,deltaY);
		if(m_attractionFormula == 1) {
			m_newImpulseX -= deltaX * delta / (desiredLength * weight(v));
			m_newImpulseY -= deltaY * delta / (desiredLength * weight(v));
		}
		else {
			deltaSqu = delta * delta;
			m_newImpulseX -= deltaX * deltaSqu / (desiredSqu * weight(v));
			m_newImpulseY -= deltaY * deltaSqu / (desiredSqu * weight(v));
		}
	}

}
Beispiel #3
0
void FPPLayout::computeCoordinates(const GraphCopy &G, IPoint &boundingBox, GridLayout &gridLayout, NodeArray<int> &num,
									NodeArray<adjEntry> &e_wp, NodeArray<adjEntry> &e_wq) {
	NodeArray<int> &x = gridLayout.x();
	NodeArray<int> &y = gridLayout.y();

	const int n = G.numberOfNodes();
	NodeArray<int>  x_rel(G);
	NodeArray<node> upper(G);
	NodeArray<node> next(G);
	Array<node, int> v(1, n);
	node w, vk, wp, wq;
	int k, xq, dx;

	forall_nodes(w, G) {
		v[num[w]] = (node) w;
	}
Beispiel #4
0
void FUPSSimple::getSpanTree(GraphCopy &GC, List<edge> &delEdges, bool random)
{
	if (GC.numberOfNodes() == 1)
		return; // nothing to do

	node s;
	hasSingleSource(GC, s);
	NodeArray<bool> visited(GC, false);
	EdgeArray<bool> isTreeEdge(GC,false);
	List<node> toDo;

	//mark the incident edges e1..e_i of super source s and the incident edges of the target node of the edge e1.._e_i as tree edge.
	visited[s] = true;
	for(adjEntry adj : s->adjEdges) {
		isTreeEdge[adj] = true;
		visited[adj->theEdge()->target()];
		for(adjEntry adjTmp : adj->theEdge()->target()->adjEdges) {
			isTreeEdge[adjTmp] = true;
			node tgt = adjTmp->theEdge()->target();
			if (!visited[tgt]) {
				toDo.pushBack(tgt);
				visited[tgt] = true;
			}
		}
	}

	//traversing with dfs
	for(node start : toDo) {
		for(adjEntry adj : start->adjEdges) {
			node v = adj->theEdge()->target();
			if (!visited[v])
				dfs_visit(GC, adj->theEdge(), visited, isTreeEdge, random);
		}
	}

	// delete all non tree edgesEdges to obtain a span tree
	List<edge> l;
	for(edge e : GC.edges) {
		if (!isTreeEdge[e])
			l.pushBack(e);
	}
	while (!l.empty()) {
		edge e = l.popFrontRet();
		delEdges.pushBack(GC.original(e));
		GC.delEdge(e);
	}
}
void FeasibleUpwardPlanarSubgraph::getSpanTree(GraphCopy &GC, List<edge> &delEdges, bool random, bool multisource)
{
	delEdges.clear();
	if (GC.numberOfNodes() == 1)
		return; // nothing to do
	node s;
	hasSingleSource(GC, s);
	NodeArray<bool> visited(GC, false);
	EdgeArray<bool> isTreeEdge(GC,false);
	List<node> toDo;

	// the original graph is a multisource graph. The sources are connected with the super source s.
	// so do not delete the incident edges of s
	if (multisource){
		// put all incident edges of the source to treeEdges
		for(adjEntry adj : s->adjEdges) {
			isTreeEdge[adj->theEdge()] = true;
			visited[adj->theEdge()->target()];
			toDo.pushBack(adj->theEdge()->target());
		}
	}
	else
		toDo.pushBack(s);


	//traversing with dfs
	for(node start : toDo) {
		for(adjEntry adj : start->adjEdges) {
			node v = adj->theEdge()->target();
			if (!visited[v])
				dfs_visit(GC, adj->theEdge(), visited, isTreeEdge, random);
		}
	}

	// delete all non tree edgesEdges to obtain a span tree
	List<edge> l;
	for(edge e : GC.edges) {
		if (!isTreeEdge[e])
			l.pushBack(e);
	}
	while (!l.empty()) {
		edge e = l.popFrontRet();
		delEdges.pushBack(GC.original(e));
		GC.delEdge(e);
	}
}
void FeasibleUpwardPlanarSubgraph::getSpanTree(GraphCopy &GC, List<edge> &delEdges, bool random, bool multisource)
{
	delEdges.clear();
	if (GC.numberOfNodes() == 1)
		return; // nothing to do
	node s;
	hasSingleSource(GC, s);
	NodeArray<bool> visited(GC, false);
	EdgeArray<bool> isTreeEdge(GC,false);
	List<node> toDo;

	// the original graph is a multisource graph. The sources are connected with the super source s.
	// so do not delete the incident edges of s
	if (multisource){
		// put all incident edges of the source to treeEdges
		adjEntry adj;
		forall_adj(adj, s) {
			isTreeEdge[adj->theEdge()] = true;
			visited[adj->theEdge()->target()];
			toDo.pushBack(adj->theEdge()->target());
		}
	}
Beispiel #7
0
void OptimalRanking::doCall(
	const Graph& G,
	NodeArray<int> &rank,
	EdgeArray<bool> &reversed,
	const EdgeArray<int> &length,
	const EdgeArray<int> &costOrig)
{
	MinCostFlowReinelt<int> mcf;

	// construct min-cost flow problem
	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);
	rank.init(G);

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

		for(edge e : GC.edges)
			if(reversed[GC.original(e)])
				GC.reverseEdge(e);

		// special cases:
		if(GC.numberOfNodes() == 1) {
			rank[GC.original(GC.firstNode())] = 0;
			continue;
		} else if(GC.numberOfEdges() == 1) {
			edge e = GC.original(GC.firstEdge());
			rank[e->source()] = 0;
			rank[e->target()] = length[e];
			continue;
		}

		EdgeArray<int> lowerBound(GC,0);
		EdgeArray<int> upperBound(GC,mcf.infinity());
		EdgeArray<int> cost(GC);
		NodeArray<int> supply(GC);

		for(edge e : GC.edges)
			cost[e] = -length[GC.original(e)];

		for(node v : GC.nodes) {
			int s = 0;
			edge e;
			forall_adj_edges(e,v) {
				if(v == e->source())
					s += costOrig[GC.original(e)];
				else
					s -= costOrig[GC.original(e)];
			}
			supply[v] = s;
		}

		OGDF_ASSERT(isAcyclic(GC) == true);

		// find min-cost flow
		EdgeArray<int> flow(GC);
		NodeArray<int> dual(GC);
#ifdef OGDF_DEBUG
		bool feasible =
#endif
			mcf.call(GC, lowerBound, upperBound, cost, supply, flow, dual);
		OGDF_ASSERT(feasible);

		for(node v : GC.nodes)
			rank[GC.original(v)] = dual[v];
	}
}
Beispiel #8
0
void FPPLayout::computeOrder(
	const GraphCopy &G,
	NodeArray<int> &num,
	NodeArray<adjEntry> &e_wp,
	NodeArray<adjEntry> &e_wq,
	adjEntry e_12,
	adjEntry e_2n,
	adjEntry e_n1)
{
	NodeArray<int> num_diag(G, 0);							// number of chords
	// link[v] = Iterator in possible, that points to v (if diag[v] = 0 and outer[v] = TRUE)
	NodeArray<ListIterator<node> > link(G, 0);
	// outer[v] = TRUE <=> v is a node of the actual outer face
	NodeArray<bool> outer(G, false);
	// List of all nodes v with outer[v] = TRUE and diag[v] = 0
	List<node> possible;

	// nodes of the outer triangle (v_1,v_2,v_n)
	node v_1 = e_12->theNode();
	node v_2 = e_2n->theNode();
	node v_n = e_n1->theNode();
	node v_k, wp, wq, u;
	adjEntry e, e2;
	int k;

	// initialization: beginn with outer face (v_1,v_2,v_n)
	// v_n is the only possible node
	num[v_1] = 1;
	num[v_2] = 2;

	outer[v_1] = true;
	outer[v_2] = true;
	outer[v_n] = true;

	link[v_n] = possible.pushBack(v_n);

	e_wq[v_1] = e_n1->twin();
	e_wp[v_2] = e_2n;

	e_wq[v_n] = e_2n->twin();
	e_wp[v_n] = e_n1;

	// select next v_k and delete it
	for (k = G.numberOfNodes(); k >= 3; k--) {
		v_k = possible.popFrontRet();	// select arbitrary node from possible as v_k

		num[v_k] = k;

		// predecessor wp and successor wq from vk in C_k (actual outer face)
		wq = (e_wq [v_k])->twinNode();
		wp = (e_wp [v_k])->twinNode();

		// v_k not in C_k-1 anymore
		outer[v_k] = false;

		// shortfall of a chord?
		if (e_wq[wp]->cyclicSucc()->twinNode() == wq) {   // wp, wq is the only successor of vk in G_k
			// wp, wq loose a chord
			if (--num_diag[wp] == 0) {
				link[wp] = possible.pushBack(wp);
			}
			if (--num_diag[wq] == 0) {
				link[wq] = possible.pushBack(wq);
			}
		}

		// update or initialize e_wq, e_wp
		e_wq[wp] = e_wq[wp]->cyclicSucc();

		e_wp[wq] = e_wp[wq]->cyclicPred();
		e = e_wq[wp];
		for (u = e->twinNode(); u != wq; u = e->twinNode()) {
			outer[u] = true;
			e_wp[u] = e->twin();
			e = e_wq[u] = e_wp[u]->cyclicSucc()->cyclicSucc();

			// search for new chords
			for (e2 = e_wp[u]->cyclicPred(); e2 != e_wq[u]; e2 = e2->cyclicPred()) {
				node w = e2->twinNode();
				if (outer[w] == true) {
					++num_diag[u];
					if (w != v_1 && w != v_2)
						if (++num_diag[w] == 1) possible.del(link[w]);
				}
			}

			if (num_diag[u] == 0) {
				link[u] = possible.pushBack(u);
			}
		}
	}
}