1 /** \file
2  * \brief Declaration of Fast Multipole Multilevel Method (FM^3).
3  *
4  * \author Stefan Hachul
5  *
6  * \par License:
7  * This file is part of the Open Graph Drawing Framework (OGDF).
8  *
9  * \par
10  * Copyright (C)<br>
11  * See README.md in the OGDF root directory for details.
12  *
13  * \par
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * Version 2 or 3 as published by the Free Software Foundation;
17  * see the file LICENSE.txt included in the packaging of this file
18  * for details.
19  *
20  * \par
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * \par
27  * You should have received a copy of the GNU General Public
28  * License along with this program; if not, see
29  * http://www.gnu.org/copyleft/gpl.html
30  */
31 
32 #pragma once
33 
34 #include <ogdf/basic/Graph.h>
35 #include <ogdf/cluster/ClusterGraphAttributes.h>
36 #include <ogdf/basic/LayoutModule.h>
37 #include <ogdf/basic/geometry.h>
38 #include <ogdf/energybased/fmmm/NewMultipoleMethod.h>
39 #include <ogdf/energybased/fmmm/maar_packing/Rectangle.h>
40 
41 namespace ogdf {
42 
43 /**
44  * \brief The fast multipole multilevel layout algorithm.
45  *
46  * @ingroup gd-energy
47  *
48  * The class FMMMLayout implements a force-directed graph drawing
49  * method suited also for very large graphs. It is based on a
50  * combination of an efficient multilevel scheme and a strategy for
51  * approximating the repulsive forces in the system by rapidly
52  * evaluating potential fields.
53  *
54  * The implementation is based on the following publication:
55  *
56  * Stefan Hachul, Michael Jünger: <i>Drawing Large Graphs with a
57  * Potential-Field-Based Multilevel Algorithm</i>. 12th International
58  * Symposium on %Graph Drawing 1998, New York (GD '04), LNCS 3383,
59  * pp. 285-295, 2004.
60  *
61  * <H3>Optional parameters</H3>
62  * The following options are the most important. You can set
63  * useHighLevelOptions to true and just need to adjust a few parameters.
64  * However, you can also adjust all parameters that the implementation
65  * uses (see below), but this requires good knowledge of the algorithm.
66  *
67  * <table>
68  *   <tr>
69  *     <th><i>Option</i><th><i>Type</i><th><i>Default</i><th><i>Description</i>
70  *   </tr><tr>
71  *     <td><i>useHighLevelOptions</i><td>bool<td>false
72  *     <td>Whether high-level options are used or not.
73  *   </tr><tr>
74  *     <td><i>pageFormat</i><td> FMMMOptions::PageFormatType <td> \c Square
75  *     <td>The desired aspect ratio of the layout.
76  *   </tr><tr>
77  *     <td><i>unitEdgeLength</i><td>double<td>100.0
78  *     <td>The unit edge length.
79  *   </tr><tr>
80  *     <td><i>newInitialPlacement</i><td>bool<td>false
81  *     <td>Specifies if initial placement of nodes is varied.
82  *   </tr><tr>
83  *     <td><i>qualityVersusSpeed</i><td> FMMMOptions::QualityVsSpeed <td> \c BeautifulAndFast
84  *     <td>Indicates if the algorithm is tuned either for best quality or best speed.
85  *   </tr>
86  * </table>
87  *
88  * If you want to do more detailed fine-tuning, you can adjust all parameters
89  * used by the algorithm. Please refer to the paper cited above for better
90  * understanding of the algorithm.
91  *
92  * <table>
93  *   <tr>
94  *     <th colspan="4" align="center"><b>General</b>
95  *   </tr><tr>
96  *     <td><i>randSeed</i><td>int<td>100
97  *     <td>The seed of the random number generator.
98  *   </tr><tr>
99  *     <td><i>edgeLengthMeasurement</i><td> FMMMOptions::EdgeLengthMeasurement <td> \c BoundingCircle
100  *     <td>Indicates how the length of an edge is measured.
101  *   </tr><tr>
102  *     <td><i>allowedPositions</i><td> FMMMOptions::AllowedPositions <td> \c Integer
103  *     <td>Defines which positions for a node are allowed.
104  *   </tr><tr>
105  *     <td><i>maxIntPosExponent</i><td>int<td>40
106  *     <td>Defines the exponent used if allowedPositions == Exponent.
107  *   </tr><tr>
108  *     <th colspan="4" align="center"><b>Divide et impera step</b>
109  *   </tr><tr>
110  *     <td><i>pageRatio</i><td>double<td>1.0
111  *     <td>The desired page ratio.
112  *   </tr><tr>
113  *     <td><i>stepsForRotatingComponents</i><td>int<td>10
114  *     <td>The number of rotations per connected component.
115  *   </tr><tr>
116  *     <td><i>tipOverCCs</i><td> FMMMOptions::TipOver <td> \c NoGrowingRow
117  *     <td>Specifies when it is allowed to tip over drawings.
118  *   </tr><tr>
119  *     <td><i>minDistCC</i><td>double<td>100
120  *     <td>The minimal distance between connected components.
121  *   </tr><tr>
122  *     <td><i>presortCCs</i><td> FMMMOptions::PreSort <td> \c DecreasingHeight
123  *     <td>Defines if the connected components are sorted before
124  *     the packing algorithm is applied.
125  *   </tr><tr>
126  *     <th colspan="4" align="center"><b>Multilevel step</b>
127  *   </tr><tr>
128  *     <td><i>minGraphSize</i><td>int<td>50
129  *     <td>Determines the number of nodes of a graph for which
130  *     no more collapsing of galaxies is performed.
131  *   </tr><tr>
132  *     <td><i>galaxyChoice</i><td> FMMMOptions::GalaxyChoice <td> \c NonUniformProbLowerMass
133  *     <td>Defines how sun nodes of galaxies are selected.
134  *   </tr><tr>
135  *     <td><i>randomTries</i><td>int<td>20
136  *     <td>Defines the number of tries to get a random node with
137  *     minimal star mass.
138  *   </tr><tr>
139  *     <td><i>maxIterChange</i><td> FMMMOptions::MaxIterChange <td> \c LinearlyDecreasing
140  *     <td>Defines how MaxIterations is changed in subsequent multilevels.
141  *   </tr><tr>
142  *     <td><i>maxIterFactor</i><td>int<td>10
143  *     <td>Defines the factor used for decreasing MaxIterations.
144  *   </tr><tr>
145  *     <td><i>initialPlacementMult</i><td> FMMMOptions::InitialPlacementMult <td> \c Advanced
146  *     <td>Defines how the initial placement is generated.
147  *   </tr><tr>
148  *     <th colspan="4" align="center"><b>Force calculation step</b>
149  *   </tr><tr>
150  *     <td><i>forceModel</i><td> FMMMOptions::ForceModel <td> \c New
151  *     <td>The used force model.
152  *   </tr><tr>
153  *     <td><i>springStrength</i><td>double<td>1.0
154  *     <td>The strength of the springs.
155  *   </tr><tr>
156  *     <td><i>repForcesStrength</i><td>double<td>1.0
157  *     <td>The strength of the repulsive forces.
158  *   </tr><tr>
159  *     <td><i>repulsiveForcesCalculation</i><td> FMMMOptions::RepulsiveForcesMethod <td> \c NMM
160  *     <td>Defines how to calculate repulsive forces.
161  *   </tr><tr>
162  *     <td><i>stopCriterion</i><td> FMMMOptions::StopCriterion <td> \c FixedIterationsOrThreshold
163  *     <td>The stop criterion.
164  *   </tr><tr>
165  *     <td><i>threshold</i><td>double<td>0.01
166  *     <td>The threshold for the stop criterion.
167  *   </tr><tr>
168  *     <td><i>fixedIterations</i><td>int<td>30
169  *     <td>The fixed number of iterations for the stop criterion.
170  *   </tr><tr>
171  *     <td><i>forceScalingFactor</i><td>double<td>0.05
172  *     <td>The scaling factor for the forces.
173  *   </tr><tr>
174  *     <td><i>coolTemperature</i><td>bool<td>false
175  *     <td>Use coolValue for scaling forces.
176  *   </tr><tr>
177  *     <td><i>coolValue</i><td>double<td>0.99
178  *     <td>The value by which forces are decreased.
179  *   </tr><tr>
180  *     <td><i>initialPlacementForces</i><td> FMMMOptions::InitialPlacementForces <td> \c RandomRandIterNr
181  *     <td>Defines how the initial placement is done.
182  *   </tr><tr>
183  *     <th colspan="4" align="center"><b>Force calculation step</b>
184  *   </tr><tr>
185  *     <td><i>resizeDrawing</i><td>bool<td>true
186  *     <td>Specifies if the resulting drawing is resized.
187  *   </tr><tr>
188  *     <td><i>resizingScalar</i><td>double<td>1
189  *     <td>Defines a parameter to scale the drawing if resizeDrawing is true.
190  *   </tr><tr>
191  *     <td><i>fineTuningIterations</i><td>int<td>20
192  *     <td>The number of iterations for fine tuning.
193  *   </tr><tr>
194  *     <td><i>fineTuneScalar</i><td>double<td>0.2
195  *     <td>Defines a parameter for scaling the forces in the fine-tuning iterations.
196  *   </tr><tr>
197  *     <td><i>adjustPostRepStrengthDynamically</i><td>bool<td>true
198  *     <td>If set to true, the strength of the repulsive force field is calculated.
199  *   </tr><tr>
200  *     <td><i>postSpringStrength</i><td>double<td>2.0
201  *     <td>The strength of the springs in the postprocessing step.
202  *   </tr><tr>
203  *     <td><i>postStrengthOfRepForces</i><td>double<td>0.01
204  *     <td>The strength of the repulsive forces in the postprocessing step.
205  *   </tr><tr>
206  *     <th colspan="4" align="center"><b>Repulsive force approximation methods</b>
207  *   </tr><tr>
208  *     <td><i>frGridQuotient</i><td>int<td>2
209  *     <td>The grid quotient.
210  *   </tr><tr>
211  *     <td><i>nmTreeConstruction</i><td> FMMMOptions::ReducedTreeConstruction <td> \c SubtreeBySubtree
212  *     <td>Defines how the reduced bucket quadtree is constructed.
213  *   </tr><tr>
214  *     <td><i>nmSmallCell</i><td> FMMMOptions::SmallestCellFinding <td> \c Iteratively
215  *     <td>Defines how the smallest quadratic cell that surrounds
216  *     the particles of a node in the reduced bucket quadtree is calculated.
217  *   </tr><tr>
218  *     <td><i>nmParticlesInLeaves</i><td>int<td>25
219  *     <td>The maximal number of particles that are contained in
220  *     a leaf of the reduced bucket quadtree.
221  *   </tr><tr>
222  *     <td><i>nmPrecision</i><td>int<td>4
223  *     <td>The precision \a p for the <i>p</i>-term multipole expansions.
224  *   </tr>
225  * </table>
226  *
227  * <H3>Running time</H3>
228  * The running time of the algorithm is
229  * O(<i>n</i> log <i>n</i> + <i>m</i>) for graphs with \a n nodes
230  * and \a m edges. The required space is linear in the input size.
231  */
232 class OGDF_EXPORT FMMMLayout : public LayoutModule
233 {
234 	using Rectangle = energybased::fmmm::Rectangle;
235 	using NodeAttributes = energybased::fmmm::NodeAttributes;
236 	using EdgeAttributes = energybased::fmmm::EdgeAttributes;
237 
238 public:
239 	//! Creates an instance of the layout algorithm.
240 	FMMMLayout();
241 
242 	// destructor
~FMMMLayout()243 	virtual ~FMMMLayout() { }
244 
245 
246 	/**
247 	 *  @name The algorithm call
248 	 *  @{
249 	 */
250 
251 	//! Calls the algorithm for graph \p GA and returns the layout information in \p GA.
252 	virtual void call(GraphAttributes &GA) override;
253 
254 	//! Calls the algorithm for clustered graph \p GA and returns the layout information in \p GA.
255 	//! Models cluster by simple edge length adaption based on least common ancestor
256 	//! cluster of end vertices.
257 	void call(ClusterGraphAttributes &GA);
258 
259 	//! Extended algorithm call: Allows to pass desired lengths of the edges.
260 	/**
261 	 * @param GA represents the input graph and is assigned the computed layout.
262 	 * @param edgeLength is an edge array of the graph associated with \p GA
263 	 *        of positive edge length.
264 	 */
265 	void call(
266 		GraphAttributes &GA,   //graph and layout
267 		const EdgeArray<double> &edgeLength); //factor for desired edge lengths
268 
269 	//! Extended algorithm call: Calls the algorithm for graph \p GA.
270 	/**
271 	 * Returns layout information in \p GA and a simple drawing is saved in file \p ps_file
272 	 * in postscript format (Nodes are drawn as uniformly sized circles).
273 	 */
274 	void call(GraphAttributes &GA, char* ps_file);
275 
276 	//! Extend algorithm call: Allows to pass desired lengths of the edges.
277 	/**
278 	 * The EdgeArray \p edgeLength must be valid for GA.constGraph() and its values must
279 	 * be positive.
280 	 * A simple drawing is saved in file ps_file in postscript format (Nodes are drawn
281 	 * as uniformly sized circles).
282 	 */
283 	void call(
284 		GraphAttributes &GA,   //graph and layout
285 		const EdgeArray<double> &edgeLength, //factor for desired edge lengths
286 		char* ps_file);
287 
288 	/** @}
289 	 *  @name Further information.
290 	 *  @{
291 	 */
292 
293 	//! Returns the runtime (=CPU-time) of the layout algorithm in seconds.
getCpuTime()294 	double getCpuTime() {
295 		return time_total;
296 	}
297 
298 
299 	/** @}
300 	 *  @name High-level options
301 	 *  Allow to specify the most relevant parameters.
302 	 *  @{
303 	 */
304 
305 	//! Returns the current setting of option useHighLevelOptions.
306 	/**
307 	 * If set to true, the high-level options are used to set all low-level options.
308 	 * Usually, it is sufficient just to set high-level options; if you want to
309 	 * be more specific, set this parameter to false and set the low level options.
310 	 */
useHighLevelOptions()311 	bool useHighLevelOptions() const { return m_useHighLevelOptions; }
312 
313 	//! Sets the option useHighLevelOptions to \p uho.
useHighLevelOptions(bool uho)314 	void useHighLevelOptions(bool uho) { m_useHighLevelOptions = uho; }
315 
316 	//! Sets single level option, no multilevel hierarchy is created if b == true
setSingleLevel(bool b)317 	void setSingleLevel(bool b) {m_singleLevel = b;}
318 
319 	//! Returns the current setting of option pageFormat.
pageFormat()320 	FMMMOptions::PageFormatType pageFormat() const { return m_pageFormat; }
321 
322 	//! Sets the option pageRatio to \p t.
pageFormat(FMMMOptions::PageFormatType t)323 	void pageFormat(FMMMOptions::PageFormatType t) { m_pageFormat = t; }
324 
325 	//! Returns the current setting of option unitEdgeLength.
unitEdgeLength()326 	double unitEdgeLength() const { return m_unitEdgeLength; }
327 
328 	//! Sets the option unitEdgeLength to \p x.
unitEdgeLength(double x)329 	void unitEdgeLength(double x) {m_unitEdgeLength = (( x > 0.0) ? x : 1);}
330 
331 	//! Returns the current setting of option newInitialPlacement.
332 	/**
333 	 * This option defines if the initial placement of the nodes at the
334 	 * coarsest multilevel is varied for each distinct call of FMMMLayout
335 	 * or keeps always the same.
336 	 */
newInitialPlacement()337 	bool newInitialPlacement() const { return m_newInitialPlacement; }
338 
339 	//! Sets the option newInitialPlacement to \p nip.
newInitialPlacement(bool nip)340 	void newInitialPlacement(bool nip) { m_newInitialPlacement = nip; }
341 
342 	//! Returns the current setting of option qualityVersusSpeed.
qualityVersusSpeed()343 	FMMMOptions::QualityVsSpeed qualityVersusSpeed() const { return m_qualityVersusSpeed; }
344 
345 	//! Sets the option qualityVersusSpeed to \p qvs.
qualityVersusSpeed(FMMMOptions::QualityVsSpeed qvs)346 	void qualityVersusSpeed(FMMMOptions::QualityVsSpeed qvs) {m_qualityVersusSpeed = qvs; }
347 
348 
349 	/** @}
350 	 *  @name General low-level options
351 	 * The low-level options in this and the following sections are meant for
352 	 * experts or interested people only.
353 	 *  @{
354 	 */
355 
356 	//! Sets the seed of the random number generator.
randSeed(int p)357 	void randSeed(int p) { m_randSeed = ((0<=p) ? p : 1);}
358 
359 	//! Returns the seed of the random number generator.
randSeed()360 	int randSeed() const {return m_randSeed;}
361 
362 	//! Returns the current setting of option edgeLengthMeasurement.
edgeLengthMeasurement()363 	FMMMOptions::EdgeLengthMeasurement edgeLengthMeasurement() const {
364 		return m_edgeLengthMeasurement;
365 	}
366 
367 	//! Sets the option edgeLengthMeasurement to \p elm.
edgeLengthMeasurement(FMMMOptions::EdgeLengthMeasurement elm)368 	void edgeLengthMeasurement(FMMMOptions::EdgeLengthMeasurement elm) { m_edgeLengthMeasurement = elm; }
369 
370 	//! Returns the current setting of option allowedPositions.
allowedPositions()371 	FMMMOptions::AllowedPositions allowedPositions() const { return m_allowedPositions; }
372 
373 	//! Sets the option allowedPositions to \p ap.
allowedPositions(FMMMOptions::AllowedPositions ap)374 	void allowedPositions(FMMMOptions::AllowedPositions ap) { m_allowedPositions = ap; }
375 
376 	//! Returns the current setting of option maxIntPosExponent.
377 	/**
378 	 * This option defines the exponent used if allowedPositions() == FMMMOptions::AllowedPositions::Exponent.
379 	 */
maxIntPosExponent()380 	int maxIntPosExponent() const { return m_maxIntPosExponent; }
381 
382 	//! Sets the option maxIntPosExponent to \p e.
maxIntPosExponent(int e)383 	void maxIntPosExponent(int e) {
384 		m_maxIntPosExponent = (((e >= 31)&&(e<=51))? e : 31);
385 	}
386 
387 
388 	/** @}
389 	 *  @name Options for the divide et impera step
390 	 *  @{
391 	 */
392 
393 	//! Returns the current setting of option pageRatio.
394 	/**
395 	 * This option defines the desired aspect ratio of the rectangular drawing area.
396 	 */
pageRatio()397 	double pageRatio() const { return m_pageRatio; }
398 
399 	//! Sets the option pageRatio to \p r.
pageRatio(double r)400 	void pageRatio(double r) {m_pageRatio = (( r > 0) ? r : 1);}
401 
402 	//! Returns the current setting of option stepsForRotatingComponents.
403 	/**
404 	 * This options determines the number of times each connected component is rotated with
405 	 * angles between 0 and 90 degree to obtain a bounding rectangle with small area.
406 	 */
stepsForRotatingComponents()407 	int stepsForRotatingComponents() const { return m_stepsForRotatingComponents; }
408 
409 	//! Sets the option stepsForRotatingComponents to \p n.
stepsForRotatingComponents(int n)410 	void stepsForRotatingComponents(int n) {
411 		m_stepsForRotatingComponents = ((0<=n) ? n : 0);
412 	}
413 
414 	//! Returns the current setting of option tipOverCCs.
tipOverCCs()415 	FMMMOptions::TipOver tipOverCCs() const { return m_tipOverCCs; }
416 
417 	//! Sets the option tipOverCCs to \p to.
tipOverCCs(FMMMOptions::TipOver to)418 	void tipOverCCs(FMMMOptions::TipOver to) { m_tipOverCCs = to; }
419 
420 	//! Returns the  minimal distance between connected components.
minDistCC()421 	double minDistCC() const { return m_minDistCC; }
422 
423 	//! Sets the  minimal distance between connected components to \p x.
minDistCC(double x)424 	void minDistCC(double x) { m_minDistCC = (( x > 0) ? x : 1);}
425 
426 	//! Returns the current setting of option presortCCs.
presortCCs()427 	FMMMOptions::PreSort presortCCs() const { return m_presortCCs; }
428 
429 	//! Sets the option presortCCs to \p ps.
presortCCs(FMMMOptions::PreSort ps)430 	void presortCCs(FMMMOptions::PreSort ps) { m_presortCCs = ps; }
431 
432 
433 	/** @}
434 	 *  @name Options for the multilevel step
435 	 *  @{
436 	 */
437 
438 	//! Returns the current setting of option minGraphSize.
439 	/**
440 	 * This option determines the number of nodes of a graph in the
441 	 * multilevel representation for which no more collapsing of galaxies
442 	 * is performed (i.e. the graph at the highest level).
443 	 */
minGraphSize()444 	int minGraphSize() const { return m_minGraphSize; }
445 
446 	//! Sets the option minGraphSize to \p n.
minGraphSize(int n)447 	void minGraphSize(int n) { m_minGraphSize = ((n >= 2)? n : 2);}
448 
449 	//! Returns the current setting of option galaxyChoice.
galaxyChoice()450 	FMMMOptions::GalaxyChoice galaxyChoice() const { return m_galaxyChoice; }
451 
452 	//! Sets the option galaxyChoice to \p gc.
galaxyChoice(FMMMOptions::GalaxyChoice gc)453 	void galaxyChoice(FMMMOptions::GalaxyChoice gc) { m_galaxyChoice = gc; }
454 
455 	//! Returns the current setting of option randomTries.
456 	/**
457 	 * This option defines the number of tries to get a random node with
458 	 * minimal star mass (used in case of galaxyChoice() == NonUniformProbLowerMass
459 	 * and galaxyChoice() == NonUniformProbHigherMass).
460 	 */
randomTries()461 	int randomTries() const { return m_randomTries; }
462 
463 	//! Sets the option randomTries to \p n.
randomTries(int n)464 	void randomTries(int n) {m_randomTries = ((n>=1)? n: 1);}
465 
466 	//! Returns the current setting of option maxIterChange.
maxIterChange()467 	FMMMOptions::MaxIterChange maxIterChange() const { return m_maxIterChange; }
468 
469 	//! Sets the option maxIterChange to \p mic.
maxIterChange(FMMMOptions::MaxIterChange mic)470 	void maxIterChange(FMMMOptions::MaxIterChange mic) { m_maxIterChange = mic; }
471 
472 	//! Returns the current setting of option maxIterFactor.
473 	/**
474 	 * This option defines the factor used for decrasing MaxIterations
475 	 * (in case of maxIterChange() == LinearlyDecreasing or maxIterChange()
476 	 * == RapidlyDecreasing).
477 	 */
maxIterFactor()478 	int maxIterFactor() const { return m_maxIterFactor; }
479 
480 	//! Sets the option maxIterFactor to \p f.
maxIterFactor(int f)481 	void maxIterFactor(int f) { m_maxIterFactor = ((f>=1) ? f : 1 ); }
482 
483 	//! Returns the current setting of option initialPlacementMult.
initialPlacementMult()484 	FMMMOptions::InitialPlacementMult initialPlacementMult() const {
485 		return m_initialPlacementMult;
486 	}
487 
488 	//! Sets the option initialPlacementMult to \p ipm.
initialPlacementMult(FMMMOptions::InitialPlacementMult ipm)489 	void initialPlacementMult(FMMMOptions::InitialPlacementMult ipm) {
490 		m_initialPlacementMult = ipm;
491 	}
492 
493 
494 	/** @}
495 	 *  @name Options for the force calculation step
496 	 *  @{
497 	 */
498 
499 	//! Returns the used force model.
forceModel()500 	FMMMOptions::ForceModel forceModel() const { return m_forceModel; }
501 
502 	//! Sets the used force model to \p fm.
forceModel(FMMMOptions::ForceModel fm)503 	void forceModel(FMMMOptions::ForceModel fm) { m_forceModel = fm; }
504 
505 	//! Returns the strength of the springs.
springStrength()506 	double springStrength() const { return m_springStrength; }
507 
508 	//! Sets the strength of the springs to \p x.
springStrength(double x)509 	void springStrength(double x) { m_springStrength  = ((x > 0)? x : 1);}
510 
511 	//! Returns the strength of the repulsive forces.
repForcesStrength()512 	double repForcesStrength() const { return m_repForcesStrength; }
513 
514 	//! Sets the strength of the repulsive forces to \p x.
repForcesStrength(double x)515 	void repForcesStrength(double x) { m_repForcesStrength =((x > 0)? x : 1);}
516 
517 	//! Returns the current setting of option repulsiveForcesCalculation.
repulsiveForcesCalculation()518 	FMMMOptions::RepulsiveForcesMethod repulsiveForcesCalculation() const {
519 		return m_repulsiveForcesCalculation;
520 	}
521 
522 	//! Sets the option repulsiveForcesCalculation to \p rfc.
repulsiveForcesCalculation(FMMMOptions::RepulsiveForcesMethod rfc)523 	void repulsiveForcesCalculation(FMMMOptions::RepulsiveForcesMethod rfc) {
524 		m_repulsiveForcesCalculation = rfc;
525 	}
526 
527 	//! Returns the stop criterion.
stopCriterion()528 	FMMMOptions::StopCriterion stopCriterion() const { return m_stopCriterion; }
529 
530 	//! Sets the stop criterion to \p rsc.
stopCriterion(FMMMOptions::StopCriterion rsc)531 	void stopCriterion(FMMMOptions::StopCriterion rsc) { m_stopCriterion = rsc; }
532 
533 	//! Returns the threshold for the stop criterion.
534 	/**
535 	 * (If the average absolute value of all forces in
536 	 * an iteration is less then threshold() then stop.)
537 	 */
threshold()538 	double threshold() const { return m_threshold; }
539 
540 	//! Sets the threshold for the stop criterion to \p x.
threshold(double x)541 	void threshold(double x) {m_threshold = ((x > 0) ? x : 0.1);}
542 
543 	//! Returns the fixed number of iterations for the stop criterion.
fixedIterations()544 	int fixedIterations() const { return m_fixedIterations; }
545 
546 	//! Sets the fixed number of iterations for the stop criterion to \p n.
fixedIterations(int n)547 	void fixedIterations(int n) { m_fixedIterations = ((n >= 1) ? n : 1);}
548 
549 	//! Returns the scaling factor for the forces.
forceScalingFactor()550 	double forceScalingFactor() const { return m_forceScalingFactor; }
551 
552 	//! Sets the scaling factor for the forces to \p f.
forceScalingFactor(double f)553 	void forceScalingFactor(double f) { m_forceScalingFactor = ((f > 0) ? f : 1);}
554 
555 	//! Returns the current setting of option coolTemperature.
556 	/**
557 	 * If set to true, forces are scaled by coolValue()^(actual iteration) *
558 	 * forceScalingFactor(); otherwise forces are scaled by forceScalingFactor().
559 	 */
coolTemperature()560 	bool coolTemperature() const { return m_coolTemperature; }
561 
562 	//! Sets the option coolTemperature to \p b.
coolTemperature(bool b)563 	void coolTemperature(bool b) { m_coolTemperature = b; }
564 
565 	//! Returns the current setting of option coolValue.
566 	/**
567 	 * This option defines the value by which forces are decreased
568 	 * if coolTemperature is true.
569 	 */
coolValue()570 	double coolValue() const { return m_coolValue; }
571 
572 	//! Sets the option coolValue to \p x.
coolValue(double x)573 	void coolValue(double x) { m_coolValue = (((x >0 )&&(x<=1) )? x : 0.99);}
574 
575 
576 	//! Returns the current setting of option initialPlacementForces.
initialPlacementForces()577 	FMMMOptions::InitialPlacementForces initialPlacementForces() const {
578 		return m_initialPlacementForces;
579 	}
580 
581 	//! Sets the option initialPlacementForces to \p ipf.
initialPlacementForces(FMMMOptions::InitialPlacementForces ipf)582 	void initialPlacementForces(FMMMOptions::InitialPlacementForces ipf) {
583 		m_initialPlacementForces = ipf;
584 	}
585 
586 
587 	/** @}
588 	 *  @name Options for the postprocessing step
589 	 *  @{
590 	 */
591 
592 	//! Returns the current setting of option resizeDrawing.
593 	/**
594 	 * If set to true, the resulting drawing is resized so that the average edge
595 	 * length is the desired edge length times resizingScalar().
596 	 */
resizeDrawing()597 	bool resizeDrawing() const { return m_resizeDrawing; }
598 
599 	//! Sets the option resizeDrawing to \p b.
resizeDrawing(bool b)600 	void resizeDrawing(bool b) { m_resizeDrawing = b; }
601 
602 	//! Returns the current setting of option resizingScalar.
603 	/**
604 	 * This option defines a parameter to scale the drawing if
605 	 * resizeDrawing() is true.
606 	 */
resizingScalar()607 	double resizingScalar() const { return m_resizingScalar; }
608 
609 	//! Sets the option resizingScalar to \p s.
resizingScalar(double s)610 	void resizingScalar(double s) { m_resizingScalar = ((s > 0) ? s : 1);}
611 
612 	//! Returns the number of iterations for fine tuning.
fineTuningIterations()613 	int fineTuningIterations() const { return m_fineTuningIterations; }
614 
615 	//! Sets the number of iterations for fine tuning to \p n.
fineTuningIterations(int n)616 	void fineTuningIterations(int n) { m_fineTuningIterations =((n >= 0) ? n : 0);}
617 
618 	//! Returns the curent setting of option fineTuneScalar.
619 	/**
620 	 * This option defines a parameter for scaling the forces in the
621 	 * fine-tuning iterations.
622 	 */
fineTuneScalar()623 	double fineTuneScalar() const { return m_fineTuneScalar; }
624 
625 	//! Sets the option fineTuneScalar to \p s
fineTuneScalar(double s)626 	void fineTuneScalar(double s) { m_fineTuneScalar = ((s >= 0) ? s : 1);}
627 
628 	//! Returns the current setting of option adjustPostRepStrengthDynamically.
629 	/**
630 	 * If set to true, the strength of the repulsive force field is calculated
631 	 * dynamically by a formula depending on the number of nodes; otherwise the
632 	 * strength are scaled by PostSpringStrength and PostStrengthOfRepForces.
633 	 */
adjustPostRepStrengthDynamically()634 	bool adjustPostRepStrengthDynamically() const {
635 		return m_adjustPostRepStrengthDynamically;
636 	}
637 
638 	//! Sets the option adjustPostRepStrengthDynamically to \p b.
adjustPostRepStrengthDynamically(bool b)639 	void adjustPostRepStrengthDynamically(bool b) {
640 		m_adjustPostRepStrengthDynamically = b;
641 	}
642 
643 	//! Returns the strength of the springs in the postprocessing step.
postSpringStrength()644 	double postSpringStrength() const { return m_postSpringStrength; }
645 
646 	//! Sets the strength of the springs in the postprocessing step to \p x.
postSpringStrength(double x)647 	void postSpringStrength(double x) { m_postSpringStrength  = ((x > 0)? x : 1);}
648 
649 	//! Returns the strength of the repulsive forces in the postprocessing step.
postStrengthOfRepForces()650 	double postStrengthOfRepForces() const { return m_postStrengthOfRepForces; }
651 
652 	//! Sets the strength of the repulsive forces in the postprocessing step to \p x.
postStrengthOfRepForces(double x)653 	void postStrengthOfRepForces(double x) {
654 		m_postStrengthOfRepForces = ((x > 0)? x : 1);
655 	}
656 
657 
658 	/** @}
659 	 *  @name Options for repulsive force approximation methods
660 	 *  @{
661 	 */
662 
663 	//! Returns the current setting of option frGridQuotient.
664 	/**
665 	 * The number k of rows and columns of the grid is sqrt(|V|) / frGridQuotient().
666 	 * (Note that in [Fruchterman,Reingold] frGridQuotient is 2.)
667 	 */
frGridQuotient()668 	int  frGridQuotient() const {return m_frGridQuotient;}
669 
670 	//! Sets the option frGridQuotient to \p p.
frGridQuotient(int p)671 	void frGridQuotient(int p) { m_frGridQuotient = ((0<=p) ? p : 2);}
672 
673 	//! Returns the current setting of option nmTreeConstruction.
nmTreeConstruction()674 	FMMMOptions::ReducedTreeConstruction nmTreeConstruction() const { return m_NMTreeConstruction; }
675 
676 	//! Sets the option nmTreeConstruction to \p rtc.
nmTreeConstruction(FMMMOptions::ReducedTreeConstruction rtc)677 	void nmTreeConstruction(FMMMOptions::ReducedTreeConstruction rtc) { m_NMTreeConstruction = rtc; }
678 
679 	//! Returns the current setting of option nmSmallCell.
nmSmallCell()680 	FMMMOptions::SmallestCellFinding nmSmallCell() const { return m_NMSmallCell; }
681 
682 	//! Sets the option nmSmallCell to \p scf.
nmSmallCell(FMMMOptions::SmallestCellFinding scf)683 	void nmSmallCell(FMMMOptions::SmallestCellFinding scf) { m_NMSmallCell = scf; }
684 
685 	//! Returns the current setting of option nmParticlesInLeaves.
686 	/**
687 	 * Defines the maximal number of particles that are contained in
688 	 * a leaf of the reduced bucket quadtree.
689 	 */
nmParticlesInLeaves()690 	int nmParticlesInLeaves() const { return m_NMParticlesInLeaves; }
691 
692 	//! Sets the option nmParticlesInLeaves to \p n.
nmParticlesInLeaves(int n)693 	void nmParticlesInLeaves(int n) { m_NMParticlesInLeaves = ((n>= 1)? n : 1);}
694 
695 	//! Returns the precision \a p for the <i>p</i>-term multipole expansions.
nmPrecision()696 	int nmPrecision() const { return m_NMPrecision; }
697 
698 	//! Sets the precision for the multipole expansions to \p p.
nmPrecision(int p)699 	void nmPrecision(int p) { m_NMPrecision  = ((p >= 1 ) ? p : 1);}
700 
701 	//! @}
702 
703 private:
704 
705 	//high level options
706 	bool                  m_useHighLevelOptions; //!< The option for using high-level options.
707 	FMMMOptions::PageFormatType m_pageFormat; //!< The option for the page format.
708 	double                m_unitEdgeLength; //!< The unit edge length.
709 	bool                  m_newInitialPlacement; //!< The option for new initial placement.
710 	FMMMOptions::QualityVsSpeed m_qualityVersusSpeed; //!< The option for quality-vs-speed trade-off.
711 
712 	//low level options
713 	//general options
714 	int                   m_randSeed; //!< The random seed.
715 	FMMMOptions::EdgeLengthMeasurement m_edgeLengthMeasurement; //!< The option for edge length measurement.
716 	FMMMOptions::AllowedPositions m_allowedPositions; //!< The option for allowed positions.
717 	int                   m_maxIntPosExponent; //!< The option for the used	exponent.
718 
719 	//options for divide et impera step
720 	double                m_pageRatio; //!< The desired page ratio.
721 	int                   m_stepsForRotatingComponents; //!< The number of rotations.
722 	FMMMOptions::TipOver  m_tipOverCCs; //!< Option for tip-over of connected components.
723 	double                m_minDistCC; //!< The separation between connected components.
724 	FMMMOptions::PreSort  m_presortCCs; //!< The option for presorting connected components.
725 
726 	//options for multilevel step
727 	bool                  m_singleLevel; //!< Option for pure single level.
728 	int                   m_minGraphSize; //!< The option for minimal graph size.
729 	FMMMOptions::GalaxyChoice m_galaxyChoice; //!< The selection of galaxy nodes.
730 	int                   m_randomTries; //!< The number of random tries.
731 
732 	//! The option for how to change MaxIterations.
733 	//! If maxIterChange != micConstant, the iterations are decreased
734 	//! depending on the level, starting from
735 	//! ((maxIterFactor()-1) * fixedIterations())
736 	FMMMOptions::MaxIterChange m_maxIterChange;
737 
738 	int                   m_maxIterFactor; //!< The factor used for decreasing MaxIterations.
739 	FMMMOptions::InitialPlacementMult m_initialPlacementMult; //!< The option for creating initial placement.
740 
741 	//options for force calculation step
742 	FMMMOptions::ForceModel m_forceModel; //!< The used force model.
743 	double                m_springStrength; //!< The strengths of springs.
744 	double                m_repForcesStrength; //!< The strength of repulsive forces.
745 	FMMMOptions::RepulsiveForcesMethod m_repulsiveForcesCalculation; //!< Option for how to calculate repulsive forces.
746 	FMMMOptions::StopCriterion m_stopCriterion; //!< The stop criterion.
747 	double                m_threshold; //!< The threshold for the stop criterion.
748 	int                   m_fixedIterations; //!< The fixed number of iterations for the stop criterion.
749 	double                m_forceScalingFactor; //!< The scaling factor for the forces.
750 	bool                  m_coolTemperature; //!< The option for how to scale forces.
751 	double                m_coolValue; //!< The value by which forces are decreased.
752 	FMMMOptions::InitialPlacementForces m_initialPlacementForces; //!< The option for how the initial placement is done.
753 
754 	//options for postprocessing step
755 	bool                  m_resizeDrawing; //!< The option for resizing the drawing.
756 	double                m_resizingScalar; //!< Parameter for resizing the drawing.
757 	int                   m_fineTuningIterations; //!< The number of iterations for fine tuning.
758 	double                m_fineTuneScalar; //!< Parameter for scaling forces during fine tuning.
759 	bool                  m_adjustPostRepStrengthDynamically; //!< The option adjustPostRepStrengthDynamically.
760 	double                m_postSpringStrength; //!< The strength of springs during postprocessing.
761 	double                m_postStrengthOfRepForces; //!< The strength of repulsive forces during postprocessing.
762 
763 	//options for repulsive force approximation methods
764 	int                   m_frGridQuotient; //!< The grid quotient.
765 	FMMMOptions::ReducedTreeConstruction m_NMTreeConstruction; //!< The option for how to construct reduced bucket quadtree.
766 	FMMMOptions::SmallestCellFinding m_NMSmallCell; //!< The option for how to calculate smallest quadtratic cells.
767 	int                   m_NMParticlesInLeaves; //!< The maximal number of particles in a leaf.
768 	int                   m_NMPrecision; //!< The precision for multipole expansions.
769 
770 	//other variables
771 	double max_integer_position; //!< The maximum value for an integer position.
772 	double cool_factor; //!< Needed for scaling the forces if coolTemperature is true.
773 	double average_ideal_edgelength; //!< Measured from center to center.
774 	double boxlength; //!< Holds the length of the quadratic comput. box.
775 	int number_of_components; //!< The number of components of the graph.
776 	DPoint down_left_corner; //!< Holds down left corner of the comput. box.
777 	NodeArray<double> radius; //!< Holds the radius of the surrounding circle for each node.
778 	double time_total; //!< The runtime (=CPU-time) of the algorithm in seconds.
779 
780 	energybased::fmmm::FruchtermanReingold FR; //!< Class for repulsive force calculation (Fruchterman, Reingold).
781 	energybased::fmmm::NewMultipoleMethod NM; //!< Class for repulsive force calculation.
782 
783 	//! \name Most important functions
784 	//! @{
785 
786 	//! Calls the divide (decomposition into connected components) and impera (drawing and packing of the componenets) step.
787 	void call_DIVIDE_ET_IMPERA_step(
788 		Graph& G,
789 		NodeArray<NodeAttributes>& A,
790 		EdgeArray<EdgeAttributes>& E);
791 
792 	//! Calls the multilevel step for subGraph \p G.
793 	void call_MULTILEVEL_step_for_subGraph(
794 		Graph& G,
795 		NodeArray<NodeAttributes>& A,
796 		EdgeArray<EdgeAttributes>& E);
797 
798 	//! Returns true iff stopCriterion() is not met
799 	bool running(int iter, int max_mult_iter, double actforcevectorlength);
800 
801 	//! Calls the force calculation step for \p G, \p A, \p E.
802 	/**
803 	 * If act_level is 0 and resizeDrawing is true the drawing is resized.
804 	 * Furthermore, the maximum number of force calc. steps is calculated
805 	 * depending on MaxIterChange, act_level, and max_level.
806 	 */
807 	void call_FORCE_CALCULATION_step (
808 		Graph& G,
809 		NodeArray<NodeAttributes>& A,
810 		EdgeArray<EdgeAttributes>& E,
811 		int act_level,
812 		int max_level);
813 
814 	//! Calls the postprocessing step.
815 	void call_POSTPROCESSING_step(
816 		Graph& G,
817 		NodeArray<NodeAttributes>& A,
818 		EdgeArray<EdgeAttributes>& E,
819 		NodeArray<DPoint>& F,
820 		NodeArray<DPoint>& F_attr,
821 		NodeArray<DPoint>& F_rep,
822 		NodeArray<DPoint>& last_node_movement);
823 
824 	//! @}
825 	//! \name Functions for pre- and post-processing
826 	//! @{
827 
828 	//! All parameter options are set to the default values.
829 	void initialize_all_options();
830 
831 	//! Updates several low level parameter options due to the settings of the high level parameter options.
832 	void update_low_level_options_due_to_high_level_options_settings();
833 
834 	//! Imports for each node \a v of \p G its width, height and position (given from \p GA) in \p A.
835 	void import_NodeAttributes(
836 		const Graph& G,
837 		GraphAttributes& GA,
838 		NodeArray<NodeAttributes>& A);
839 
840 	//! Imports for each edge e of G its desired length given via edgeLength.
841 	void import_EdgeAttributes (
842 		const Graph& G,
843 		const EdgeArray<double>& edgeLength,
844 		EdgeArray <EdgeAttributes>& E);
845 
846 	//! Sets the individual ideal edge length for each edge \a e.
847 	void init_ind_ideal_edgelength(
848 		const Graph& G,
849 		NodeArray<NodeAttributes>&A,
850 		EdgeArray <EdgeAttributes>& E);
851 
852 	//! The radii of the surrounding circles of the bounding boxes are computed.
853 	void set_radii(const Graph& G,NodeArray<NodeAttributes>& A);
854 
855 	//! Exports for each node \a v in \p G_reduced the position of the original_node in \p GA.
856 	void export_NodeAttributes(
857 		Graph& G_reduced,
858 		NodeArray<NodeAttributes>& A_reduced,
859 		GraphAttributes& GA);
860 
861 	//! Creates a simple and loopfree copy of \p G and stores the corresponding node / edge attributes.
862 	/**
863 	 * The corresponding node / edge attributes are stored in \p A_reduced and
864 	 * \p E_reduced; the links to the copy_node and original node are stored in \p A,
865 	 * \p A_reduced, too.
866 	 */
867 	void make_simple_loopfree(
868 		const Graph& G,
869 		NodeArray<NodeAttributes>& A,
870 		EdgeArray<EdgeAttributes>E,
871 		Graph& G_reduced,
872 		NodeArray<NodeAttributes>& A_reduced,
873 		EdgeArray<EdgeAttributes>& E_reduced);
874 
875 	//! Deletes parallel edges of \p G_reduced.
876 	/**
877 	 * Saves for each set of parallel edges one representative edge in \p S and
878 	 * saves in \p new_edgelength the new edge length of this edge in \p G_reduced.
879 	 */
880 	void delete_parallel_edges(
881 		const Graph& G,
882 		EdgeArray<EdgeAttributes>& E,
883 		Graph& G_reduced,
884 		List<edge>& S,
885 		EdgeArray<double>& new_edgelength);
886 
887 	//! Sets for each edge \a e of \a G_reduced in \p S its edgelength to \p new_edgelength[\a e].
888 	/**
889 	 * Also stores this information in \p E_reduced.
890 	 */
891 	void update_edgelength(
892 		List<edge>& S,
893 		EdgeArray <double>& new_edgelength,
894 		EdgeArray<EdgeAttributes>& E_reduced);
895 
896 	//! Returns the value for the strength of the repulsive forces.
897 	/**
898 	 * Used in the postprocessing step; depending on \p n = G.numberOfNodes().
899 	 */
get_post_rep_force_strength(int n)900 	double get_post_rep_force_strength(int n) {
901 		return min(0.2,400.0/double(n));
902 	}
903 
904 	/**
905 	 * Adjust positions according to allowedPositions()
906 	 *
907 	 * \see FMMMOptions::AllowedPositions
908 	 */
909 	void adjust_positions(const Graph& G, NodeArray<NodeAttributes>& A);
910 
911 	//! Creates a simple drawing of \p GA in postscript format and saves it in file \p ps_file.
912 	void create_postscript_drawing(GraphAttributes& GA, char* ps_file);
913 
914 	//! @}
915 	//! \name Functions for divide et impera step
916 	//! @{
917 
918 	//! Constructs the list of connected components of G.
919 	/**
920 	 * Also constructs the corresponding lists with the node / edge attributes
921 	 * (containing a pointer to the original node in \p G for each node in a subgraph).
922 	 */
923 	void create_maximum_connected_subGraphs(
924 		Graph& G,
925 		NodeArray<NodeAttributes>&A,
926 		EdgeArray<EdgeAttributes>&E,
927 		Graph G_sub[],
928 		NodeArray<NodeAttributes> A_sub[],
929 		EdgeArray<EdgeAttributes> E_sub[],
930 		NodeArray<int>& component);
931 
932 	//! The drawings of the subgraphs are packed.
933 	/**
934 	 * This is done such that the subgraphs do not overlap and fit into a small
935 	 * box with the desired aspect ratio.
936 	 */
937 	void pack_subGraph_drawings(
938 		NodeArray<NodeAttributes>& A,
939 		Graph G_sub[],
940 		NodeArray<NodeAttributes> A_sub[]);
941 
942 	//! The bounding rectangles of all connected componenents of \a G are calculated and stored in \p R.
943 	void  calculate_bounding_rectangles_of_components(
944 		List<Rectangle>& R,
945 		Graph  G_sub[],
946 		NodeArray<NodeAttributes> A_sub[]);
947 
948 	//! The bounding rectangle of the componenet_index-th. component of G is returned.
949 	Rectangle calculate_bounding_rectangle(
950 		Graph& G,
951 		NodeArray<NodeAttributes>& A,
952 		int componenet_index);
953 
954 	/**
955 	 * If number_of_components > 1, the subgraphs \p G_sub are rotated and skipped to
956 	 * find bounding rectangles with minimum area. The information is saved in \p R and
957 	 * the node positions in \p A_sub are updated. If number_of_components == 1 a rotation
958 	 * with minimal aspect ratio is found instead.
959 	 */
960 	void rotate_components_and_calculate_bounding_rectangles(
961 		List<Rectangle>&R,
962 		Graph G_sub[],
963 		NodeArray<NodeAttributes> A_sub[]);
964 
965 	/**
966 	 * Returns the area (aspect ratio area) of a rectangle with width w and height h
967 	 * if comp_nr > 1 ( comp_nr == 1).
968 	 */
calculate_area(double width,double height,int comp_nr)969 	double calculate_area(double width, double height, int comp_nr) {
970 		double scaling = 1.0;
971 		if (comp_nr == 1) {  //calculate aspect ratio area of the rectangle
972 			OGDF_ASSERT( height != 0.0 );
973 			double ratio = width / height;
974 			if (ratio < pageRatio()) { //scale width
975 				OGDF_ASSERT( ratio != 0.0 );
976 				scaling = pageRatio() / ratio;
977 			} else { //scale height
978 				OGDF_ASSERT( pageRatio() != 0.0 );
979 				scaling = ratio / pageRatio();
980 			}
981 		}
982 		return width * height * scaling;
983 	}
984 
985 	/**
986 	 * The positions of the nodes in the subgraphs are calculated by using the
987 	 * information stored in R and are exported to A. (The coordinates of components
988 	 * which surrounding rectangles have been tipped over in the packing step are
989 	 * tipped over here,too)
990 	 */
991 	void export_node_positions(
992 		NodeArray<NodeAttributes>& A,
993 		List<Rectangle>& R,
994 		Graph G_sub[],
995 		NodeArray<NodeAttributes> A_sub[]);
996 
997 	//! Frees dynamically allocated memory for the connected component subgraphs.
delete_all_subGraphs(Graph G_sub[],NodeArray<NodeAttributes> A_sub[],EdgeArray<EdgeAttributes> E_sub[])998 	void delete_all_subGraphs(
999 		Graph G_sub[],
1000 		NodeArray<NodeAttributes> A_sub[],
1001 		EdgeArray<EdgeAttributes> E_sub[])
1002 	{
1003 		delete[] G_sub;
1004 		delete[] A_sub;
1005 		delete[] E_sub;
1006 	}
1007 
1008 	//! @}
1009 	//! \name Functions for multilevel step
1010 	//! @{
1011 
1012 	/**
1013 	 * Returns the maximum number of iterations for the force calc. step depending
1014 	 * on act_level, max_level, FixedIterations, MaxIterChange, MaxIterFactor,
1015 	 * and the number of nodes of the Graph in the actual mutilevel.
1016 	 */
1017 	int get_max_mult_iter(int act_level, int max_level, int node_nr);
1018 
1019 	//! @}
1020 	//! \name Functions for force calculation
1021 	//! @{
1022 
1023 	//! The forces are calculated here.
1024 	void calculate_forces(
1025 		Graph& G,
1026 		NodeArray<NodeAttributes>& A,
1027 		EdgeArray<EdgeAttributes>& E,NodeArray<DPoint>& F,
1028 		NodeArray<DPoint>& F_attr,
1029 		NodeArray<DPoint>& F_rep,
1030 		NodeArray<DPoint>& last_node_movement,
1031 		int iter,
1032 		int fine_tuning_step);
1033 
1034 	//! The length of the computational box in the first iteration is set (down left corner is at (0,0).
1035 	void init_boxlength_and_cornercoordinate(Graph& G,NodeArray<NodeAttributes>& A);
1036 
1037 	//! The initial placements of the nodes are created by using initialPlacementForces().
1038 	void create_initial_placement (Graph& G,NodeArray<NodeAttributes>& A);
1039 
1040 	//! Places nodes uniformly in a grid.
1041 	void create_initial_placement_uniform_grid(const Graph& G, NodeArray<NodeAttributes>& A);
1042 
1043 	//! Places nodes randomly.
1044 	void create_initial_placement_random(const Graph& G, NodeArray<NodeAttributes>& A);
1045 
1046 	//! Sets all entries of \p F to (0,0).
1047 	void  init_F (Graph& G, NodeArray<DPoint>& F);
1048 
1049 
1050 	//! Make initializations for the data structures that are used in the choosen class for rep. force calculation.
1051 	void make_initialisations_for_rep_calc_classes(
1052 		Graph& G/*,
1053 		NodeArray<NodeAttributes> &A,
1054 		NodeArray<DPoint>& F_rep*/);
1055 
1056 	//! Calculates repulsive forces for each node.
calculate_repulsive_forces(Graph & G,NodeArray<NodeAttributes> & A,NodeArray<DPoint> & F_rep)1057 	void calculate_repulsive_forces(
1058 		Graph &G,
1059 		NodeArray<NodeAttributes>& A,
1060 		NodeArray<DPoint>& F_rep)
1061 	{
1062 		switch (repulsiveForcesCalculation()) {
1063 		case FMMMOptions::RepulsiveForcesMethod::Exact:
1064 			FR.calculate_exact_repulsive_forces(G,A,F_rep);
1065 			break;
1066 		case FMMMOptions::RepulsiveForcesMethod::GridApproximation:
1067 			FR.calculate_approx_repulsive_forces(G,A,F_rep);
1068 			break;
1069 		case FMMMOptions::RepulsiveForcesMethod::NMM:
1070 			NM.calculate_repulsive_forces(G,A,F_rep);
1071 			break;
1072 		}
1073 	}
1074 
1075 
1076 	//! Deallocates dynamically allocated memory of the choosen rep. calculation class.
deallocate_memory_for_rep_calc_classes()1077 	void deallocate_memory_for_rep_calc_classes()
1078 	{
1079 		if(repulsiveForcesCalculation() == FMMMOptions::RepulsiveForcesMethod::NMM)
1080 			NM.deallocate_memory();
1081 	}
1082 
1083 	//! Calculates attractive forces for each node.
1084 	void calculate_attractive_forces(
1085 		Graph& G,
1086 		NodeArray<NodeAttributes> & A,
1087 		EdgeArray<EdgeAttributes>& E,
1088 		NodeArray<DPoint>& F_attr);
1089 
1090 	//! Returns the attractive force scalar.
1091 	double f_attr_scalar (double d,double ind_ideal_edge_length);
1092 
1093 	//! Add attractive and repulsive forces for each node.
1094 	void add_attr_rep_forces(
1095 		Graph& G,
1096 		NodeArray<DPoint>& F_attr,
1097 		NodeArray<DPoint>& F_rep,
1098 		NodeArray<DPoint>& F,
1099 		int iter,
1100 		int fine_tuning_step);
1101 
1102 	//! Move the nodes.
1103 	void move_nodes(Graph& G,NodeArray<NodeAttributes>& A,NodeArray<DPoint>& F);
1104 
1105 	//! Computes a new tight computational square-box.
1106 	/**
1107 	 * (Guaranteeing, that all midpoints are inside the square.)
1108 	 */
1109 	void update_boxlength_and_cornercoordinate(Graph& G,NodeArray<NodeAttributes>& A);
1110 
1111 	//! Describes the max. radius of a move in one time step, depending on the number of iterations.
max_radius(int iter)1112 	double max_radius(int iter) {
1113 		return (iter == 1) ? boxlength/1000 : boxlength/5;
1114 	}
1115 
1116 	//! The average_ideal_edgelength for all edges is computed.
1117 	void set_average_ideal_edgelength(Graph& G,EdgeArray<EdgeAttributes>& E);
1118 
1119 	/**
1120 	 * Calculates the average force on each node in the actual iteration, which is
1121 	 * needed if StopCriterion is scThreshold() or scFixedIterationsOrThreshold().
1122 	 */
1123 	double get_average_forcevector_length (Graph& G, NodeArray<DPoint>& F);
1124 
1125 	/**
1126 	 * Depending on the direction of \p last_node_movement[\a v], the length of the next
1127 	 * displacement of node \a v is restricted.
1128 	 */
1129 	void prevent_oscillations(
1130 		Graph& G,
1131 		NodeArray<DPoint>& F,
1132 		NodeArray<DPoint>&
1133 		last_node_movement,
1134 		int iter);
1135 
1136 	//! \p last_node_movement is initialized to \p F (used after first iteration).
1137 	void init_last_node_movement(
1138 		Graph& G,
1139 		NodeArray<DPoint>& F,
1140 		NodeArray<DPoint>& last_node_movement);
1141 
1142 	/**
1143 	 * If resizeDrawing is true, the drawing is adapted to the ideal average
1144 	 * edge length by shrinking respectively expanding the drawing area.
1145 	 */
1146 	void adapt_drawing_to_ideal_average_edgelength(
1147 		Graph& G,
1148 		NodeArray<NodeAttributes>& A,
1149 		EdgeArray<EdgeAttributes>& E);
1150 
1151 	/**
1152 	 * The force is restricted to have values within the comp. box (needed for
1153 	 * exception handling, if the force is too large for further calculations).
1154 	 */
restrict_force_to_comp_box(DPoint & force)1155 	void restrict_force_to_comp_box(DPoint& force) {
1156 		double x_min = down_left_corner.m_x;
1157 		double x_max = down_left_corner.m_x+boxlength;
1158 		double y_min = down_left_corner.m_y;
1159 		double y_max = down_left_corner.m_y+boxlength;
1160 		if (force.m_x < x_min )
1161 			force.m_x = x_min;
1162 		else if (force.m_x > x_max )
1163 			force.m_x = x_max;
1164 		if (force.m_y < y_min )
1165 			force.m_y = y_min;
1166 		else if (force.m_y > y_max )
1167 			force.m_y = y_max;
1168 	}
1169 
1170 	//! @}
1171 	//! \name Functions for analytic information
1172 	//! @{
1173 
1174 	//! Sets time_total to zero.
init_time()1175 	void init_time() { time_total = 0; }
1176 
1177 	//! @}
1178 };
1179 
1180 }
1181