예제 #1
0
void GridLayoutModule::call(GraphAttributes &AG)
{
	const Graph &G = AG.constGraph();

	// compute grid layout
	GridLayout gridLayout(G);
	doCall(G,gridLayout,m_gridBoundingBox);

	// transform grid layout to real layout
	mapGridLayout(G,gridLayout,AG);
}
예제 #2
0
파일: SimDraw.cpp 프로젝트: lncosie/ogdf
//*************************************************************
//adds new GraphAttributes to m_G if maxSubgraph() < 32
//
bool SimDraw::addGraphAttributes(const GraphAttributes & GA)
{
	if(maxSubGraph() >= 31)
		return false;

	//if(compareBy() == label)
	OGDF_ASSERT((compareBy() != label) || (m_GA.attributes() & GraphAttributes::edgeLabel));

	int max = numberOfBasicGraphs();
	bool foundEdge = false;
	//node v;
	//edge e, f;
	Graph G = GA.constGraph();

	for(edge e : G.edges) {
		for(edge f : m_G.edges) {
			if (compare(m_GA, f->source(), GA, e->source())
			 && compare(m_GA, f->target(), GA, e->target())) {
				foundEdge = true;
				m_GA.addSubGraph(f,max);
			}
		}

		if (!foundEdge) {
			node s, t;
			bool srcFound = false;
			bool tgtFound = false;
			for(node v : m_G.nodes) {
				if (compare(m_GA, v, GA, e->source())) {
					s = v;
					srcFound = true;
				}
				if (compare(m_GA, v, GA, e->target())) {
					t = v;
					tgtFound = true;
				}
			}

			if (!srcFound)
				s = m_G.newNode(e->source()->index());

			if (!tgtFound)
				t = m_G.newNode(e->target()->index());

			edge d = m_G.newEdge(s, t);
			if(compareBy() == label)
				m_GA.label(d) = GA.label(e);

			m_GA.addSubGraph(d, max);
		}
	}
	return true;

}// end addGraphAttributes
예제 #3
0
void StressMinimization::copyLayout(
	const GraphAttributes& GA,
	NodeArray<double>& newX,
	NodeArray<double>& newY)
{
	// copy the layout
	for(node v : GA.constGraph().nodes)
	{
		newX[v] = GA.x(v);
		newY[v] = GA.y(v);
	}
}
예제 #4
0
파일: PivotMDS.cpp 프로젝트: marvin2k/ogdf
void PivotMDS::getPivotDistanceMatrix(
	const GraphAttributes& GA,
	Array<Array<double> >& pivDistMatrix)
{
	const Graph& G = GA.constGraph();
	const int n = G.numberOfNodes();

	// lower the number of pivots if necessary
	int numberOfPivots = min(n, m_numberOfPivots);
	// number of pivots times n matrix used to store the graph distances
	pivDistMatrix.init(numberOfPivots);
	for (int i = 0; i < numberOfPivots; i++) {
		pivDistMatrix[i].init(n);
	}
	// edges costs array
	EdgeArray<double> edgeCosts;
	bool hasEdgeCosts = false;
	// already checked whether this attribute exists or not (see call method)
	if (m_hasEdgeCostsAttribute) {
		edgeCosts.init(G);
		for(edge e : G.edges)
		{
			edgeCosts[e] = GA.doubleWeight(e);
		}
		hasEdgeCosts = true;
	}
	// used for min-max strategy
	NodeArray<double> minDistances(G, std::numeric_limits<double>::infinity());
	NodeArray<double> shortestPathSingleSource(G);
	// the current pivot node
	node pivNode = G.firstNode();
	for (int i = 0; i < numberOfPivots; i++) {
		// get the shortest path from the currently processed pivot node to
		// all other nodes in the graph
		shortestPathSingleSource.fill(std::numeric_limits<double>::infinity());
		if (hasEdgeCosts) {
			dijkstra_SPSS(pivNode, G, shortestPathSingleSource, edgeCosts);
		} else {
			bfs_SPSS(pivNode, G, shortestPathSingleSource, m_edgeCosts);
		}
		copySPSS(pivDistMatrix[i], shortestPathSingleSource);
		// update the pivot and the minDistances array ... to ensure the
		// correctness set minDistance of the pivot node to zero
		minDistances[pivNode] = 0;
		for(node v : G.nodes)
		{
			minDistances[v] = min(minDistances[v], shortestPathSingleSource[v]);
			if (minDistances[v] > minDistances[pivNode]) {
				pivNode = v;
			}
		}
	}
}
예제 #5
0
	int LayoutStatistics::numberOfBends(
		const GraphAttributes &ga,
		int *pMinBendsPerEdge,
		int *pMaxBendsPerEdge,
		double *pAvgBendsPerEdge,
		double *pStdDeviation,
		bool    considerSelfLoops)
	{
		const Graph &G = ga.constGraph();
		int m = G.numberOfEdges();

		int totalBends = 0, minBends = numeric_limits<int>::max(), maxBends = 0;

		EdgeArray<int> bends(G);
		int nSelfLoops = 0;

		for(edge e : G.edges) {
			if(!considerSelfLoops && e->isSelfLoop()) {
				nSelfLoops++;
				continue;
			}

			const DPolyline &dpl = ga.bends(e);

			bends[e] = max(0, dpl.size() - 2);

			totalBends += bends[e];
			minBends = min(minBends, bends[e]);
			maxBends = max(maxBends, bends[e]);
		}

		m -= nSelfLoops;

		double avgBends = double(totalBends) / m;
		if(pAvgBendsPerEdge) *pAvgBendsPerEdge = avgBends;
		if(pMinBendsPerEdge) *pMinBendsPerEdge = minBends;
		if(pMaxBendsPerEdge) *pMaxBendsPerEdge = maxBends;

		if(pStdDeviation) {
			double sum = 0;
			for(edge e : G.edges) {
				if(!considerSelfLoops && e->isSelfLoop())
					continue;
				double d = bends[e] - avgBends;
				sum += d*d;
			}

			*pStdDeviation = sqrt(sum / m);
		}

		return totalBends;
	}
예제 #6
0
void ComponentSplitterLayout::call(GraphAttributes &GA)
{
	// Only do preparations and call if layout is valid
	if (m_secondaryLayout.valid())
	{
		//first we split the graph into its components
		const Graph& G = GA.constGraph();

		NodeArray<int> componentNumber(G);
		m_numberOfComponents = connectedComponents(G, componentNumber);
		if (m_numberOfComponents == 0) {
			return;
		}

		//std::vector< std::vector<node> > componentArray;
		//componentArray.resize(numComponents);
		//Array<GraphAttributes *> components(numComponents);
		//

		// intialize the array of lists of nodes contained in a CC
		nodesInCC.init(m_numberOfComponents);

		node v;
		forall_nodes(v,G)
			nodesInCC[componentNumber[v]].pushBack(v);

		// Create copies of the connected components and corresponding
		// GraphAttributes
		GraphCopy GC;
		GC.createEmpty(G);

		EdgeArray<edge> auxCopy(G);

		for (int i = 0; i < m_numberOfComponents; i++)
		{
			GC.initByNodes(nodesInCC[i],auxCopy);
			GraphAttributes cGA(GC, GA.attributes());
			//copy information into copy GA
			forall_nodes(v, GC)
			{
				cGA.width(v) = GA.width(GC.original(v));
				cGA.height(v) = GA.height(GC.original(v));
				cGA.x(v) = GA.x(GC.original(v));
				cGA.y(v) = GA.y(GC.original(v));
			}
			// copy information on edges
			if (GA.attributes() & GraphAttributes::edgeDoubleWeight) {
				edge e;
				forall_edges(e, GC) {
				cGA.doubleWeight(e) = GA.doubleWeight(GC.original(e));
				}
			}
예제 #7
0
void PlanarGridLayoutModule::callFixEmbed(GraphAttributes &AG, adjEntry adjExternal)
{
	const Graph &G = AG.constGraph();

	// compute grid layout
	GridLayout gridLayout(G);
	if (!handleTrivial(G, gridLayout, m_gridBoundingBox)) {
		doCall(G, adjExternal, gridLayout, m_gridBoundingBox, true);
	}

	// transform grid layout to real layout
	mapGridLayout(G,gridLayout,AG);
}
예제 #8
0
void FastMultipoleMultilevelEmbedder::call(GraphAttributes &GA)
{
	EdgeArray<float> edgeLengthAuto(GA.constGraph());
	computeAutoEdgeLength(GA, edgeLengthAuto);
	const Graph& t = GA.constGraph();
	if (t.numberOfNodes() <= 25)
	{
		FastMultipoleEmbedder fme;
		fme.setNumberOfThreads(this->m_iMaxNumThreads);
		fme.setRandomize(true);
		fme.setNumIterations(500);
		fme.call(GA);
		return;
	}

	run(GA, edgeLengthAuto);

	for(edge e : GA.constGraph().edges)
	{
		GA.bends(e).clear();
	}
}
예제 #9
0
파일: PivotMDS.cpp 프로젝트: mneumann/tulip
void PivotMDS::pivotMDSLayout(GraphAttributes& GA)
{
	const Graph& G = GA.constGraph();
	if (G.numberOfNodes() <= 1) {
		// make it exception save
		node v;
		forall_nodes(v,G)
		{
			GA.x(v) = 0.0;
			GA.y(v) = 0.0;
			if (DIMENSION_COUNT > 2)
				GA.z(v) = 0.0;
		}
예제 #10
0
파일: PivotMDS.cpp 프로젝트: marvin2k/ogdf
void PivotMDS::call(GraphAttributes& GA)
{
	if (!isConnected(GA.constGraph())) {
		OGDF_THROW_PARAM(PreconditionViolatedException,pvcConnected);
		return;
	}
	if (m_hasEdgeCostsAttribute
			&& !GA.has(GraphAttributes::edgeDoubleWeight)) {
				OGDF_THROW(PreconditionViolatedException);
		return;
	}
	pivotMDSLayout(GA);
}
예제 #11
0
	//chooses the initial radius of the disk as half the maximum of width and height of
	//the initial layout or depending on the value of m_fineTune
	void DavidsonHarel::computeFirstRadius(const GraphAttributes &AG)
	{
		const Graph &G = AG.constGraph();
		node v = G.firstNode();
		double minX = AG.x(v);
		double minY = AG.y(v);
		double maxX = minX;
		double maxY = minY;
		forall_nodes(v,G) {
			minX = min(minX,AG.x(v));
			maxX = max(maxX,AG.x(v));
			minY = min(minY,AG.y(v));
			maxY = max(maxY,AG.y(v));
		}
예제 #12
0
void FastMultipoleMultilevelEmbedder::computeAutoEdgeLength(const GraphAttributes& GA, EdgeArray<float>& edgeLength, float factor)
{
	for(edge e : GA.constGraph().edges)
	{
		node v = e->source();
		node w = e->target();
		float radius_v = (float)sqrt(GA.width(v)*GA.width(v) + GA.height(v)*GA.height(v)) * 0.5f;
		float radius_w = (float)sqrt(GA.width(w)*GA.width(w) + GA.height(w)*GA.height(w)) * 0.5f;
		float sum = radius_v + radius_w;
		if (OGDF_GEOM_ET.equal(sum, (float) 0))
			sum = 1.0;
		edgeLength[e] = factor*(sum);
	}
}
예제 #13
0
void FastMultipoleMultilevelEmbedder::initFinestLevel(GraphAttributes &GA, const EdgeArray<float>& edgeLength)
{
#if 0
	NodeArray<float> perimeter(GA.constGraph(), 0.0);
#endif
	for(node v : GA.constGraph().nodes)
	{
		GalaxyMultilevel::LevelNodeInfo& nodeInfo = (*(m_pFinestLevel->m_pNodeInfo))[v];
		nodeInfo.mass = 1.0;
		float r = (float)sqrt(GA.width(v)*GA.width(v) + GA.height(v)*GA.height(v)) * 0.5f;
		nodeInfo.radius = r;
	}

	for(edge e : GA.constGraph().edges)
	{
		GalaxyMultilevel::LevelEdgeInfo& edgeInfo = (*(m_pFinestLevel->m_pEdgeInfo))[e];
		node v = e->source();
		node w = e->target();
		GalaxyMultilevel::LevelNodeInfo& vNodeInfo = (*(m_pFinestLevel->m_pNodeInfo))[v];
		GalaxyMultilevel::LevelNodeInfo& wNodeInfo = (*(m_pFinestLevel->m_pNodeInfo))[w];
		edgeInfo.length = (vNodeInfo.radius +  wNodeInfo.radius) + edgeLength[e];
	}
}
예제 #14
0
파일: DavidsonHarel.cpp 프로젝트: ogdf/ogdf
//the vertices with degree zero are placed below all other vertices on a horizontal
// line centered with repect to the rest of the drawing
void DavidsonHarel::placeIsolatedNodes(GraphAttributes &AG) const {
	double minX = 0.0;
	double minY = 0.0;
	double maxX = 0.0;

	if (!m_nonIsolatedNodes.empty()) {
		//compute a rectangle that includes all non-isolated vertices
		node vFirst = m_nonIsolatedNodes.front();
		minX = AG.x(vFirst);
		minY = AG.y(vFirst);
		maxX = minX;
		double maxY = minY;
		for (node v : m_nonIsolatedNodes) {
			double xVal = AG.x(v);
			double yVal = AG.y(v);
			double halfHeight = AG.height(v) / 2.0;
			double halfWidth = AG.width(v) / 2.0;
			if (xVal - halfWidth < minX) minX = xVal - halfWidth;
			if (xVal + halfWidth > maxX) maxX = xVal + halfWidth;
			if (yVal - halfHeight < minY) minY = yVal - halfHeight;
			if (yVal + halfHeight > maxY) maxY = yVal + halfHeight;
		}
	}

	// compute the width and height of the largest isolated node
	List<node> isolated;
	const Graph &G = AG.constGraph();
	double maxWidth = 0;
	double maxHeight = 0;
	for (node v : G.nodes)
	if (v->degree() == 0) {
		isolated.pushBack(v);
		if (AG.height(v) > maxHeight) maxHeight = AG.height(v);
		if (AG.width(v) > maxWidth) maxWidth = AG.width(v);
	}
	// The nodes are placed on a line in the middle under the non isolated vertices.
	// Each node gets a box sized 2 maxWidth.
	double boxWidth = 2.0*maxWidth;
	double commonYCoord = minY - (1.5*maxHeight);
	double XCenterOfDrawing = minX + ((maxX - minX) / 2.0);
	double startXCoord = XCenterOfDrawing - 0.5*(isolated.size()*boxWidth);
	double xcoord = startXCoord;
	for (node v : isolated) {
		AG.x(v) = xcoord;
		AG.y(v) = commonYCoord;
		xcoord += boxWidth;
	}
}
예제 #15
0
static void write_ogml_graph_edges(const GraphAttributes &A, ostream &os)
{
	const Graph &G = A.constGraph();

	for(edge e : G.edges) {
		GraphIO::indent(os,3) << "<edge id=\"e" << e->index() << "\">\n";
		if (A.has(GraphAttributes::edgeLabel)) {
			GraphIO::indent(os,4) << "<label id=\"le" << e->index() << "\">\n";
			GraphIO::indent(os,5) << "<content>" << formatLabel(A.label(e)) << "</content>\n";
			GraphIO::indent(os,4) << "</label>\n";
		}
		GraphIO::indent(os,4) << "<source idRef=\"n" << e->source()->index() << "\" />\n";
		GraphIO::indent(os,4) << "<target idRef=\"n" << e->target()->index() << "\" />\n";
		GraphIO::indent(os,3) << "</edge>\n";
	}
}
예제 #16
0
void DominanceLayout::compact(const UpwardPlanRep &UPR, GraphAttributes &GA)
{
	double maxNodeSize = 0;
	for(node v : GA.constGraph().nodes) {
		if (GA.width(v) > maxNodeSize || GA.height(v) > maxNodeSize)
			maxNodeSize = max(GA.width(v), GA.height(v));
	}

	int gridDist = m_grid_dist;
	if (gridDist < maxNodeSize+1)
		gridDist = (int) maxNodeSize+1;

	xCoord.init(UPR);
	yCoord.init(UPR);

	//ASSIGN X COORDINATE

	OGDF_ASSERT(!xNodes.empty());

	node v = xNodes.popFrontRet();
	xCoord[v] = 0;
	while (!xNodes.empty()) {
		node u = xNodes.popFrontRet();
		if ( (yPreCoord[v] > yPreCoord[u]) || (firstout[v] == lastout[v] && firstin[u] == lastin[u] && m_L <= m_R)) {
			xCoord[u] = xCoord[v] + gridDist;
		}
		else
			xCoord[u] = xCoord[v];
		v = u;
	}

	//ASSIGN Y COORDINATE
	OGDF_ASSERT(!yNodes.empty());

	v = yNodes.popFrontRet();
	yCoord[v] = 0;
	while (!yNodes.empty()) {
		node u = yNodes.popFrontRet();
		if ( (xPreCoord[v] > xPreCoord[u]) || (firstout[v] == lastout[v] && firstin[u] == lastin[u] && m_L > m_R)) {
			yCoord[u] = yCoord[v] + gridDist;
		}
		else
			yCoord[u] = yCoord[v];
		v = u;
	}
}
예제 #17
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();
}
예제 #18
0
void FastMultipoleMultilevelEmbedder::run(GraphAttributes& GA, const EdgeArray<float>& edgeLength)
{
	// too lazy for new, delete
	NodeArray<float> nodeXPos1;
	NodeArray<float> nodeYPos1;
	NodeArray<float> nodeXPos2;
	NodeArray<float> nodeYPos2;
	EdgeArray<float> edgeLength1;
	NodeArray<float> nodeSize1;

	m_pCurrentNodeXPos	= &nodeXPos1;
	m_pCurrentNodeYPos	= &nodeYPos1;
	m_pLastNodeXPos		= &nodeXPos2;
	m_pLastNodeYPos		= &nodeYPos2;
	m_pCurrentEdgeLength= &edgeLength1;
	m_pCurrentNodeSize	= &nodeSize1;
	Graph* pGraph = const_cast<Graph*>(&(GA.constGraph()));

	// create all multilevels
	this->createMultiLevelGraphs(pGraph, GA, edgeLength);
	// init the coarsest level
	initCurrentLevel();

	// layout the current level
	layoutCurrentLevel();

	//proceed with remaining levels
	while (m_iCurrentLevelNr > 0)
	{
		// move to finer level
		nextLevel();
		// init the arrays for current level
		initCurrentLevel();
		// assign positions from last to current
		assignPositionsFromPrevLevel();
		// layout the current level
		layoutCurrentLevel();
	}
	// the finest level is processed
	// assumes m_pCurrentGraph == GA.constGraph
	writeCurrentToGraphAttributes(GA);
	// clean up multilevels
	deleteMultiLevelGraphs();
}
예제 #19
0
void TutteLayout::call(GraphAttributes &AG)
{
	const Graph &G = AG.constGraph();

	List<node> fixedNodes;
	List<DPoint> positions;

	double diam =
	sqrt((m_bbox.width()) * (m_bbox.width())
		 + (m_bbox.height()) * (m_bbox.height()));

	// handle graphs with less than two nodes
	switch (G.numberOfNodes()) {
		case 0:
			return;
		case 1:
			node v = G.firstNode();

			DPoint center(0.5 * m_bbox.width(),0.5 * m_bbox.height());
			center = center + m_bbox.p1();

			AG.x(v) = center.m_x;
			AG.y(v) = center.m_y;

			return;
	}

	// increase radius to have no overlap on the outer circle
	node v = G.firstNode();

	double r        = diam/2.8284271;
	int n           = G.numberOfNodes();
	double nodeDiam = 2.0*sqrt((AG.width(v)) * (AG.width(v))
			 + (AG.height(v)) * (AG.height(v)));

	if(r<nodeDiam/(2*sin(2*Math::pi/n))) {
		r=nodeDiam/(2*sin(2*Math::pi/n));
		m_bbox = DRect (0.0, 0.0, 2*r, 2*r);
	}

	setFixedNodes(G,fixedNodes,positions,r);

	doCall(AG,fixedNodes,positions);
}
예제 #20
0
void ArrayGraph::readFrom(const GraphAttributes& GA, const EdgeArray<float>& edgeLength, const NodeArray<float>& nodeSize)
{
    const Graph& G = GA.constGraph();
    NodeArray<__uint32> nodeIndex(G);

    node v;
    m_numNodes = 0;
    m_numEdges = 0;
    m_avgNodeSize = 0;
    m_desiredAvgEdgeLength = 0;
    forall_nodes(v, G)
    {
        m_nodeXPos[m_numNodes] = (float)GA.x(v);
        m_nodeYPos[m_numNodes] = (float)GA.y(v);
        m_nodeSize[m_numNodes] = nodeSize[v];
        nodeIndex[v] = m_numNodes;
        m_avgNodeSize += nodeSize[v];
        m_numNodes++;
    };
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;
	} 
    }
}
예제 #22
0
SpringEmbedderFRExact::ArrayGraph::ArrayGraph(GraphAttributes &ga) : m_ga(&ga), m_mapNode(ga.constGraph())
{
	const Graph &G = ga.constGraph();
	m_numNodes = m_numEdges = 0;

	m_orig = nullptr;
	m_src = m_tgt = nullptr;
	m_x = m_y = nullptr;
	m_nodeWeight = nullptr;
	m_useNodeWeight = false;

	// compute connected components of G
	NodeArray<int> component(G);
	m_numCC = connectedComponents(G,component);

	m_nodesInCC.init(m_numCC);

	for(node v : G.nodes)
		m_nodesInCC[component[v]].pushBack(v);
}
예제 #23
0
// write graph structure with attributes
static void write_ogml_graph(const GraphAttributes &A, ostream &os)
{
	const Graph &G = A.constGraph();

	GraphIO::indent(os,2) << "<structure>\n";

	for(node v : G.nodes) {
		GraphIO::indent(os,3) << "<node id=\"n" << v->index() << "\">\n";
		if (A.has(GraphAttributes::nodeLabel)) {
			GraphIO::indent(os,4) << "<label id=\"ln" << v->index() << "\">\n";
			GraphIO::indent(os,5) << "<content>" << formatLabel(A.label(v)) << "</content>\n";
			GraphIO::indent(os,4) << "</label>\n";
		}
		GraphIO::indent(os,3) << "</node>\n";
	}

	write_ogml_graph_edges(A, os);

	GraphIO::indent(os,2) << "</structure>\n";
}
예제 #24
0
파일: svg.cpp 프로젝트: ogdf/ogdf
void createDocument(GraphAttributes attr, pugi::xml_document &doc, GraphIO::SVGSettings *settings = nullptr, bool reassignPositions = true) {
	std::ostringstream write;

	if(reassignPositions) {
		int i = 0;
		for(node v : attr.constGraph().nodes) {
			attr.x(v) = attr.y(v) = i++ * 100;
			attr.width(v) = attr.height(v) = 10;
		}
	}

	if(settings == nullptr) {
		GraphIO::drawSVG(attr, write);
	} else {
		GraphIO::drawSVG(attr, write, *settings);
	}

	pugi::xml_parse_result result =  doc.load_string(write.str().c_str());
	AssertThat((bool) result, IsTrue());
}
예제 #25
0
static void compute_bounding_box(const GraphAttributes &A, double &xmin, double &ymin, double &xmax, double &ymax)
{
	const Graph &G = A.constGraph();
	if(G.numberOfNodes() == 0) {
		xmin = xmax = ymin = ymax = 0;
		return;
	}

	node v = G.firstNode();
	xmin = xmax = A.x(v),
	ymin = ymax = A.y(v);

	forall_nodes(v, G) {
		double lw = (A.attributes() & GraphAttributes::nodeStyle) ? 0.5*A.strokeWidth(v) : 0.5;

		xmax = max(xmax, A.x(v) + A.width (v)/2 + lw);
		ymax = max(ymax, A.y(v) + A.height(v)/2 + lw);
		xmin = min(xmin, A.x(v) - A.width (v)/2 - lw);
		ymin = min(ymin, A.y(v) - A.height(v)/2 - lw);
	}
예제 #26
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)));
		}
예제 #27
0
void StressMinimization::minimizeStress(
	GraphAttributes& GA,
	NodeArray<NodeArray<double> >& shortestPathMatrix,
	NodeArray<NodeArray<double> >& weightMatrix)
{
	const Graph& G = GA.constGraph();
	int numberOfPerformedIterations = 0;

	double prevStress = numeric_limits<double>::max();
	double curStress = numeric_limits<double>::max();

	if (m_terminationCriterion == STRESS) {
		curStress = calcStress(GA, shortestPathMatrix, weightMatrix);
	}

	NodeArray<double> newX;
	NodeArray<double> newY;
	NodeArray<double> newZ;

	if (m_terminationCriterion == POSITION_DIFFERENCE) {
		newX.init(G);
		newY.init(G);
		if (GA.has(GraphAttributes::threeD))
			newZ.init(G);
	}
	do {
		if (m_terminationCriterion == POSITION_DIFFERENCE) {
			if (GA.has(GraphAttributes::threeD))
				copyLayout(GA, newX, newY, newZ);
			else copyLayout(GA, newX, newY);
		}
		nextIteration(GA, shortestPathMatrix, weightMatrix);
		if (m_terminationCriterion == STRESS) {
			prevStress = curStress;
			curStress = calcStress(GA, shortestPathMatrix, weightMatrix);
		}
	} while (!finished(GA, ++numberOfPerformedIterations, newX, newY, prevStress, curStress));

	Logger::slout() << "Iteration count:\t" << numberOfPerformedIterations
		<< "\tStress:\t" << calcStress(GA, shortestPathMatrix, weightMatrix) << endl;
}
예제 #28
0
MultilevelGraph::MultilevelGraph(GraphAttributes &GA)
:m_createdGraph(false)
{
	m_G = new Graph();
	if(m_G == 0) {
		OGDF_THROW(InsufficientMemoryException);
	} else {
		m_createdGraph = true;
	}
	m_nodeAssociations.init(*m_G);
	m_edgeAssociations.init(*m_G);
	m_x.init(*m_G);
	m_y.init(*m_G);
	m_radius.init(*m_G);
	m_weight.init(*m_G);
	copyFromGraph(GA.constGraph(), m_nodeAssociations, m_edgeAssociations);
	prepareGraphAttributes(GA);
	importAttributes(GA);

	initReverseIndizes();
}
예제 #29
0
MultilevelGraph::MultilevelGraph(GraphAttributes &GA)
:m_createdGraph(true)
{
	m_G = new Graph();
	if(m_G == 0) {
		OGDF_THROW(InsufficientMemoryException);
	} 
	
	//replaces layout info stuff below
	initInternal();

	m_nodeAssociations.init(*m_G);
	m_edgeAssociations.init(*m_G);
	m_radius.init(*m_G);
	m_weight.init(*m_G);
	copyFromGraph(GA.constGraph(), m_nodeAssociations, m_edgeAssociations);
	prepareGraphAttributes(GA);
	importAttributes(GA);

	initReverseIndizes();
}
예제 #30
0
void StressMinimization::call(
	GraphAttributes& GA,
	NodeArray<NodeArray<double> >& shortestPathMatrix,
	NodeArray<NodeArray<double> >& weightMatrix)
{
	// compute the initial layout if necessary
	if (!m_hasInitialLayout) {
		computeInitialLayout(GA);
	}
	const Graph& G = GA.constGraph();
	// replace infinity distances by sqrt(n) and compute weights.
	// Note isConnected is only true during calls triggered by the
	// ComponentSplitterLayout.
	if (!m_componentLayout && !isConnected(G)) {
		replaceInfinityDistances(shortestPathMatrix,
				m_avgEdgeCosts * sqrt((double)(G.numberOfNodes())));
	}
	// calculate the weights
	calcWeights(G, G.numberOfNodes() - 1, shortestPathMatrix, weightMatrix);
	// minimize the stress
	minimizeStress(GA, shortestPathMatrix, weightMatrix);
}