Beispiel #1
0
void RadialTreeLayout::ComputeCoordinates(GraphAttributes &AG)
{
	const Graph &G = AG.constGraph();

	//double mx = m_outerRadius + 0.5*m_connectedComponentDistance;
	//double my = mx;

	for(node v : G.nodes) {
		double r = m_radius[m_level[v]];
		double alpha = m_angle[v];

		AG.x(v) = r * cos(alpha);
		AG.y(v) = r * sin(alpha);
	}

	AG.clearAllBends();
}
void FMMMLayout::call(GraphAttributes &GA, const EdgeArray<double> &edgeLength)
{
  const Graph &G = GA.constGraph();
  //tms t_total;//helping variable for time measure
  double t_total;
  NodeArray<NodeAttributes> A(G);       //stores the attributes of the nodes (given by L)
  EdgeArray<EdgeAttributes> E(G);       //stores the edge attributes of G
  Graph G_reduced;                      //stores a undirected simple and loopfree copy 
                                        //of G
  EdgeArray<EdgeAttributes> E_reduced;  //stores the edge attributes of G_reduced
  NodeArray<NodeAttributes> A_reduced;  //stores the node attributes of G_reduced 

  if(G.numberOfNodes() > 1)
    {
      GA.clearAllBends();//all are edges straight line
      if(useHighLevelOptions())
	update_low_level_options_due_to_high_level_options_settings();
      import_NodeAttributes(G,GA,A);
      import_EdgeAttributes(G,edgeLength,E);
      
      //times(&t_total);
	  usedTime(t_total);
      max_integer_position = pow(2.0,maxIntPosExponent());
      init_ind_ideal_edgelength(G,A,E);  
      make_simple_loopfree(G,A,E,G_reduced,A_reduced,E_reduced);
      call_DIVIDE_ET_IMPERA_step(G_reduced,A_reduced,E_reduced);
      if(allowedPositions() != apAll)
	make_positions_integer(G_reduced,A_reduced);
      //time_total = get_time(t_total);
	  time_total = usedTime(t_total);
            
      export_NodeAttributes(G_reduced,A_reduced,GA);
    }
  else //trivial cases
    { 
      if(G.numberOfNodes() == 1 )
	{
	  node v = G.firstNode();
	  GA.x(v) = 0;
	  GA.y(v) = 0;
	} 
    }
}
Beispiel #3
0
void BertaultLayout::call(GraphAttributes &AG)
{
	const Graph &G = AG.constGraph();
	if(G.numberOfNodes() == 0)
		return;
	if( (AG.attributes() & GraphAttributes::nodeGraphics) == 0 )
		return;
	if( (AG.attributes() & GraphAttributes::edgeGraphics) != 0 )
		AG.clearAllBends();
	if(iter_no==0)
		iter_no=G.numberOfNodes()*10;
	if(req_length==0)
	{
		edge e;
		forall_edges(e,G)
		{
			node a=e->source();
			node b=e->target();
			req_length+=sqrt((AG.x(a)-AG.x(b))*(AG.x(a)-AG.x(b))+(AG.y(a)-AG.y(b))*(AG.y(a)-AG.y(b)));
		}
void SpringEmbedderFR::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);

	node v;
	forall_nodes(v,G)
		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);
		node vCopy;
		forall_nodes(vCopy, GC) {
			node vOrig = GC.original(vCopy);
			AGC.x(vCopy) = AG.x(vOrig);
			AGC.y(vCopy) = AG.y(vOrig);
		}

		// original
		if (initialize(GC, AGC) == true)
		{
			for(int i = 1; i <= m_iterations; i++)
				mainStep(GC, AGC);

		}
		cleanup();
		// end original

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

		forall_nodes(vCopy,GC) {
			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;
		}
Beispiel #5
0
//this sets the parameters of the class DavidsonHarel, adds the energy functions and
//starts the optimization process
void DavidsonHarelLayout::call(GraphAttributes &AG)
{
	// all edges straight-line
	AG.clearAllBends();

	DavidsonHarel dh;
	Repulsion rep(AG);
	Attraction atr(AG);
	Overlap over(AG);
	Planarity plan(AG);
	//PlanarityGrid plan(AG);
	//PlanarityGrid2 plan(AG);
	//NodeIntersection ni(AG);

	// Either use a fixed value...
	if (DIsGreater(m_prefEdgeLength, 0.0))
	{
		atr.setPreferredEdgelength(m_prefEdgeLength);
	}
	// ...or set it depending on vertex sizes
	else atr.reinitializeEdgeLength(m_multiplier);
	 

	dh.addEnergyFunction(&rep,m_repulsionWeight);
	dh.addEnergyFunction(&atr,m_attractionWeight);
	dh.addEnergyFunction(&over,m_nodeOverlapWeight);
	if (m_crossings) dh.addEnergyFunction(&plan,m_planarityWeight);
	//dh.addEnergyFunction(&ni,2000.0);

	//dh.setNumberOfIterations(m_numberOfIterations);
	//dh.setStartTemperature(m_startTemperature);
	const Graph& G = AG.constGraph();
	//TODO: Immer Anzahl Iterationen abhängig von Größe
	if (m_numberOfIterations == 0)
	{
		switch (m_speed)  //todo: function setSpeedParameters
		{
		  case sppFast: {
				          m_numberOfIterations = max(75, 3*G.numberOfNodes()); 
						  m_startTemperature = 400;
						} break;
		  case sppMedium: {
				            m_numberOfIterations = 10*G.numberOfNodes(); 
							m_startTemperature = 1500;
						  } 
				          break;
		  case sppHQ: {
				        m_numberOfIterations = 2500*G.numberOfNodes(); //should be: isolate
						m_startTemperature = 2000;
					  } 
					  break;
		  default: OGDF_THROW_PARAM(AlgorithmFailureException, afcIllegalParameter); break;
		}//switch
	}//if
	else
	{
		if (m_itAsFactor)
			dh.setNumberOfIterations(200+m_numberOfIterations*G.numberOfNodes());
		else
			dh.setNumberOfIterations(m_numberOfIterations);
	}
	dh.setStartTemperature(m_startTemperature);
	dh.call(AG);
}
void GEMLayout::call(GraphAttributes &AG) 
{
	const Graph &G = AG.constGraph();
	if(G.empty())
		return;

	OGDF_ASSERT(m_numberOfRounds >= 0);
	OGDF_ASSERT(DIsGreaterEqual(m_minimalTemperature,0));
	OGDF_ASSERT(DIsGreaterEqual(m_initialTemperature,m_minimalTemperature));
	OGDF_ASSERT(DIsGreaterEqual(m_gravitationalConstant,0));
	OGDF_ASSERT(DIsGreaterEqual(m_desiredLength,0));
	OGDF_ASSERT(DIsGreaterEqual(m_maximalDisturbance,0));
	OGDF_ASSERT(DIsGreaterEqual(m_rotationAngle,0));
	OGDF_ASSERT(DIsLessEqual(m_rotationAngle,pi / 2));
	OGDF_ASSERT(DIsGreaterEqual(m_oscillationAngle,0));
	OGDF_ASSERT(DIsLessEqual(m_oscillationAngle,pi / 2));
	OGDF_ASSERT(DIsGreaterEqual(m_rotationSensitivity,0));
	OGDF_ASSERT(DIsLessEqual(m_rotationSensitivity,1));
	OGDF_ASSERT(DIsGreaterEqual(m_oscillationSensitivity,0));
	OGDF_ASSERT(DIsLessEqual(m_oscillationSensitivity,1));
	OGDF_ASSERT(m_attractionFormula == 1 || m_attractionFormula == 2);
	
	// 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);

	node v;
	forall_nodes(v,G)
		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);
		node vCopy;
		forall_nodes(vCopy, GC) {
			node vOrig = GC.original(vCopy);
			AGC.x(vCopy) = AG.x(vOrig);
			AGC.y(vCopy) = AG.y(vOrig);
		}

		SList<node> permutation;
		node v;

		// 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;
		forall_nodes(v,GC) {
			m_barycenterX += weight(v) * AGC.x(v);
			m_barycenterY += weight(v) * AGC.y(v);
		}
void SpringEmbedderFRExact::call(GraphAttributes &AG)
{
	const Graph &G = AG.constGraph();
	if(G.empty())
		return;

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

	ArrayGraph component(AG);
	component.m_useNodeWeight = m_useNodeWeight;

	EdgeArray<edge> auxCopy(G);
	Array<DPoint> boundingBox(component.numberOfCCs());

	int i;
	for(i = 0; i < component.numberOfCCs(); ++i)
	{
		component.initCC(i);

		if (component.numberOfNodes() >= 2)
		{
			initialize(component);

#ifdef OGDF_SSE3_EXTENSIONS
			if(System::cpuSupports(cpufSSE3))
				mainStep_sse3(component);
			else
#endif
				mainStep(component);
		}

		double minX, maxX, minY, maxY;
		minX = maxX = component.m_x[0];
		minY = maxY = component.m_y[0];

		for(int vCopy = 0; vCopy < component.numberOfNodes(); ++vCopy) {
			node v = component.original(vCopy);
			AG.x(v) = component.m_x[vCopy];
			AG.y(v) = component.m_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(int vCopy = 0; vCopy < component.numberOfNodes(); ++vCopy) {
			node v = component.original(vCopy);
			AG.x(v) -= minX;
			AG.y(v) -= minY;
		}

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

	Array<DPoint> offset(component.numberOfCCs());
	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 < component.numberOfCCs(); ++i)
	{
		const SList<node> &nodes = component.nodesInCC(i);

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

		// iterate over all nodes in ith CC
		for(node v : nodes)
		{
			AG.x(v) += dx;
			AG.y(v) += dy;
		}
	}
}
Beispiel #8
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();
}