| 1 | /** \file |
| 2 | * \brief MMM is a Multilevel Graph drawing Algorithm that can use different modules. |
| 3 | * |
| 4 | * \author Gereon Bartel |
| 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 <memory> |
| 35 | #include <ogdf/module/LayoutModule.h> |
| 36 | #include <ogdf/energybased/multilevel_mixer/MultilevelGraph.h> |
| 37 | #include <ogdf/energybased/multilevel_mixer/MultilevelBuilder.h> |
| 38 | #include <ogdf/energybased/multilevel_mixer/InitialPlacer.h> |
| 39 | |
| 40 | |
| 41 | namespace ogdf { |
| 42 | |
| 43 | //! Modular multilevel graph layout. |
| 44 | /** |
| 45 | * @ingroup gd-multi |
| 46 | * |
| 47 | * <H3>%Module options</H3> |
| 48 | * The various phases of the algorithm can be exchanged by setting |
| 49 | * module options allowing flexible customization. The algorithm provides |
| 50 | * the following module options: |
| 51 | * |
| 52 | * <table> |
| 53 | * <tr> |
| 54 | * <th><i>Option</i><th><i>Type</i><th><i>Default</i><th><i>Description</i> |
| 55 | * </tr><tr> |
| 56 | * <td><i>multilevelBuilder</i><td>MultilevelBuilder<td>SolarMerger |
| 57 | * <td>The multilevel builder module that computes the multilevel graph hierarchy. |
| 58 | * </tr><tr> |
| 59 | * <td><i>initialPlacer</i><td>InitialPlacer<td>BarycenterPlacer |
| 60 | * <td>The initial placer module that computes the initial positions for nodes inserted into the previous level. |
| 61 | * </tr><tr> |
| 62 | * <td><i>levelLayout</i><td>LayoutModule<td>FastMultipoleEmbedder |
| 63 | * <td>The layout module applied on each level. |
| 64 | * </tr><tr> |
| 65 | * <td><i>finalLayout</i><td>LayoutModule<td>none |
| 66 | * <td>The layout module applied on the last level. |
| 67 | * </tr><tr> |
| 68 | * <td><i>postLayout</i><td>LayoutModule<td>none |
| 69 | * <td>The layout module applied to the final drawing for additional beautification. |
| 70 | * </tr> |
| 71 | * </table> |
| 72 | */ |
| 73 | class OGDF_EXPORT ModularMultilevelMixer : public LayoutModule |
| 74 | { |
| 75 | private: |
| 76 | |
| 77 | //! The layout algorithm applied on each level. |
| 78 | /** |
| 79 | * The one-level layout module should not completely discard the initial Layout |
| 80 | * but do incremental beautification. |
| 81 | * Usually a simple force-directed / energy-based Layout should be chosen. |
| 82 | */ |
| 83 | std::unique_ptr<LayoutModule> m_oneLevelLayoutModule; |
| 84 | |
| 85 | //! The layout algorithm applied on the last level (i.e., the largest graph in the multilevel hierarchy). |
| 86 | /** |
| 87 | * The final layout module can be set to speed up the computation if the |
| 88 | * one-level layout ist relatively slow. If not set, the one-level layout |
| 89 | * is also used on the last level. |
| 90 | */ |
| 91 | std::unique_ptr<LayoutModule> m_finalLayoutModule; |
| 92 | |
| 93 | //! The multilevel builder module computes the multilevel hierarchy. |
| 94 | std::unique_ptr<MultilevelBuilder> m_multilevelBuilder; |
| 95 | |
| 96 | //! The initial placer module computes the initial positions for nodes inserted into the previous level. |
| 97 | std::unique_ptr<InitialPlacer> m_initialPlacement; |
| 98 | |
| 99 | //! The one-level layout will be called #m_times to improve quality. |
| 100 | int m_times; |
| 101 | |
| 102 | //! If set to a value > 0, all edge weights will be set to this value. |
| 103 | double m_fixedEdgeLength; |
| 104 | |
| 105 | //! If set to a value > 0, all node sizes will be set to this value. |
| 106 | double m_fixedNodeSize; |
| 107 | |
| 108 | double m_coarseningRatio; //!< Ratio between sizes of previous (p) and current (c) level graphs: c/p |
| 109 | |
| 110 | bool m_levelBound; //!< Determines if computation is stopped when number of levels is too high. |
| 111 | bool m_randomize; //!< Determines if initial random layout is computed. |
| 112 | |
| 113 | public: |
| 114 | |
| 115 | //! Error codes for calls. |
| 116 | enum class erc { |
| 117 | None, //!< no error |
| 118 | LevelBound //!< level bound exceeded by merger step |
| 119 | }; |
| 120 | |
| 121 | ModularMultilevelMixer(); |
| 122 | |
| 123 | //! Sets the one-level layout module to \p levelLayout. |
| 124 | void setLevelLayoutModule(LayoutModule *levelLayout) { |
| 125 | m_oneLevelLayoutModule.reset(levelLayout); |
| 126 | } |
| 127 | |
| 128 | //! Sets the final layout module to \p finalLayout. |
| 129 | void setFinalLayoutModule(LayoutModule *finalLayout) { |
| 130 | m_finalLayoutModule.reset(finalLayout); |
| 131 | } |
| 132 | |
| 133 | //! Sets the multilevel builder module to \p levelBuilder. |
| 134 | void setMultilevelBuilder(MultilevelBuilder *levelBuilder) { |
| 135 | m_multilevelBuilder.reset(levelBuilder); |
| 136 | } |
| 137 | |
| 138 | //! Sets the initial placer module to \p placement. |
| 139 | void setInitialPlacer(InitialPlacer *placement) { |
| 140 | m_initialPlacement.reset(placement); |
| 141 | } |
| 142 | |
| 143 | //! Determines how many times the one-level layout will be called. |
| 144 | void setLayoutRepeats(int times = 1) { m_times = times; } |
| 145 | |
| 146 | //! If \p len > 0, all edge weights will be set to \p len. |
| 147 | void setAllEdgeLengths(double len) { m_fixedEdgeLength = len; } |
| 148 | |
| 149 | //! If \p size > 0, all node sizes will be set to \p size. |
| 150 | void setAllNodeSizes(double size) { m_fixedNodeSize = size; } |
| 151 | |
| 152 | //! Determines if an initial random layout is computed. |
| 153 | void setRandomize(bool b) { m_randomize = b; } |
| 154 | |
| 155 | //! Determines if computation is stopped when number of levels is too high. |
| 156 | void setLevelBound(bool b) { m_levelBound = b; } |
| 157 | |
| 158 | //! Calls the multilevel layout algorithm for graph attributes \p GA. |
| 159 | void call(GraphAttributes &GA) override; |
| 160 | |
| 161 | /** |
| 162 | * \brief Calls the multilevel layout algorithm for multilevel graph \a MLG. |
| 163 | * |
| 164 | * This method allows the mixer to modify the Graph, saving some memory |
| 165 | * compared to a normal call(GA) in our implementation. |
| 166 | * (because the Graph is already given in the MultiLevelGraph Format |
| 167 | * (or can be converted without creating a copy) AND the layout would need a copy otherwise). |
| 168 | * All Incremental Layouts (especially energy based) CAN be called by ModularMultilevelMixer. |
| 169 | * @param MLG is the input graph and will also be assigned the layout information. |
| 170 | */ |
| 171 | #if 0 |
| 172 | virtual void call(MultilevelGraph &MLG) { |
| 173 | GraphAttributes GA(MLG.getGraph()); |
| 174 | MLG.exportAttributesSimple(GA); |
| 175 | call(GA); |
| 176 | MLG.importAttributesSimple(GA); |
| 177 | }; |
| 178 | #else |
| 179 | virtual void call(MultilevelGraph &MLG); |
| 180 | #endif |
| 181 | |
| 182 | //! Returns the error code of last call. |
| 183 | erc errorCode() { return m_errorCode; } |
| 184 | |
| 185 | //! Returns the ratio c/p between sizes of previous (p) and current (c) level graphs. |
| 186 | double coarseningRatio() { return m_coarseningRatio; } |
| 187 | |
| 188 | private: |
| 189 | erc m_errorCode; //!< The error code of the last call. |
| 190 | }; |
| 191 | |
| 192 | } |
| 193 | |