File: TreeLayout.h

package info (click to toggle)
tulip 4.8.0dfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 179,264 kB
  • ctags: 64,517
  • sloc: cpp: 600,444; ansic: 36,311; makefile: 22,136; python: 1,304; sh: 946; yacc: 522; xml: 337; pascal: 157; php: 66; lex: 55
file content (302 lines) | stat: -rw-r--r-- 10,659 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
/*
 * $Revision: 2583 $
 *
 * last checkin:
 *   $Author: gutwenger $
 *   $Date: 2012-07-12 01:02:21 +0200 (Thu, 12 Jul 2012) $
 ***************************************************************/

/** \file
 * \brief Declaration of linear time layout algorithm for trees
 *        (TreeLayout) based on Walker's algorithm.
 *
 * \author Christoph Buchheim
 *
 * \par License:
 * This file is part of the Open Graph Drawing Framework (OGDF).
 *
 * \par
 * Copyright (C)<br>
 * See README.txt in the root directory of the OGDF installation for details.
 *
 * \par
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * Version 2 or 3 as published by the Free Software Foundation;
 * see the file LICENSE.txt included in the packaging of this file
 * for details.
 *
 * \par
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * \par
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 * \see  http://www.gnu.org/copyleft/gpl.html
 ***************************************************************/


#ifdef _MSC_VER
#pragma once
#endif

#ifndef OGDF_TREE_LAYOUT_H
#define OGDF_TREE_LAYOUT_H

#include <ogdf/module/LayoutModule.h>
#include <ogdf/basic/SList.h>

namespace ogdf {

/**
 * \brief The tree layout algorithm.
 *
 * The class TreeLayout represents the improved version of the tree layout
 * algorithm by Walker presented in:
 *
 * Christoph Buchheim, Michael J&uuml;nger, Sebastian Leipert: <i>Drawing
 * rooted trees in linear time</i>. Software: Practice and Experience 36(6),
 * pp. 651-665, 2006.
 *
 * The algorithm also allows to lay out a forest, i.e., a collection of trees.
 *
 * <H3>Optional parameters</H3>
 * Tree layout provides various optional parameters.
 *
 * <table>
 *   <tr>
 *     <th><i>Option</i><th><i>Type</i><th><i>Default</i><th><i>Description</i>
 *   </tr><tr>
 *     <td><i>siblingDistance</i><td>double<td>20.0
 *     <td>The horizontal spacing between adjacent sibling nodes.
 *   </tr><tr>
 *     <td><i>subtreeDistance</i><td>double<td>20.0
 *     <td>The horizontal spacing between adjacent subtrees.
 *   </tr><tr>
 *     <td><i>levelDistance</i><td>double<td>50.0
 *     <td>The vertical spacing between adjacent levels.
 *   </tr><tr>
 *     <td><i>treeDistance</i><td>double<td>50.0
 *     <td>The horizontal spacing between adjacent trees in a forest.
 *   </tr><tr>
 *     <td><i>orthogonalLayout</i><td>bool<td>false
 *     <td>Determines whether edges are routed in an orthogonal
 *     or straight-line fashion.
 *   </tr><tr>
 *     <td><i>orientation</i><td> #Orientation <td> #topToBottom
 *     <td>Determines if the tree is laid out in a top-to-bottom,
 *     bottom-to-top, left-to-right, or right-to-left fashion.
 *   </tr><tr>
 *     <td><i>selectRoot</i><td> #RootSelectionType <td> #rootIsSource
 *     <td>Determines how to select the root of the tree(s). Possible
 *     selection strategies are to take a (unique) source or sink in
 *     the graph, or to use the coordinates and to select the topmost
 *     node for top-to-bottom orientation, etc.
 *   </tr>
 * </table>
 *
 * The spacing between nodes is determined by the <i>siblingDistance</i>,
 * <i>subtreeDistance</i>, <i>levelDistance</i>, and <i>treeDistance</i>.
 * The layout style is determined by <i>orthogonalLayout</i> and
 * <i>orientation</i>; the root of the tree is selected according to
 * th eselection strategy given by <i>selectRoot</i>.
 */
class OGDF_EXPORT TreeLayout : public LayoutModule {
public:
	//! Determines how to select the root of the tree.
	enum RootSelectionType {
		rootIsSource, //!< Select a source in the graph.
		rootIsSink,   //!< Select a sink in the graph.
		rootByCoord   //!< Use the coordinates, e.g., select the topmost node if orientation is topToBottom.
	};

private:
	double m_siblingDistance;        //!< The minimal distance between siblings.
	double m_subtreeDistance;        //!< The minimal distance between subtrees.
	double m_levelDistance;          //!< The minimal distance between levels.
	double m_treeDistance;           //!< The minimal distance between trees.

	bool m_orthogonalLayout;         //!< Option for orthogonal style (yes/no).
	Orientation m_orientation;       //!< Option for orientation of tree layout.
	RootSelectionType m_selectRoot;  //!< Option for how to determine the root.

	NodeArray<int> m_number;         //!< Consecutive numbers for children.

	NodeArray<node> m_parent;        //!< Parent node, 0 if root.
	NodeArray<node> m_leftSibling;   //!< Left sibling, 0 if none.
	NodeArray<node> m_firstChild;    //!< Leftmost child, 0 if leaf.
	NodeArray<node> m_lastChild;	 //!< Rightmost child, 0 if leaf.
	NodeArray<node> m_thread;        //!< Thread, 0 if none.
	NodeArray<node> m_ancestor;      //!< Actual highest ancestor.

	NodeArray<double> m_preliminary; //!< Preliminary x-coordinates.
	NodeArray<double> m_modifier;    //!< Modifier of x-coordinates.
	NodeArray<double> m_change;      //!< Change of shift applied to subtrees.
	NodeArray<double> m_shift;       //!< Shift applied to subtrees.

	SListPure<edge> m_reversedEdges; //!< List of temporarily removed edges.
	Graph           *m_pGraph; //!< The input graph.

public:
	//! Creates an instance of tree layout and sets options to default values.
	TreeLayout();

	//! Copy constructor.
	TreeLayout(const TreeLayout &tl);

	// destructor
	~TreeLayout();


	/**
	 *  @name Algorithm call
	 *  @{
	 */

	/**
	 * \brief Calls tree layout for graph attributes \a GA.
	 *
	 * \pre The graph is a tree.
	 *
	 * The order of children is given by the adjacency lists;
	 * the successor of the unique in-edge of a non-root node
	 * leads to its leftmost child; the leftmost child of the root
	 * is given by its first adjacency entry.
	 * @param GA is the input graph and will also be assigned the layout information.
	 */
	void call(GraphAttributes &GA);

	/**
	 * \brief Calls tree layout for graph attributes \a GA.
	 *
	 * \pre The graph is a tree.
	 *
	 * Sorts the adjacency entries according to the positions of adjacent
	 * vertices in \a GA.
	 * @param GA is the input graph and will also be assigned the layout information.
	 * @param G is the graph associated with \a GA.
	 */
	void callSortByPositions(GraphAttributes &GA, Graph &G);


	/** @}
	 *  @name Optional parameters
	 *  @{
	 */

	//! Returns the the minimal required horizontal distance between siblings.
	double siblingDistance() const { return m_siblingDistance; }

	//! Sets the the minimal required horizontal distance between siblings to \a x.
	void siblingDistance(double x) { m_siblingDistance = x; }

	//! Returns the minimal required horizontal distance between subtrees.
	double subtreeDistance() const { return m_subtreeDistance; }

	//! Sets the minimal required horizontal distance between subtrees to \a x.
	void subtreeDistance(double x) { m_subtreeDistance = x; }

	//! Returns the minimal required vertical distance between levels.
	double levelDistance() const { return m_levelDistance; }

	//! Sets the minimal required vertical distance between levels to \a x.
	void levelDistance(double x) { m_levelDistance = x; }

	//! Returns the minimal required horizontal distance between trees in the forest.
	double treeDistance() const { return m_treeDistance; }

	//! Sets the minimal required horizontal distance between trees in the forest to \a x.
	void treeDistance(double x) { m_treeDistance = x; }

	//! Returns whether orthogonal edge routing style is used.
	bool orthogonalLayout() const { return m_orthogonalLayout; }

	//! Sets the option for orthogonal edge routing style to \a b.
	void orthogonalLayout(bool b) { m_orthogonalLayout = b; }

	//! Returns the option that determines the orientation of the layout.
	Orientation orientation() const { return m_orientation; }

	//! Sets the option that determines the orientation of the layout to \a orientation.
	void orientation(Orientation orientation) { m_orientation = orientation; }

	//! Returns the option that determines how the root is selected.
	RootSelectionType rootSelection() const { return m_selectRoot; }

	//! Sets the option that determines how the root is selected to \a rootSelection.
	void rootSelection(RootSelectionType rootSelection) { m_selectRoot = rootSelection; }


	/** @}
	 *  @name Operators
	 *  @{
	 */

	//! Assignment operator.
	TreeLayout &operator=(const TreeLayout &tl);

	//! @}

private:
	class AdjComparer;

	void adjustEdgeDirections(Graph &G, node v, node parent);
	void setRoot(GraphAttributes &AG, Graph &tree);
	void undoReverseEdges(GraphAttributes &AG);

	// initialize all node arrays and
	// compute the tree structure from the adjacency lists
	//
	// returns the root node
	void initializeTreeStructure(const Graph &tree, List<node> &roots);

	// delete all node arrays
	void deleteTreeStructure();

	// returns whether node v is a leaf
	int isLeaf(node v) const;

	// returns the successor of node v on the left/right contour
	// returns 0 if there is none
	node nextOnLeftContour(node v) const;
	node nextOnRightContour(node v) const;

	// recursive bottom up traversal of the tree for computing
	// preliminary x-coordinates
	void firstWalk(node subtree,const GraphAttributes &AG,bool upDown);

	// space out the small subtrees on the left hand side of subtree
	// defaultAncestor is used for all nodes with obsolete m_ancestor
	void apportion(
		node subtree,
		node &defaultAncestor,
		const GraphAttributes &AG,
		bool upDown);

	// recursive top down traversal of the tree for computing final
	// x-coordinates
	void secondWalkX(node subtree, double modifierSum, GraphAttributes &AG);
	void secondWalkY(node subtree, double modifierSum, GraphAttributes &AG);

	// compute y-coordinates and edge shapes
	void computeYCoordinatesAndEdgeShapes(node root,GraphAttributes &AG);
	void computeXCoordinatesAndEdgeShapes(node root,GraphAttributes &AG);

	void findMinX(GraphAttributes &AG, node root, double &minX);
	void findMinY(GraphAttributes &AG, node root, double &minY);
	void findMaxX(GraphAttributes &AG, node root, double &maxX);
	void findMaxY(GraphAttributes &AG, node root, double &maxY);
	void shiftTreeX(GraphAttributes &AG, node root, double shift);
	void shiftTreeY(GraphAttributes &AG, node root, double shift);
};

} // end namespace ogdf

#endif