Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
DTreeMultilevelEmbedder.h
Go to the documentation of this file.
1
29#pragma once
30
31#include <ogdf/basic/Graph.h>
34#include <ogdf/basic/basic.h>
39
40#include <algorithm>
41
42namespace ogdf {
43
44template<int Dim>
46public:
47 struct NodeCoords {
48 double coords[Dim];
49 };
50
76
78 void call(const Graph& graph, NodeArray<NodeCoords>& coords);
79
80private:
90
93};
94
96public:
97 void call(GraphAttributes& GA) override {
98 // the graph
99 const Graph& G = GA.constGraph();
100
101 // the input for the general d dim class
103
104 // call it
106
107 // copy the coords back to graph attributes
108 for (node v = G.firstNode(); v; v = v->succ()) {
109 GA.x(v) = coords[v].coords[0];
110 GA.y(v) = coords[v].coords[1];
111 }
112 }
113};
114
116public:
117 void call(GraphAttributes& GA) override {
118 // assert 3d
120
121 // the graph
122 const Graph& G = GA.constGraph();
123
124 // the input for the general d dim class
126
127 // call it
129
130 // copy the coords back to graph attributes
131 for (node v = G.firstNode(); v; v = v->succ()) {
132 GA.x(v) = coords[v].coords[0];
133 GA.y(v) = coords[v].coords[1];
134 GA.z(v) = coords[v].coords[2];
135 }
136 }
137};
138
139template<int Dim>
141 using namespace energybased::dtree;
142 using Embedder = DTreeEmbedder<Dim>;
143
144 // we call this just in case
145 resultCoords.init(graph);
146
147 // make sure the graph is connected
148 OGDF_ASSERT(isConnected(graph));
149
150 // setup the multilevel step
151 GalaxyLevel levelBegin(graph);
152
153 // this is the coarsest level with at most m_levelMaxNumNodes
154 GalaxyLevel* pLevelEnd = levelBegin.buildLevelsUntil(m_levelMaxNumNodes);
155
156 // this array will hold the layout information of the parent node in the coarser level.
157 // furthermore this will keep the final result.
158 NodeArray<NodeCoords>& parentPosition = resultCoords;
159
160 double currNumIterations = m_numIterationsFinestLevel;
161 double currThreshold = m_thresholdFinestLevel;
162
163 // loop from the coarsest to the finest level
164 for (GalaxyLevel* pCurrLevel = &levelBegin; pCurrLevel != nullptr;
165 pCurrLevel = pCurrLevel->nextCoarser()) {
166 currNumIterations *= m_numIterationsFactorPerLevel;
167 currThreshold *= m_thresholdFactorPerLevel;
168 }
169
170 // now we loop from the coarsest to the finest level
171 for (GalaxyLevel* pCurrLevel = pLevelEnd; pCurrLevel; pCurrLevel = pCurrLevel->nextFiner()) {
172 currNumIterations /= m_numIterationsFactorPerLevel;
173 currThreshold /= m_thresholdFactorPerLevel;
174
175 // new embedder instance for the current level
176 Embedder embedder(pCurrLevel->graph());
177
178 // if this is coarsest one
179 if (pCurrLevel->isCoarsestLevel()) {
180 // we cannot init from the parent level, do it random
181 for (node v = pCurrLevel->graph().firstNode(); v; v = v->succ()) {
182 // for all dims
183 for (int d = 0; d < Dim; d++) {
184 // set the position to some random value
185 embedder.setPosition(v, d, randomDouble(-1.0, 1.0));
186 }
187 }
188 } else { // if we have a parent level
189 // iterate over all nodes
190 for (node v = pCurrLevel->graph().firstNode(); v; v = v->succ()) {
191 // this is a node on the coarser level we already processed
192 node v_parent = pCurrLevel->parent(v);
193
194 // now init the position from the parent.
195 for (int d = 0; d < Dim; d++) {
196 // get the position of the parent
197 double offset = parentPosition[v_parent].coords[d] * m_scaleFactorPerLevel;
198
199 // set v's position to the parents pos with some random
200 embedder.setPosition(v, d, offset + randomDouble(-1.0, 1.0));
201 }
202 }
203 }
204 // we have some proper initial coordinates for the nodes
205
206 if (m_useMultilevelWeights) {
207 // we cannot init from the parent level, do it random
208 for (node v = pCurrLevel->graph().firstNode(); v; v = v->succ()) {
209 embedder.setMass(v, pCurrLevel->weight(v));
210 }
211
212 for (edge e = pCurrLevel->graph().firstEdge(); e; e = e->succ()) {
213 embedder.setEdgeWeight(e, pCurrLevel->edgeWeight(e));
214 }
215 }
216
217 const int numIterationsMaybe =
218 pCurrLevel->isCoarsestLevel() ? m_numIterationsCoarsestLevel : currNumIterations;
219 const int numIterations = std::min(std::max(m_minIterationsPerLevel, numIterationsMaybe),
220 m_maxIterationsPerLevel);
221
222 embedder.scaleNodes(3.0);
223 embedder.doIterationsNewton(numIterations, currThreshold, RepForceFunctionNewton<Dim, 1>,
224 AttrForceFunctionPow<Dim, 2>);
225 embedder.scaleNodes(1.0 / 3.0);
226 embedder.doIterationsNewton(numIterations, currThreshold, RepForceFunctionNewton<Dim, 2>,
227 AttrForceFunctionPow<Dim, 2>);
228 // run the layout
229
230 // we now have to backup the positions before getting rid of the embedder
231 parentPosition.init(pCurrLevel->graph());
232
233 // iterate over all nodes
234 for (node v = pCurrLevel->graph().firstNode(); v; v = v->succ()) {
235 // for all coords
236 for (int d = 0; d < Dim; d++) {
237 parentPosition[v].coords[d] = embedder.position(v, d);
238 }
239 }
240 }
241
242 // we are done with the layout. It is saved now in the parentposition nodearray.
243 // which is a reference to the result array
244}
245
246}
Includes declaration of graph class.
Declaration of class GraphAttributes which extends a Graph by additional attributes.
Declaration of interface for layout algorithms (class LayoutModule)
Basic declarations, included by all source files.
void call(GraphAttributes &GA) override
Computes a layout of graph GA.
void call(GraphAttributes &GA) override
Computes a layout of graph GA.
DTreeMultilevelEmbedder()
constructor with a given graph, allocates memory and does initialization
void call(const Graph &graph, NodeArray< NodeCoords > &coords)
call the multilevel embedder layout for graph, the result is stored in coords
Class for the representation of edges.
Definition Graph_d.h:364
edge succ() const
Returns the successor in the list of all edges.
Definition Graph_d.h:434
Stores additional attributes of a graph (like layout information).
double y(node v) const
Returns the y-coordinate of node v.
double x(node v) const
Returns the x-coordinate of node v.
const Graph & constGraph() const
Returns a reference to the associated graph.
static const long threeD
Corresponds to node attribute z(node). Note that all methods work on 2D coordinates only.
bool has(long attr) const
Returns true iff all attributes in attr are available.
double z(node v) const
Returns the z-coordinate of node v.
Data type for general directed graphs (adjacency list representation).
Definition Graph_d.h:866
Interface of general layout algorithms.
Class for the representation of nodes.
Definition Graph_d.h:241
node succ() const
Returns the successor in the list of all nodes.
Definition Graph_d.h:293
void init(const Base *base=nullptr)
Reinitializes the array. Associates the array with the matching registry of base.
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition Graph_d.h:659
bool isConnected(const Graph &G)
Returns true iff G is connected.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:52
double randomDouble(double low, double high)
Returns a random double value from the interval [low, high).
The namespace for all OGDF objects.
Declaration of simple graph algorithms.