Don't import ogdf namespace
[TortoiseGit.git] / ext / OGDF / ogdf / energybased / FMMMLayout.h
blob2b4bd39e2dc729a269368b2c0b8994ca38fadeb0
1 /*
2 * $Revision: 2583 $
4 * last checkin:
5 * $Author: gutwenger $
6 * $Date: 2012-07-12 01:02:21 +0200 (Do, 12. Jul 2012) $
7 ***************************************************************/
9 /** \file
10 * \brief Declaration of Fast Multipole Multilevel Method (FM^3).
12 * \author Stefan Hachul
14 * \par License:
15 * This file is part of the Open Graph Drawing Framework (OGDF).
17 * \par
18 * Copyright (C)<br>
19 * See README.txt in the root directory of the OGDF installation for details.
21 * \par
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * Version 2 or 3 as published by the Free Software Foundation;
25 * see the file LICENSE.txt included in the packaging of this file
26 * for details.
28 * \par
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
34 * \par
35 * You should have received a copy of the GNU General Public
36 * License along with this program; if not, write to the Free
37 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
38 * Boston, MA 02110-1301, USA.
40 * \see http://www.gnu.org/copyleft/gpl.html
41 ***************************************************************/
44 #ifdef _MSC_VER
45 #pragma once
46 #endif
48 #ifndef OGDF_FMMMLAYOUT_H
49 #define OGDF_FMMMLAYOUT_H
51 #include <ogdf/basic/Graph.h>
52 #include <ogdf/cluster/ClusterGraphAttributes.h>
53 #include <ogdf/module/LayoutModule.h>
54 #include <ogdf/basic/geometry.h>
55 #include <ogdf/internal/energybased/FruchtermanReingold.h>
56 #include <ogdf/internal/energybased/NMM.h>
59 namespace ogdf {
61 class Rectangle;
63 /**
64 * \brief The fast multipole multilevel layout algorithm.
66 * The class FMMMLayout implements a force-directed graph drawing
67 * method suited also for very large graphs. It is based on a
68 * combination of an efficient multilevel scheme and a strategy for
69 * approximating the repulsive forces in the system by rapidly
70 * evaluating potential fields.
72 * The implementation is based on the following publication:
74 * Stefan Hachul, Michael J�nger: <i>Drawing Large Graphs with a
75 * Potential-Field-Based Multilevel Algorithm</i>. 12th International
76 * Symposium on %Graph Drawing 1998, New York (GD '04), LNCS 3383,
77 * pp. 285-295, 2004.
79 * <H3>Optional parameters</H3>
80 * The following options are the most important. You can set
81 * useHighLevelOptions to true and just need to adjust a few parameters.
82 * However, you can also adjust all parameters that the implementation
83 * uses (see below), but this requires good knowledge of the algorithm.
85 * <table>
86 * <tr>
87 * <th><i>Option</i><th><i>Type</i><th><i>Default</i><th><i>Description</i>
88 * </tr><tr>
89 * <td><i>useHighLevelOptions</i><td>bool<td>false
90 * <td>Whether high-level options are used or not.
91 * </tr><tr>
92 * <td><i>pageFormat</i><td> #PageFormatType <td> #pfSquare
93 * <td>The desired aspect ratio of the layout.
94 * </tr><tr>
95 * <td><i>unitEdgeLength</i><td>double<td>100.0
96 * <td>The unit edge length.
97 * </tr><tr>
98 * <td><i>newInitialPlacement</i><td>bool<td>false
99 * <td>Specifies if initial placement of nodes is varied.
100 * </tr><tr>
101 * <td><i>qualityVersusSpeed</i><td> #QualityVsSpeed <td> #qvsBeautifulAndFast
102 * <td>Indicates if the algorithm is tuned either for best quality or best speed.
103 * </tr>
104 * </table>
106 * If you want to do more detailed fine-tuning, you can adjust all parameters
107 * used by the algorithm. Please refer to the paper cited above for better
108 * understanding of the algorithm.
110 * <table>
111 * <tr>
112 * <th colspan="4" align="center"><b>General</b>
113 * </tr><tr>
114 * <td><i>randSeed</i><td>int<td>100
115 * <td>The seed of the random number generator.
116 * </tr><tr>
117 * <td><i>edgeLengthMeasurement</i><td> #EdgeLengthMeasurement <td> #elmBoundingCircle
118 * <td>Indicates how the length of an edge is measured.
119 * </tr><tr>
120 * <td><i>allowedPositions</i><td> #AllowedPositions <td> #apInteger
121 * <td>Defines which positions for a node are allowed.
122 * </tr><tr>
123 * <td><i>maxIntPosExponent</i><td>int<td>40
124 * <td>Defines the exponent used if allowedPositions == apExponent.
125 * </tr><tr>
126 * <th colspan="4" align="center"><b>Divide et impera step</b>
127 * </tr><tr>
128 * <td><i>pageRatio</i><td>double<td>1.0
129 * <td>The desired page ratio.
130 * </tr><tr>
131 * <td><i>stepsForRotatingComponents</i><td>int<td>10
132 * <td>The number of rotations per connected component.
133 * </tr><tr>
134 * <td><i>tipOverCCs</i><td> #TipOver <td> #toNoGrowingRow
135 * <td>Specifies when it is allowed to tip over drawings.
136 * </tr><tr>
137 * <td><i>minDistCC</i><td>double<td>100
138 * <td>The minimal distance between connected components.
139 * </tr><tr>
140 * <td><i>presortCCs</i><td> #PreSort <td> #psDecreasingHeight
141 * <td>Defines if the connected components are sorted before
142 * the packing algorithm is applied.
143 * </tr><tr>
144 * <th colspan="4" align="center"><b>Multilevel step</b>
145 * </tr><tr>
146 * <td><i>minGraphSize</i><td>int<td>50
147 * <td>Determines the number of nodes of a graph for which
148 * no more collapsing of galaxies is performed.
149 * </tr><tr>
150 * <td><i>galaxyChoice</i><td> #GalaxyChoice <td> #gcNonUniformProbLowerMass
151 * <td>Defines how sun nodes of galaxies are selected.
152 * </tr><tr>
153 * <td><i>randomTries</i><td>int<td>20
154 * <td>Defines the number of tries to get a random node with
155 * minimal star mass.
156 * </tr><tr>
157 * <td><i>maxIterChange</i><td> #MaxIterChange <td> #micLinearlyDecreasing
158 * <td>Defines how MaxIterations is changed in subsequent multilevels.
159 * </tr><tr>
160 * <td><i>maxIterFactor</i><td>int<td>10
161 * <td>Defines the factor used for decreasing MaxIterations.
162 * </tr><tr>
163 * <td><i>initialPlacementMult</i><td> #InitialPlacementMult <td> #ipmAdvanced
164 * <td>Defines how the initial placement is generated.
165 * </tr><tr>
166 * <th colspan="4" align="center"><b>Force calculation step</b>
167 * </tr><tr>
168 * <td><i>forceModel</i><td> #ForceModel <td> #fmNew
169 * <td>The used force model.
170 * </tr><tr>
171 * <td><i>springStrength</i><td>double<td>1.0
172 * <td>The strength of the springs.
173 * </tr><tr>
174 * <td><i>repForcesStrength</i><td>double<td>1.0
175 * <td>The strength of the repulsive forces.
176 * </tr><tr>
177 * <td><i>repulsiveForcesCalculation</i><td> #RepulsiveForcesMethod <td> #rfcNMM
178 * <td>Defines how to calculate repulsive forces.
179 * </tr><tr>
180 * <td><i>stopCriterion</i><td> #StopCriterion <td> #scFixedIterationsOrThreshold
181 * <td>The stop criterion.
182 * </tr><tr>
183 * <td><i>threshold</i><td>double<td>0.01
184 * <td>The threshold for the stop criterion.
185 * </tr><tr>
186 * <td><i>fixedIterations</i><td>int<td>30
187 * <td>The fixed number of iterations for the stop criterion.
188 * </tr><tr>
189 * <td><i>forceScalingFactor</i><td>double<td>0.05
190 * <td>The scaling factor for the forces.
191 * </tr><tr>
192 * <td><i>coolTemperature</i><td>bool<td>false
193 * <td>Use coolValue for scaling forces.
194 * </tr><tr>
195 * <td><i>coolValue</i><td>double<td>0.99
196 * <td>The value by which forces are decreased.
197 * </tr><tr>
198 * <td><i>initialPlacementForces</i><td> #InitialPlacementForces <td> #ipfRandomRandIterNr
199 * <td>Defines how the initial placement is done.
200 * </tr><tr>
201 * <th colspan="4" align="center"><b>Force calculation step</b>
202 * </tr><tr>
203 * <td><i>resizeDrawing</i><td>bool<td>true
204 * <td>Specifies if the resulting drawing is resized.
205 * </tr><tr>
206 * <td><i>resizingScalar</i><td>double<td>1
207 * <td>Defines a parameter to scale the drawing if resizeDrawing is true.
208 * </tr><tr>
209 * <td><i>fineTuningIterations</i><td>int<td>20
210 * <td>The number of iterations for fine tuning.
211 * </tr><tr>
212 * <td><i>fineTuneScalar</i><td>double<td>0.2
213 * <td>Defines a parameter for scaling the forces in the fine-tuning iterations.
214 * </tr><tr>
215 * <td><i>adjustPostRepStrengthDynamically</i><td>bool<td>true
216 * <td>If set to true, the strength of the repulsive force field is calculated.
217 * </tr><tr>
218 * <td><i>postSpringStrength</i><td>double<td>2.0
219 * <td>The strength of the springs in the postprocessing step.
220 * </tr><tr>
221 * <td><i>postStrengthOfRepForces</i><td>double<td>0.01
222 * <td>The strength of the repulsive forces in the postprocessing step.
223 * </tr><tr>
224 * <th colspan="4" align="center"><b>Repulsive force approximation methods</b>
225 * </tr><tr>
226 * <td><i>frGridQuotient</i><td>int<td>2
227 * <td>The grid quotient.
228 * </tr><tr>
229 * <td><i>nmTreeConstruction</i><td> #ReducedTreeConstruction <td> #rtcSubtreeBySubtree
230 * <td>Defines how the reduced bucket quadtree is constructed.
231 * </tr><tr>
232 * <td><i>nmSmallCell</i><td> #SmallestCellFinding <td> #scfIteratively
233 * <td>Defines how the smallest quadratic cell that surrounds
234 * the particles of a node in the reduced bucket quadtree is calculated.
235 * </tr><tr>
236 * <td><i>nmParticlesInLeaves</i><td>int<td>25
237 * <td>The maximal number of particles that are contained in
238 * a leaf of the reduced bucket quadtree.
239 * </tr><tr>
240 * <td><i>nmPrecision</i><td>int<td>4
241 * <td>The precision \a p for the <i>p</i>-term multipole expansions.
242 * </tr>
243 * </table>
245 * <H3>Running time</H3>
246 * The running time of the algorithm is
247 * O(<i>n</i> log <i>n</i> + <i>m</i>) for graphs with \a n nodes
248 * and \a m edges. The required space is linear in the input size.
250 class OGDF_EXPORT FMMMLayout : public LayoutModule
252 public:
253 //! Possible page formats.
254 enum PageFormatType {
255 pfPortrait, //!< A4 portrait page.
256 pfLandscape, //!< A4 landscape page.
257 pfSquare //!< Square format.
260 //! Trade-off between run-time and quality.
261 enum QualityVsSpeed {
262 qvsGorgeousAndEfficient, //!< Best quality.
263 qvsBeautifulAndFast, //!< Medium quality and speed.
264 qvsNiceAndIncredibleSpeed //!< Best speed.
267 //! Specifies how the length of an edge is measured.
268 enum EdgeLengthMeasurement {
269 elmMidpoint, //!< Measure from center point of edge end points.
270 elmBoundingCircle //!< Measure from border of circle s surrounding edge end points.
273 //! Specifies which positions for a node are allowed.
274 enum AllowedPositions {
275 apAll,
276 apInteger,
277 apExponent
280 //! Specifies in which case it is allowed to tip over drawings of connected components.
281 enum TipOver {
282 toNone,
283 toNoGrowingRow,
284 toAlways
287 //! Specifies how connected components are sorted before the packing algorithm is applied.
288 enum PreSort {
289 psNone, //!< Do not presort.
290 psDecreasingHeight, //!< Presort by decreasing height of components.
291 psDecreasingWidth //!< Presort by decreasing width of components.
294 //! Specifies how sun nodes of galaxies are selected.
295 enum GalaxyChoice {
296 gcUniformProb,
297 gcNonUniformProbLowerMass,
298 gcNonUniformProbHigherMass
301 //! Specifies how MaxIterations is changed in subsequent multilevels.
302 enum MaxIterChange {
303 micConstant,
304 micLinearlyDecreasing,
305 micRapidlyDecreasing
308 //! Specifies how the initial placement is generated.
309 enum InitialPlacementMult {
310 ipmSimple,
311 ipmAdvanced
314 //! Specifies the force model.
315 enum ForceModel {
316 fmFruchtermanReingold, //!< The force-model by Fruchterman, Reingold.
317 fmEades, //!< The force-model by Eades.
318 fmNew //!< The new force-model.
321 //! Specifies how to calculate repulsive forces.
322 enum RepulsiveForcesMethod {
323 rfcExact, //!< Exact calculation.
324 rfcGridApproximation, //!< Grid approximation.
325 rfcNMM //!< Calculation as for new multipole method.
328 //! Specifies the stop criterion.
329 enum StopCriterion {
330 scFixedIterations, //!< Stop if fixedIterations() is reached.
331 scThreshold, //!< Stop if threshold() is reached.
332 scFixedIterationsOrThreshold //!< Stop if fixedIterations() or threshold() is reached.
335 //! Specifies how the initial placement is done.
336 enum InitialPlacementForces {
337 ipfUniformGrid, //!< Uniform placement on a grid.
338 ipfRandomTime, //!< Random placement (based on current time).
339 ipfRandomRandIterNr, //!< Random placement (based on randIterNr()).
340 ipfKeepPositions //!< No change in placement.
343 //! Specifies how the reduced bucket quadtree is constructed.
344 enum ReducedTreeConstruction {
345 rtcPathByPath, //!< Path-by-path construction.
346 rtcSubtreeBySubtree //!< Subtree-by-subtree construction.
349 //! Specifies how to calculate the smallest quadratic cell surrounding particles of a node in the reduced bucket quadtree.
350 enum SmallestCellFinding {
351 scfIteratively, //!< Iteratively (in constant time).
352 scfAluru //!< According to formula by Aluru et al. (in constant time).
356 //! Creates an instance of the layout algorithm.
357 FMMMLayout();
359 // destructor
360 virtual ~FMMMLayout() { }
364 * @name The algorithm call
365 * @{
368 //! Calls the algorithm for graph \a GA and returns the layout information in \a AG.
369 void call(GraphAttributes &GA);
371 //! Calls the algorithm for clustered graph \a GA and returns the layout information in \a AG.
372 //! Models cluster by simple edge length adaption based on least common ancestor
373 //! cluster of end vertices.
374 void call(ClusterGraphAttributes &GA);
376 //! Extended algorithm call: Allows to pass desired lengths of the edges.
378 * @param GA represents the input graph and is assigned the computed layout.
379 * @param edgeLength is an edge array of the graph associated with \a GA
380 * of positive edge length.
382 void call(
383 GraphAttributes &GA, //graph and layout
384 const EdgeArray<double> &edgeLength); //factor for desired edge lengths
386 //! Extended algorithm call: Calls the algorithm for graph \a AG.
388 * Returns layout information in \a AG and a simple drawing is saved in file \a ps_file
389 * in postscript format (Nodes are drawn as uniformly sized circles).
391 void call(GraphAttributes &AG, char* ps_file);
393 //! Extend algorithm call: Allows to pass desired lengths of the edges.
395 * The EdgeArray \a edgeLength must be valid for AG.constGraph() and its values must
396 * be positive.
397 * A simple drawing is saved in file ps_file in postscript format (Nodes are drawn
398 * as uniformly sized circles).
400 void call(
401 GraphAttributes &AG, //graph and layout
402 const EdgeArray<double> &edgeLength, //factor for desired edge lengths
403 char* ps_file);
405 /** @}
406 * @name Further information.
407 * @{
410 //! Returns the runtime (=CPU-time) of the layout algorithm in seconds.
411 double getCpuTime() {
412 return time_total;
416 /** @}
417 * @name High-level options
418 * Allow to specify the most relevant parameters.
419 * @{
422 //! Returns the current setting of option useHighLevelOptions.
424 * If set to true, the high-level options are used to set all low-level options.
425 * Usually, it is sufficient just to set high-level options; if you want to
426 * be more specific, set this parameter to false and set the low level options.
428 bool useHighLevelOptions() const { return m_useHighLevelOptions; }
430 //! Sets the option useHighLevelOptions to \a uho.
431 void useHighLevelOptions(bool uho) { m_useHighLevelOptions = uho; }
433 //! Sets single level option, no multilevel hierarchy is created if b == true
434 void setSingleLevel(bool b) {m_singleLevel = b;}
436 //! Returns the current setting of option pageFormat.
438 * This option defines the desired aspect ratio of the drawing area.
439 * - \a pfPortrait: A4 page in portrait orientation
440 * - \a pfLandscape: A4 page in landscape orientation
441 * - \a pfSquare: square page format
443 PageFormatType pageFormat() const { return m_pageFormat; }
445 //! Sets the option pageRatio to \a t.
446 void pageFormat(PageFormatType t) { m_pageFormat = t; }
448 //! Returns the current setting of option unitEdgeLength.
449 double unitEdgeLength() const { return m_unitEdgeLength; }
451 //! Sets the option unitEdgeLength to \a x.
452 void unitEdgeLength(double x) {m_unitEdgeLength = (( x > 0.0) ? x : 1);}
454 //! Returns the current setting of option newInitialPlacement.
456 * This option defines if the initial placement of the nodes at the
457 * coarsest multilevel is varied for each distinct call of FMMMLayout
458 * or keeps always the same.
460 bool newInitialPlacement() const { return m_newInitialPlacement; }
462 //! Sets the option newInitialPlacement to \a nip.
463 void newInitialPlacement(bool nip) { m_newInitialPlacement = nip; }
465 //! Returns the current setting of option qualityVersusSpeed.
467 * Indicates if the algorithm is tuned either for best quality or best speed.
468 * - \a qvsGorgeousAndEfficient: gorgeous quality and efficient speed
469 * - \a qvsBeautifulAndFast: beautiful quality and fast speed
470 * - \a qvsNiceAndIncredibleSpeed: nice quality and incredible speed
472 QualityVsSpeed qualityVersusSpeed() const { return m_qualityVersusSpeed; }
474 //! Sets the option qualityVersusSpeed to \a qvs.
475 void qualityVersusSpeed(QualityVsSpeed qvs) {m_qualityVersusSpeed = qvs; }
478 /** @}
479 * @name General low-level options
480 * The low-level options in this and the following sections are meant for
481 * experts or interested people only.
482 * @{
485 //! Sets the seed of the random number generator.
486 void randSeed(int p) { m_randSeed = ((0<=p) ? p : 1);}
488 //! Returns the seed of the random number generator.
489 int randSeed() const {return m_randSeed;}
491 //! Returns the current setting of option edgeLengthMeasurement.
493 * This option indicates how the length of an edge is measured.
494 * Possible values:
495 * - \a elmMidpoint: from center to center
496 * - \a elmBoundingCircle: the distance between the two tight circles bounding the
497 * graphics of two adjacent nodes
499 EdgeLengthMeasurement edgeLengthMeasurement() const {
500 return m_edgeLengthMeasurement;
503 //! Sets the option edgeLengthMeasurement to \a elm.
504 void edgeLengthMeasurement(EdgeLengthMeasurement elm) { m_edgeLengthMeasurement = elm; }
506 //! Returns the current setting of option allowedPositions.
508 * This option defines which positions for a node are allowed.
509 * Possibly values:
510 * - \a apAll: every position is allowed
511 * - \a apInteger: only integer positions in the range depending on the number of
512 * nodes
513 * - \a apExponent: only integer positions in the range of -2^MaxIntPosExponent to
514 * 2^MaxIntPosExponent
516 AllowedPositions allowedPositions() const { return m_allowedPositions; }
518 //! Sets the option allowedPositions to \a ap.
519 void allowedPositions(AllowedPositions ap) { m_allowedPositions = ap; }
521 //! Returns the current setting of option maxIntPosExponent.
523 * This option defines the exponent used if allowedPositions() == \a apExponent.
525 int maxIntPosExponent() const { return m_maxIntPosExponent; }
527 //! Sets the option maxIntPosExponent to \a e.
528 void maxIntPosExponent(int e) {
529 m_maxIntPosExponent = (((e >= 31)&&(e<=51))? e : 31);
533 /** @}
534 * @name Options for the divide et impera step
535 * @{
538 //! Returns the current setting of option pageRatio.
540 * This option defines the desired aspect ratio of the rectangular drawing area.
542 double pageRatio() const { return m_pageRatio; }
544 //! Sets the option pageRatio to \a r.
545 void pageRatio(double r) {m_pageRatio = (( r > 0) ? r : 1);}
547 //! Returns the current setting of option stepsForRotatingComponents.
549 * This options determines the number of times each connected component is rotated with
550 * angles between 0 and 90 degree to obtain a bounding rectangle with small area.
552 int stepsForRotatingComponents() const { return m_stepsForRotatingComponents; }
554 //! Sets the option stepsForRotatingComponents to \a n.
555 void stepsForRotatingComponents(int n) {
556 m_stepsForRotatingComponents = ((0<=n) ? n : 0);
559 //! Returns the current setting of option tipOverCCs.
561 * Defines in which case it is allowed to tip over drawings of connected components.
562 * Possible values:
563 * - \a toNone: not allowed at all
564 * - \a toNoGrowingRow: only if the height of the packing row does not grow
565 * - \a toAlways: always allowed
567 TipOver tipOverCCs() const { return m_tipOverCCs; }
569 //! Sets the option tipOverCCs to \a to.
570 void tipOverCCs(TipOver to) { m_tipOverCCs = to; }
572 //! Returns the minimal distance between connected components.
573 double minDistCC() const { return m_minDistCC; }
575 //! Sets the minimal distance between connected components to \a x.
576 void minDistCC(double x) { m_minDistCC = (( x > 0) ? x : 1);}
578 //! Returns the current setting of option presortCCs.
580 * This option defines if the connected components are sorted before
581 * the packing algorithm is applied.
582 * Possible values:
583 * - \a psNone: no sorting
584 * - \a psDecreasingHeight: sorted by decreasing height
585 * - \a psDecreasingWidth: sorted by decreasing width
587 PreSort presortCCs() const { return m_presortCCs; }
589 //! Sets the option presortCCs to \a ps.
590 void presortCCs(PreSort ps) { m_presortCCs = ps; }
593 /** @}
594 * @name Options for the multilevel step
595 * @{
598 //! Returns the current setting of option minGraphSize.
600 * This option determines the number of nodes of a graph in the
601 * multilevel representation for which no more collapsing of galaxies
602 * is performed (i.e. the graph at the highest level).
604 int minGraphSize() const { return m_minGraphSize; }
606 //! Sets the option minGraphSize to \a n.
607 void minGraphSize(int n) { m_minGraphSize = ((n >= 2)? n : 2);}
609 //! Returns the current setting of option galaxyChoice.
611 * This option defines how sun nodes of galaxies are selected.
612 * Possible values:
613 * - \a gcUniformProb: selecting by uniform random probability
614 * - \a gcNonUniformProbLowerMass: selecting by non-uniform probability depending on
615 * the star masses (prefering nodes with lower star mass)
616 * - \a gcNonUniformProbHigherMass: as above but prefering nodes with higher star mass
618 GalaxyChoice galaxyChoice() const { return m_galaxyChoice; }
620 //! Sets the option galaxyChoice to \a gc.
621 void galaxyChoice(GalaxyChoice gc) { m_galaxyChoice = gc; }
623 //! Returns the current setting of option randomTries.
625 * This option defines the number of tries to get a random node with
626 * minimal star mass (used in case of galaxyChoice() == gcNonUniformProbLowerMass
627 * and galaxyChoice() == gcNonUniformProbHigherMass).
629 int randomTries() const { return m_randomTries; }
631 //! Sets the option randomTries to \a n.
632 void randomTries(int n) {m_randomTries = ((n>=1)? n: 1);}
634 //! Returns the current setting of option maxIterChange.
636 * This option defines how MaxIterations is changed in subsequent multilevels.
637 * Possible values:
638 * - \a micConstant: kept constant at the force calculation step at every level
639 * - \a micLinearlyDecreasing: linearly decreasing from MaxIterFactor*FixedIterations
640 * to FixedIterations
641 * - \a micRapidlyDecreasing: rapdily decreasing from MaxIterFactor*FixedIterations
642 * to FixedIterations
644 MaxIterChange maxIterChange() const { return m_maxIterChange; }
646 //! Sets the option maxIterChange to \a mic.
647 void maxIterChange(MaxIterChange mic) { m_maxIterChange = mic; }
649 //! Returns the current setting of option maxIterFactor.
651 * This option defines the factor used for decrasing MaxIterations
652 * (in case of maxIterChange() == micLinearlyDecreasing or maxIterChange()
653 * == micRapidlyDecreasing).
655 int maxIterFactor() const { return m_maxIterFactor; }
657 //! Sets the option maxIterFactor to \a f.
658 void maxIterFactor(int f) { m_maxIterFactor = ((f>=1) ? f : 1 ); }
660 //! Returns the current setting of option initialPlacementMult.
662 * This option defines how the initial placement is generated.
663 * Possible values:
664 * - \a ipmSimple: only using information about placement of nodes on higher levels
665 * - \a ipmAdvanced: using additional information about the placement of all inter
666 * - \a solar system nodes
668 InitialPlacementMult initialPlacementMult() const {
669 return m_initialPlacementMult;
672 //! Sets the option initialPlacementMult to \a ipm.
673 void initialPlacementMult(InitialPlacementMult ipm) {
674 m_initialPlacementMult = ipm;
678 /** @}
679 * @name Options for the force calculation step
680 * @{
683 //! Returns the used force model.
685 * Possibly values:
686 * - \a fmFruchtermanReingold: model of Fruchterman and Reingold
687 * - \a fmEades: model of Eades
688 * - \a fmNew: new model
690 ForceModel forceModel() const { return m_forceModel; }
692 //! Sets the used force model to \a fm.
693 void forceModel(ForceModel fm) { m_forceModel = fm; }
695 //! Returns the strength of the springs.
696 double springStrength() const { return m_springStrength; }
698 //! Sets the strength of the springs to \a x.
699 void springStrength(double x) { m_springStrength = ((x > 0)? x : 1);}
701 //! Returns the strength of the repulsive forces.
702 double repForcesStrength() const { return m_repForcesStrength; }
704 //! Sets the strength of the repulsive forces to \a x.
705 void repForcesStrength(double x) { m_repForcesStrength =((x > 0)? x : 1);}
707 //! Returns the current setting of option repulsiveForcesCalculation.
709 * This option defines how to calculate repulsive forces.
710 * Possible values:
711 * - \a rfcExact: exact calculation (slow)
712 * - \a rfcGridApproximation: grid approxiamtion (inaccurate)
713 * - \a rfcNMM: like in NMM (= New Multipole Method; fast and accurate)
715 RepulsiveForcesMethod repulsiveForcesCalculation() const {
716 return m_repulsiveForcesCalculation;
719 //! Sets the option repulsiveForcesCalculation to \a rfc.
720 void repulsiveForcesCalculation(RepulsiveForcesMethod rfc) {
721 m_repulsiveForcesCalculation = rfc;
724 //! Returns the stop criterion.
726 * Possible values:
727 * - \a rscFixedIterations: stop if fixedIterations() is reached
728 * - \a rscThreshold: stop if threshold() is reached
729 * - \a rscFixedIterationsOrThreshold: stop if fixedIterations() or threshold()
730 * is reached
732 StopCriterion stopCriterion() const { return m_stopCriterion; }
734 //! Sets the stop criterion to \a rsc.
735 void stopCriterion(StopCriterion rsc) { m_stopCriterion = rsc; }
737 //! Returns the threshold for the stop criterion.
739 * (If the average absolute value of all forces in
740 * an iteration is less then threshold() then stop.)
742 double threshold() const { return m_threshold; }
744 //! Sets the threshold for the stop criterion to \a x.
745 void threshold(double x) {m_threshold = ((x > 0) ? x : 0.1);}
747 //! Returns the fixed number of iterations for the stop criterion.
748 int fixedIterations() const { return m_fixedIterations; }
750 //! Sets the fixed number of iterations for the stop criterion to \a n.
751 void fixedIterations(int n) { m_fixedIterations = ((n >= 1) ? n : 1);}
753 //! Returns the scaling factor for the forces.
754 double forceScalingFactor() const { return m_forceScalingFactor; }
756 //! Sets the scaling factor for the forces to \ f.
757 void forceScalingFactor(double f) { m_forceScalingFactor = ((f > 0) ? f : 1);}
759 //! Returns the current setting of option coolTemperature.
761 * If set to true, forces are scaled by coolValue()^(actual iteration) *
762 * forceScalingFactor(); otherwise forces are scaled by forceScalingFactor().
764 bool coolTemperature() const { return m_coolTemperature; }
766 //! Sets the option coolTemperature to \a b.
767 void coolTemperature(bool b) { m_coolTemperature = b; }
769 //! Returns the current setting of option coolValue.
771 * This option defines the value by which forces are decreased
772 * if coolTemperature is true.
774 double coolValue() const { return m_coolValue; }
776 //! Sets the option coolValue to \a x.
777 void coolValue(double x) { m_coolValue = (((x >0 )&&(x<=1) )? x : 0.99);}
780 //! Returns the current setting of option initialPlacementForces.
782 * This option defines how the initial placement is done.
783 * Possible values:
784 * - \a ipfUniformGrid: uniform on a grid
785 * - \a ipfRandomTime: random based on actual time
786 * - \a ipfRandomRandIterNr: random based on randIterNr()
787 * - \a ipfKeepPositions: no change in placement
789 InitialPlacementForces initialPlacementForces() const {
790 return m_initialPlacementForces;
793 //! Sets the option initialPlacementForces to \a ipf.
794 void initialPlacementForces(InitialPlacementForces ipf) {
795 m_initialPlacementForces = ipf;
799 /** @}
800 * @name Options for the postprocessing step
801 * @{
804 //! Returns the current setting of option resizeDrawing.
806 * If set to true, the resulting drawing is resized so that the average edge
807 * length is the desired edge length times resizingScalar().
809 bool resizeDrawing() const { return m_resizeDrawing; }
811 //! Sets the option resizeDrawing to \a b.
812 void resizeDrawing(bool b) { m_resizeDrawing = b; }
814 //! Returns the current setting of option resizingScalar.
816 * This option defines a parameter to scale the drawing if
817 * resizeDrawing() is true.
819 double resizingScalar() const { return m_resizingScalar; }
821 //! Sets the option resizingScalar to \a s.
822 void resizingScalar(double s) { m_resizingScalar = ((s > 0) ? s : 1);}
824 //! Returns the number of iterations for fine tuning.
825 int fineTuningIterations() const { return m_fineTuningIterations; }
827 //! Sets the number of iterations for fine tuning to \a n.
828 void fineTuningIterations(int n) { m_fineTuningIterations =((n >= 0) ? n : 0);}
830 //! Returns the curent setting of option fineTuneScalar.
832 * This option defines a parameter for scaling the forces in the
833 * fine-tuning iterations.
835 double fineTuneScalar() const { return m_fineTuneScalar; }
837 //! Sets the option fineTuneScalar to \a s
838 void fineTuneScalar(double s) { m_fineTuneScalar = ((s >= 0) ? s : 1);}
840 //! Returns the current setting of option adjustPostRepStrengthDynamically.
842 * If set to true, the strength of the repulsive force field is calculated
843 * dynamically by a formula depending on the number of nodes; otherwise the
844 * strength are scaled by PostSpringStrength and PostStrengthOfRepForces.
846 bool adjustPostRepStrengthDynamically() const {
847 return m_adjustPostRepStrengthDynamically;
850 //! Sets the option adjustPostRepStrengthDynamically to \a b.
851 void adjustPostRepStrengthDynamically(bool b) {
852 m_adjustPostRepStrengthDynamically = b;
855 //! Returns the strength of the springs in the postprocessing step.
856 double postSpringStrength() const { return m_postSpringStrength; }
858 //! Sets the strength of the springs in the postprocessing step to \a x.
859 void postSpringStrength(double x) { m_postSpringStrength = ((x > 0)? x : 1);}
861 //! Returns the strength of the repulsive forces in the postprocessing step.
862 double postStrengthOfRepForces() const { return m_postStrengthOfRepForces; }
864 //! Sets the strength of the repulsive forces in the postprocessing step to \a x.
865 void postStrengthOfRepForces(double x) {
866 m_postStrengthOfRepForces = ((x > 0)? x : 1);
870 /** @}
871 * @name Options for repulsive force approximation methods
872 * @{
875 //! Returns the current setting of option frGridQuotient.
877 * The number k of rows and columns of the grid is sqrt(|V|) / frGridQuotient().
878 * (Note that in [Fruchterman,Reingold] frGridQuotient is 2.)
880 int frGridQuotient() const {return m_frGridQuotient;}
882 //! Sets the option frGridQuotient to \a p.
883 void frGridQuotient(int p) { m_frGridQuotient = ((0<=p) ? p : 2);}
885 //! Returns the current setting of option nmTreeConstruction.
887 * This option defines how the reduced bucket quadtree is constructed.
888 * Possible values:
889 * - \a rtcPathByPath: path by path construction
890 * - \a rtcSubtreeBySubtree: subtree by subtree construction
892 ReducedTreeConstruction nmTreeConstruction() const { return m_NMTreeConstruction; }
894 //! Sets the option nmTreeConstruction to \a rtc.
895 void nmTreeConstruction(ReducedTreeConstruction rtc) { m_NMTreeConstruction = rtc; }
897 //! Returns the current setting of option nmSmallCell.
899 * This option defines how the smallest quadratic cell that surrounds
900 * the particles of a node in the reduced bucket quadtree is calculated.
901 * Possible values:
902 * - \a scfIteratively: iteratively (in constant time)
903 * - \a scfAluru: by the formula by Aluru et al. (in constant time)
905 SmallestCellFinding nmSmallCell() const { return m_NMSmallCell; }
907 //! Sets the option nmSmallCell to \a scf.
908 void nmSmallCell(SmallestCellFinding scf) { m_NMSmallCell = scf; }
910 //! Returns the current setting of option nmParticlesInLeaves.
912 * Defines the maximal number of particles that are contained in
913 * a leaf of the reduced bucket quadtree.
915 int nmParticlesInLeaves() const { return m_NMParticlesInLeaves; }
917 //! Sets the option nmParticlesInLeaves to \a n.
918 void nmParticlesInLeaves(int n) { m_NMParticlesInLeaves = ((n>= 1)? n : 1);}
920 //! Returns the precision \a p for the <i>p</i>-term multipole expansions.
921 int nmPrecision() const { return m_NMPrecision; }
923 //! Sets the precision for the multipole expansions to \ p.
924 void nmPrecision(int p) { m_NMPrecision = ((p >= 1 ) ? p : 1);}
926 //! @}
928 private:
930 //high level options
931 bool m_useHighLevelOptions; //!< The option for using high-level options.
932 PageFormatType m_pageFormat; //!< The option for the page format.
933 double m_unitEdgeLength; //!< The unit edge length.
934 bool m_newInitialPlacement; //!< The option for new initial placement.
935 QualityVsSpeed m_qualityVersusSpeed; //!< The option for quality-vs-speed trade-off.
937 //low level options
938 //general options
939 int m_randSeed; //!< The random seed.
940 EdgeLengthMeasurement m_edgeLengthMeasurement; //!< The option for edge length measurement.
941 AllowedPositions m_allowedPositions; //!< The option for allowed positions.
942 int m_maxIntPosExponent; //!< The option for the used exponent.
944 //options for divide et impera step
945 double m_pageRatio; //!< The desired page ratio.
946 int m_stepsForRotatingComponents; //!< The number of rotations.
947 TipOver m_tipOverCCs; //!< Option for tip-over of connected components.
948 double m_minDistCC; //!< The separation between connected components.
949 PreSort m_presortCCs; //!< The option for presorting connected components.
951 //options for multilevel step
952 bool m_singleLevel; //!< Option for pure single level.
953 int m_minGraphSize; //!< The option for minimal graph size.
954 GalaxyChoice m_galaxyChoice; //!< The selection of galaxy nodes.
955 int m_randomTries; //!< The number of random tries.
956 MaxIterChange m_maxIterChange; //!< The option for how to change MaxIterations.
957 //!< If maxIterChange != micConstant, the iterations are decreased
958 //!< depending on the level, starting from
959 //!< ((maxIterFactor()-1) * fixedIterations())
960 int m_maxIterFactor; //!< The factor used for decreasing MaxIterations.
961 InitialPlacementMult m_initialPlacementMult; //!< The option for creating initial placement.
963 //options for force calculation step
964 ForceModel m_forceModel; //!< The used force model.
965 double m_springStrength; //!< The strengths of springs.
966 double m_repForcesStrength; //!< The strength of repulsive forces.
967 RepulsiveForcesMethod m_repulsiveForcesCalculation; //!< Option for how to calculate repulsive forces.
968 StopCriterion m_stopCriterion; //!< The stop criterion.
969 double m_threshold; //!< The threshold for the stop criterion.
970 int m_fixedIterations; //!< The fixed number of iterations for the stop criterion.
971 double m_forceScalingFactor; //!< The scaling factor for the forces.
972 bool m_coolTemperature; //!< The option for how to scale forces.
973 double m_coolValue; //!< The value by which forces are decreased.
974 InitialPlacementForces m_initialPlacementForces; //!< The option for how the initial placement is done.
976 //options for postprocessing step
977 bool m_resizeDrawing; //!< The option for resizing the drawing.
978 double m_resizingScalar; //!< Parameter for resizing the drawing.
979 int m_fineTuningIterations; //!< The number of iterations for fine tuning.
980 double m_fineTuneScalar; //!< Parameter for scaling forces during fine tuning.
981 bool m_adjustPostRepStrengthDynamically; //!< The option adjustPostRepStrengthDynamically.
982 double m_postSpringStrength; //!< The strength of springs during postprocessing.
983 double m_postStrengthOfRepForces; //!< The strength of repulsive forces during postprocessing.
985 //options for repulsive force approximation methods
986 int m_frGridQuotient; //!< The grid quotient.
987 ReducedTreeConstruction m_NMTreeConstruction; //!< The option for how to construct reduced bucket quadtree.
988 SmallestCellFinding m_NMSmallCell; //!< The option for how to calculate smallest quadtratic cells.
989 int m_NMParticlesInLeaves; //!< The maximal number of particles in a leaf.
990 int m_NMPrecision; //!< The precision for multipole expansions.
992 //other variables
993 double max_integer_position; //!< The maximum value for an integer position.
994 double cool_factor; //!< Needed for scaling the forces if coolTemperature is true.
995 double average_ideal_edgelength; //!< Measured from center to center.
996 double boxlength; //!< Holds the length of the quadratic comput. box.
997 int number_of_components; //!< The number of components of the graph.
998 DPoint down_left_corner; //!< Holds down left corner of the comput. box.
999 NodeArray<double> radius; //!< Holds the radius of the surrounding circle for each node.
1000 double time_total; //!< The runtime (=CPU-time) of the algorithm in seconds.
1002 FruchtermanReingold FR; //!< Class for repulsive force calculation (Fruchterman, Reingold).
1003 NMM NM; //!< Class for repulsive force calculation.
1006 //------------------- most important functions ----------------------------
1008 //! Calls the divide (decomposition into connected components) and impera (drawing and packing of the componenets) step.
1009 void call_DIVIDE_ET_IMPERA_step(
1010 Graph& G,
1011 NodeArray<NodeAttributes>& A,
1012 EdgeArray<EdgeAttributes>& E);
1014 //! Calls the multilevel step for subGraph \a G.
1015 void call_MULTILEVEL_step_for_subGraph(
1016 Graph& G,
1017 NodeArray<NodeAttributes>& A,
1018 EdgeArray<EdgeAttributes>& E,
1019 int comp_index);
1021 //! Calls the force calculation step for \a G, \a A, \a E.
1023 * If act_level is 0 and resizeDrawing is true the drawing is resized.
1024 * Furthermore, the maximum number of force calc. steps is calculated
1025 * depending on MaxIterChange, act_level, and max_level.
1027 void call_FORCE_CALCULATION_step (
1028 Graph& G,
1029 NodeArray<NodeAttributes>& A,
1030 EdgeArray<EdgeAttributes>& E,
1031 int act_level,
1032 int max_level);
1034 //! Calls the postprocessing step.
1035 void call_POSTPROCESSING_step(
1036 Graph& G,
1037 NodeArray<NodeAttributes>& A,
1038 EdgeArray<EdgeAttributes>& E,
1039 NodeArray<DPoint>& F,
1040 NodeArray<DPoint>& F_attr,
1041 NodeArray<DPoint>& F_rep,
1042 NodeArray<DPoint>& last_node_movement);
1045 //---------------- functions for pre/pos-processing -----------------------------
1047 //! All parameter options are set to the default values.
1048 void initialize_all_options();
1050 //! Updates several low level parameter options due to the settings of the high level parameter options.
1051 void update_low_level_options_due_to_high_level_options_settings();
1053 //! Imports for each node \a v of \a G its width, height and position(given from \a GA) in \a A.
1054 void import_NodeAttributes(
1055 const Graph& G,
1056 GraphAttributes& GA,
1057 NodeArray<NodeAttributes>& A);
1059 //! Imports for each edge e of G its desired length given via edgeLength.
1060 void import_EdgeAttributes (
1061 const Graph& G,
1062 const EdgeArray<double>& edgeLength,
1063 EdgeArray <EdgeAttributes>& E);
1065 //! Sets the individual ideal edge length for each edge \a e.
1066 void init_ind_ideal_edgelength(
1067 const Graph& G,
1068 NodeArray<NodeAttributes>&A,
1069 EdgeArray <EdgeAttributes>& E);
1071 //! The radii of the surrounding circles of the bounding boxes are computed.
1072 void set_radii(const Graph& G,NodeArray<NodeAttributes>& A);
1074 //! Exports for each node \a v in \a G_reduced the position of the original_node in \a G.
1075 void export_NodeAttributes(
1076 Graph& G_reduced,
1077 NodeArray<NodeAttributes>& A_reduced,
1078 GraphAttributes& GA);
1080 //! Creates a simple and loopfree copy of \a G and stores the corresponding node / edge attributes.
1082 * The corresponding node / edge attributes are stored in \a A_reduced and
1083 * \a E_reduced; the links to the copy_node and original node are stored in \a A,
1084 * \a A_reduced, too.
1086 void make_simple_loopfree(
1087 const Graph& G,
1088 NodeArray<NodeAttributes>& A,
1089 EdgeArray<EdgeAttributes>E,
1090 Graph& G_reduced,
1091 NodeArray<NodeAttributes>& A_reduced,
1092 EdgeArray<EdgeAttributes>& E_reduced);
1094 //! Deletes parallel edges of \a G_reduced.
1096 * Saves for each set of parallel edges one representative edge in \a S and
1097 * saves in \a new_edgelength the new edge length of this edge in \a G_reduced.
1099 void delete_parallel_edges(
1100 const Graph& G,
1101 EdgeArray<EdgeAttributes>& E,
1102 Graph& G_reduced,
1103 List<edge>& S,
1104 EdgeArray<double>& new_edgelength);
1106 //! Sets for each edge \a e of \a G_reduced in \a S its edgelength to \a new_edgelength[\a e].
1108 * Also stores this information in \a E_reduced.
1110 void update_edgelength(
1111 List<edge>& S,
1112 EdgeArray <double>& new_edgelength,
1113 EdgeArray<EdgeAttributes>& E_reduced);
1115 //! Returns the value for the strength of the repulsive forces.
1117 * Used in the postprocessing step; depending on \a n = G.numberOfNodes().
1119 double get_post_rep_force_strength(int n) {
1120 return min(0.2,400.0/double(n));
1123 //! Makes the node positions integers.
1125 * If allowedPositions == apInteger the values are in a range depending on
1126 * G.number_of_nodes() and the average_ideal_edgelength. If allowed_positions
1127 * == apExponent the values are integers in a bounded integer range.
1129 void make_positions_integer(Graph& G, NodeArray<NodeAttributes>& A);
1131 //! Creates a simple drawing of \a AG in postscript format and saves it in file \a ps_file.
1132 void create_postscript_drawing(GraphAttributes& AG, char* ps_file);
1135 //------------------ functions for divide et impera step -----------------------
1137 //! Constructs the list of connected components of G.
1139 * Also constructs the corresponding lists with the node / edge attributes
1140 * (containing a pointer to the original node in \a G for each node in a subgraph).
1142 void create_maximum_connected_subGraphs(
1143 Graph& G,
1144 NodeArray<NodeAttributes>&A,
1145 EdgeArray<EdgeAttributes>&E,
1146 Graph G_sub[],
1147 NodeArray<NodeAttributes> A_sub[],
1148 EdgeArray<EdgeAttributes> E_sub[],
1149 NodeArray<int>& component);
1151 //! The drawings of the subgraphs are packed.
1153 * This is done such that the subgraphs do not overlap and fit into a small
1154 * box with the desired aspect ratio.
1156 void pack_subGraph_drawings(
1157 NodeArray<NodeAttributes>& A,
1158 Graph G_sub[],
1159 NodeArray<NodeAttributes> A_sub[]);
1161 //! The bounding rectangles of all connected componenents of \a G are calculated and stored in \a R.
1162 void calculate_bounding_rectangles_of_components(
1163 List<Rectangle>& R,
1164 Graph G_sub[],
1165 NodeArray<NodeAttributes> A_sub[]);
1167 //! The bounding rectangle of the componenet_index-th. component of G is returned.
1168 Rectangle calculate_bounding_rectangle(
1169 Graph& G,
1170 NodeArray<NodeAttributes>& A,
1171 int componenet_index);
1174 * If number_of_components > 1, the subgraphs \a G_sub are rotated and skipped to
1175 * find bounding rectangles with minimum area. The information is saved in \a R and
1176 * the node positions in \a A_sub are updated. If number_of_components == 1 a rotation
1177 * with minimal aspect ratio is found instead.
1179 void rotate_components_and_calculate_bounding_rectangles(
1180 List<Rectangle>&R,
1181 Graph G_sub[],
1182 NodeArray<NodeAttributes> A_sub[]);
1185 * Returns the area (aspect ratio area) of a rectangle with width w and height h
1186 * if comp_nr > 1 ( comp_nr == 1).
1188 double calculate_area(double width,double height,int comp_nr) {
1189 if (comp_nr == 1) //calculate aspect ratio area of the rectangle
1191 double ratio = width/height;
1193 if(ratio < pageRatio()) //scale width
1194 return ( width * height * (pageRatio()/ratio));
1195 else //scale height
1196 return (width * height * (ratio/pageRatio()));
1198 else //calculate area of the rectangle
1199 return width * height;
1203 * The positions of the nodes in the subgraphs are calculated by using the
1204 * information stored in R and are exported to A. (The coordinates of components
1205 * which surrounding rectangles have been tipped over in the packing step are
1206 * tipped over here,too)
1208 void export_node_positions(
1209 NodeArray<NodeAttributes>& A,
1210 List<Rectangle>& R,
1211 Graph G_sub[],
1212 NodeArray<NodeAttributes> A_sub[]);
1214 //! Frees dynamically allocated memory for the connected component subgraphs.
1215 void delete_all_subGraphs(
1216 Graph G_sub[],
1217 NodeArray<NodeAttributes> A_sub[],
1218 EdgeArray<EdgeAttributes> E_sub[])
1220 delete [] G_sub;
1221 delete [] A_sub;
1222 delete [] E_sub;
1227 //------------------ functions for multilevel step --------------------------
1230 * Returns the maximum number of iterations for the force calc. step depending
1231 * on act_level, max_level, FixedIterations, MaxIterChange, MaxIterFactor,
1232 * and the number of nodes of the Graph in the actual mutilevel.
1234 int get_max_mult_iter(int act_level, int max_level, int node_nr);
1237 //------------------ functions for force calculation ---------------------------
1239 //! The forces are calculated here.
1240 void calculate_forces(
1241 Graph& G,
1242 NodeArray<NodeAttributes>& A,
1243 EdgeArray<EdgeAttributes>& E,NodeArray<DPoint>& F,
1244 NodeArray<DPoint>& F_attr,
1245 NodeArray<DPoint>& F_rep,
1246 NodeArray<DPoint>& last_node_movement,
1247 int iter,
1248 int fine_tuning_step);
1250 //! The length of the computational box in the first iteration is set (down left corner is at (0,0).
1251 void init_boxlength_and_cornercoordinate(Graph& G,NodeArray<NodeAttributes>& A);
1253 //! The initial placements of the nodes are created by using initialPlacementForces().
1254 void create_initial_placement (Graph& G,NodeArray<NodeAttributes>& A);
1256 //! Sets all entries of \a F to (0,0).
1257 void init_F (Graph& G, NodeArray<DPoint>& F);
1260 //! Make initializations for the data structures that are used in the choosen class for rep. force calculation.
1261 void make_initialisations_for_rep_calc_classes(
1262 Graph& G/*,
1263 NodeArray<NodeAttributes> &A,
1264 NodeArray<DPoint>& F_rep*/);
1266 //! Calculates repulsive forces for each node.
1267 void calculate_repulsive_forces(
1268 Graph &G,
1269 NodeArray<NodeAttributes>& A,
1270 NodeArray<DPoint>& F_rep)
1272 if(repulsiveForcesCalculation() == rfcExact )
1273 FR.calculate_exact_repulsive_forces(G,A,F_rep);
1274 else if(repulsiveForcesCalculation() == rfcGridApproximation )
1275 FR.calculate_approx_repulsive_forces(G,A,F_rep);
1276 else //repulsiveForcesCalculation() == rfcNMM
1277 NM.calculate_repulsive_forces(G,A,F_rep);
1281 //! Deallocates dynamically allocated memory of the choosen rep. calculation class.
1282 void deallocate_memory_for_rep_calc_classes()
1284 if(repulsiveForcesCalculation() == rfcNMM)
1285 NM.deallocate_memory();
1288 //! Calculates attractive forces for each node.
1289 void calculate_attractive_forces(
1290 Graph& G,
1291 NodeArray<NodeAttributes> & A,
1292 EdgeArray<EdgeAttributes>& E,
1293 NodeArray<DPoint>& F_attr);
1295 //! Returns the attractive force scalar.
1296 double f_attr_scalar (double d,double ind_ideal_edge_length);
1298 //! Add attractive and repulsive forces for each node.
1299 void add_attr_rep_forces(
1300 Graph& G,
1301 NodeArray<DPoint>& F_attr,
1302 NodeArray<DPoint>& F_rep,
1303 NodeArray<DPoint>& F,
1304 int iter,
1305 int fine_tuning_step);
1307 //! Move the nodes.
1308 void move_nodes(Graph& G,NodeArray<NodeAttributes>& A,NodeArray<DPoint>& F);
1310 //! Computes a new tight computational square-box.
1312 * (Guaranteeing, that all midpoints are inside the square.)
1314 void update_boxlength_and_cornercoordinate(Graph& G,NodeArray<NodeAttributes>& A);
1316 //! Describes the max. radius of a move in one time step, depending on the number of iterations.
1317 double max_radius(int iter) {
1318 return (iter == 1) ? boxlength/1000 : boxlength/5;
1321 //! The average_ideal_edgelength for all edges is computed.
1322 void set_average_ideal_edgelength(Graph& G,EdgeArray<EdgeAttributes>& E);
1325 * Calculates the average force on each node in the actual iteration, which is
1326 * needed if StopCriterion is scThreshold() or scFixedIterationsOrThreshold().
1328 double get_average_forcevector_length (Graph& G, NodeArray<DPoint>& F);
1331 * Depending on the direction of \a last_node_movement[\a v], the length of the next
1332 * displacement of node \a v is restricted.
1334 void prevent_oscilations(
1335 Graph& G,
1336 NodeArray<DPoint>& F,
1337 NodeArray<DPoint>&
1338 last_node_movement,
1339 int iter);
1341 //! Calculates the angle between \a PQ and \a PS in [0,2pi).
1342 double angle(DPoint& P, DPoint& Q, DPoint& R);
1344 //! \a last_node_movement is initialized to \a F (used after first iteration).
1345 void init_last_node_movement(
1346 Graph& G,
1347 NodeArray<DPoint>& F,
1348 NodeArray<DPoint>& last_node_movement);
1351 * If resizeDrawing is true, the drawing is adapted to the ideal average
1352 * edge length by shrinking respectively expanding the drawing area.
1354 void adapt_drawing_to_ideal_average_edgelength(
1355 Graph& G,
1356 NodeArray<NodeAttributes>& A,
1357 EdgeArray<EdgeAttributes>& E);
1360 * The force is restricted to have values within the comp. box (needed for
1361 * exception handling, if the force is too large for further calculations).
1363 void restrict_force_to_comp_box(DPoint& force) {
1364 double x_min = down_left_corner.m_x;
1365 double x_max = down_left_corner.m_x+boxlength;
1366 double y_min = down_left_corner.m_y;
1367 double y_max = down_left_corner.m_y+boxlength;
1368 if (force.m_x < x_min )
1369 force.m_x = x_min;
1370 else if (force.m_x > x_max )
1371 force.m_x = x_max;
1372 if (force.m_y < y_min )
1373 force.m_y = y_min;
1374 else if (force.m_y > y_max )
1375 force.m_y = y_max;
1379 //------------------- functions for analytic information -------------------------
1381 //! Sets time_total to zero.
1382 void init_time() { time_total = 0; }
1385 } //end namespace ogdf
1387 #endif