1 /** \file 2 * \brief declaration of the FastSimpleHierarchyLayout 3 * (third phase of sugiyama) 4 * 5 * \author Till Schäfer, Carsten Gutwenger 6 * 7 * \par License: 8 * This file is part of the Open Graph Drawing Framework (OGDF). 9 * 10 * \par 11 * Copyright (C)<br> 12 * See README.md in the OGDF root directory for details. 13 * 14 * \par 15 * This program is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU General Public License 17 * Version 2 or 3 as published by the Free Software Foundation; 18 * see the file LICENSE.txt included in the packaging of this file 19 * for details. 20 * 21 * \par 22 * This program is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License for more details. 26 * 27 * \par 28 * You should have received a copy of the GNU General Public 29 * License along with this program; if not, see 30 * http://www.gnu.org/copyleft/gpl.html 31 */ 32 33 #pragma once 34 35 #include <ogdf/layered/HierarchyLayoutModule.h> 36 #include <ogdf/layered/Hierarchy.h> 37 #include <ogdf/basic/NodeArray.h> 38 39 namespace ogdf { 40 41 /** 42 * \brief Coordinate assignment phase for the Sugiyama algorithm by Ulrik Brandes and Boris Köpf 43 * 44 * @ingroup gd-hlm 45 * 46 * This class implements a hierarchy layout algorithm, i.e., it layouts 47 * hierarchies with a given order of nodes on each layer. It is used as a third 48 * phase of the Sugiyama algorithm. 49 * 50 * The Algorithm runs in three phases.<br> 51 * - Alignment (4x)<br> 52 * - Horizontal Compactation (4x)<br> 53 * - Balancing 54 * 55 * The <i>Alignment</i> and <i>Horzontal Compactation</i> phase are calculated downward, upward, 56 * left-to-right and right-to-left. The four resulting layouts are combined in a balancing step. 57 * 58 * The implementation is based on: 59 * 60 * Ulrik Brandes, Boris Köpf: <i>Fast and Simple Horizontal Coordinate Assignment</i>. 61 * LNCS 2002, Volume 2265/2002, pp. 33-36 62 * 63 * <h3>Optional Parameters</h3> 64 * 65 * <table> 66 * <tr> 67 * <th>Option</th><th>Type</th><th>Default</th><th>Description</th> 68 * </tr><tr> 69 * <td><i>node distance</i></td><td>int</td><td>150</td> 70 * <td>the minimal horizontal distance between two nodes on the same layer</td> 71 * </tr><tr> 72 * <td><i>layer distance</i></td><td>int</td><td>75</td> 73 * <td>the minimal vertical distance between two nodes on adjacent layers</td> 74 * </tr><tr> 75 * <td><i>balanced</i></td><td>bool</td><td>true</td> 76 * <td>determines whether balancing is used</td> 77 * </tr><tr> 78 * <td><i>left-to-right</i></td><td>bool</td><td>true</td> 79 * <td>determines whether block alignment is computed by a left-to-right (true) or right-to-left traversal</td> 80 * </tr><tr> 81 * <td><i>downward</i></td><td>bool</td><td>true</td> 82 * <td>determines whether block alignment is computed by a downward (true) or upward traversal</td> 83 * </tr> 84 * </table> 85 */ 86 class OGDF_EXPORT FastSimpleHierarchyLayout : public HierarchyLayoutModule 87 { 88 private: 89 double m_minXSep; //!< stores the option <i>node distance</i>. 90 double m_ySep; //!< stores the option <i>layer distance</i>. 91 bool m_balanced; //!< stores the option <i>balanced</i>. 92 bool m_downward; //!< stores the option <i>downward</i>. 93 bool m_leftToRight; //!< stores the option <i>left-to-right</i>. 94 95 protected: 96 virtual void doCall(const HierarchyLevelsBase &levels, GraphAttributes &AGC) override; 97 98 public: 99 //! Creates an instance of fast simple hierarchy layout. 100 /** 101 * Sets the options to default values, i.e., use balanced layout with left-to-right node 102 * direction on each layer, node distance as given by LayoutStandards, and layer distance as 103 * 1.5 times node distance. 104 */ 105 FastSimpleHierarchyLayout(); 106 107 108 //! Copy constructor. 109 FastSimpleHierarchyLayout(const FastSimpleHierarchyLayout &); 110 111 // destructor ~FastSimpleHierarchyLayout()112 virtual ~FastSimpleHierarchyLayout() { } 113 114 115 //! Assignment operator 116 FastSimpleHierarchyLayout &operator=(const FastSimpleHierarchyLayout &); 117 118 119 //! Returns the option <i>node distance</i>. nodeDistance()120 double nodeDistance() const { 121 return m_minXSep; 122 } 123 124 //! Sets the option node distance to \p dist. nodeDistance(double dist)125 void nodeDistance(double dist) { 126 m_minXSep = dist; 127 } 128 129 //! Returns the option <i>layer distance</i>. layerDistance()130 double layerDistance() const { 131 return m_ySep; 132 } 133 134 //! Sets the option <i>layer distance</i> to \p dist. layerDistance(double dist)135 void layerDistance(double dist) { 136 m_ySep = dist; 137 } 138 139 //! Returns the option <i>downward</i>. downward()140 bool downward() const { 141 return m_downward; 142 } 143 144 //! Sets the option <i>downward</i> to \p d. downward(bool d)145 void downward(bool d) { 146 m_downward = d; 147 } 148 149 //! Returns the option <i>left-to-right</i>. leftToRight()150 bool leftToRight() const { 151 return m_leftToRight; 152 } 153 154 //! Sets the option <i>left-to-right</i> to \p b. leftToRight(bool b)155 void leftToRight(bool b) { 156 m_leftToRight = b; 157 } 158 159 //! Returns the option <i>balanced</i>. balanced()160 bool balanced() const { 161 return m_balanced; 162 } 163 164 //! Sets the option <i>balanced</i> to \p b. balanced(bool b)165 void balanced(bool b) { 166 m_balanced = b; 167 } 168 169 170 private: 171 /** 172 * Preprocessing step to find all type1 conflicts. 173 * A type1 conflict is a crossing of a inner segment with a non-inner segment. 174 * 175 * This is for preferring straight inner segments. 176 * 177 * @param levels The Hierarchy 178 * @param downward The level direction 179 * @param type1Conflicts is assigned the conflicts, (type1Conflicts[v])[u]=true means (u,v) is marked, u is the upper node 180 */ 181 void markType1Conflicts(const HierarchyLevelsBase &levels, bool downward, NodeArray<NodeArray<bool> > &type1Conflicts); 182 183 /** 184 * Align each node to a node on the next higher level. The result is a blockgraph where each 185 * node is in a block whith a nother node when they have the same root. 186 * 187 * @param levels The Hierarchy 188 * @param root The root for each node (calculated by this method) 189 * @param align The alignment to the next level node (align(v)=u <=> u is aligned to v) (calculated by this method) 190 * @param type1Conflicts Type1 conflicts to prefer straight inner segments 191 * @param downward The level direction 192 * @param leftToRight The node direction on each level 193 */ 194 void verticalAlignment( 195 const HierarchyLevelsBase &levels, 196 NodeArray<node> &root, 197 NodeArray<node> &align, 198 const NodeArray<NodeArray<bool> > &type1Conflicts, 199 const bool downward, 200 const bool leftToRight); 201 202 /** 203 * Computes the width of each block, i.e., the maximal width of a node in the block, and 204 * stores it in blockWidth for the root of the block. 205 * 206 * @param GC The input graph copy 207 * @param GCA The input graph copies (gives in particular the widths of nodes) 208 * @param root The root for each node (calculated by this method) 209 * @param blockWidth Is assigned the width of each block (stored for the root) 210 */ 211 void computeBlockWidths( 212 const GraphCopy &GC, 213 const GraphAttributes &GCA, 214 NodeArray<node> &root, 215 NodeArray<double> &blockWidth); 216 217 /** 218 * Calculate the coordinates for each node 219 * 220 * @param align The alignment to the next level node (align(v)=u <=> u is aligned to v) 221 * @param levels The Hierarchy 222 * @param root The root for each node 223 * @param blockWidth The width of each block 224 * @param x The x-coordinates for each node (calculated by this method) 225 * @param leftToRight The node direction on each level 226 * @param downward The level direction 227 */ 228 void horizontalCompactation( 229 const NodeArray<node> &align, 230 const HierarchyLevelsBase &levels, 231 const NodeArray<node> &root, 232 const NodeArray<double> &blockWidth, 233 NodeArray<double> &x, 234 const bool leftToRight, 235 bool downward); 236 237 /** 238 * Calculate the coordinate for root nodes (placing) 239 * 240 * @param v The root node to place 241 * @param sink The Sink for each node. A sink identifies each block class (calculated by this method) 242 * @param shift The shift for each class (calculated by this method) 243 * @param x The class relative x-coordinate for each node (calculated by this method) 244 * @param align The alignment to the next level node (align(v)=u <=> u is aligned to v) 245 * @param levels The Hierarchy 246 * @param blockWidth The width of each block 247 * @param root The root for each node 248 * @param leftToRight The node direction on each level 249 */ 250 void placeBlock( 251 node v, 252 NodeArray<node> &sink, 253 NodeArray<double> &shift, 254 NodeArray<double> &x, 255 const NodeArray<node> &align, 256 const HierarchyLevelsBase &levels, 257 const NodeArray<double> &blockWidth, 258 const NodeArray<node> &root, 259 const bool leftToRight); 260 261 /** 262 * The twin of an inner Segment 263 * 264 * @return Parent node which is connected by an inner segment. 265 * nullptr if there is no parent segment or if the segment is not an inner segment. 266 */ 267 node virtualTwinNode(const HierarchyLevelsBase &levels, const node v, const HierarchyLevelsBase::TraversingDir dir) const; 268 269 /** 270 * Predecessor of v on the same level, 271 * 272 * @param v The node for which the predecessor should be calculated. 273 * @param levels The Hierarchy 274 * @param leftToRight If true the left predecessor is choosen. Otherwise the right predecessor. 275 * @return Predescessor on the same level. nullptr if there is no predecessor. 276 */ 277 node pred(const node v, const HierarchyLevelsBase &levels, const bool leftToRight); 278 }; 279 280 } 281