File: TopologyModule.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 (240 lines) | stat: -rw-r--r-- 8,295 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
/*
 * $Revision: 3960 $
 *
 * last checkin:
 *   $Author: gutwenger $
 *   $Date: 2014-03-13 11:36:28 +0100 (Thu, 13 Mar 2014) $
 ***************************************************************/

/** \file
 * \brief Declaration of class TopologyModule.
 *
 * The TopologyModule transports the layout information from
 * GraphAttributes to PlanRep on that Graph, i.e., it computes a
 * combinatorial embedding for the input.
 *
 * \author Karsten Klein
 *
 * \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_TOPOLOGYMODULE_H
#define OGDF_TOPOLOGYMODULE_H



#include <ogdf/planarity/PlanRep.h>
#include <ogdf/basic/GraphAttributes.h>
#include <ogdf/basic/EdgeComparer.h>

namespace ogdf {

class EdgeLeg;

//===============================================
//main function(s):
//		setEmbeddingFromGraph(PlanRep&, GraphAttributes&)
//	    assumes that PG(AG) without bend nodes in PG
//
//		sortEdgesFromLayout(GraphAttributes &AG)
//      sort the edges in AG, no crossing insertion
//===============================================

//! Constructs embeddings from given layout.
/**
 * This class comprises functions for constructing the combinatorial embedding of a graph
 * or a planarized representation from a given layout.
 *
 * The main functions of the class are the following:
 *   - setEmbeddingFromGraph(PlanRep &PG, GraphAttributes &GA)
 *   - sortEdgesFromLayout(GraphAttributes &GA)
 */
class OGDF_EXPORT TopologyModule
{
public:
	TopologyModule() : m_options(opDegOneCrossings | opGenToAss |
		opCrossFlip | opLoop | opFlipUML) {}
	virtual ~TopologyModule() {}

	//! The (pre/post)processing options
	/**
	 * opCrossFlip increases running time by constant * n,
	 * opLoop increases running time by constant * m
	 */
	enum Options {
		opDegOneCrossings = 0x0001, //!< should degree one node's edge be crossed
		opGenToAss        = 0x0002, //!< should generalizations be turned into associations
		opCrossFlip       = 0x0004, //!< if there is a crossing between two edges with the same start or end point,
		                            //!< should their position at the node be flipped and the crossing be skipped?
		opFlipUML         = 0x0010, //!< only flip if same edge type
		opLoop            = 0x0008  //!< should loops between crossings (consecutive on both crossing edges) be deleted
		                            //!< (we dont check for enclosed CC's; therefore it is safe to remove the crossing).
	};

	void setOptions(int i) { m_options = i; }
	void addOption(TopologyModule::Options o)  { m_options = (m_options | o); }

	//! Uses the layout \a GA to determine an embedding for \a PG.
	/**
	 * Non-constness of GA in the following methods is only used when resolving problems,
	 * e.g., setting edge types if two generalizations cross in the input layout
	 *
	 * @param PG  is the input graph.
	 * @param GA  is the input layout.
	 * @param adjExternal  is assigned the external face (if \a setExternal is true).
	 * @param setExternal if true, we run over faces to compute the external face.
	 * @param reuseGAEmbedding If true, the call only checks for a correct embedding of \a PG
	 *                         and tries to insert crossings detected in the given layout otherwise.
	 *                         This allows to assign already sorted UMLGraphs.
	 *                         NOTE: if the sorting of the edges does not correspond to the layout given in \a GA,
	 *                         this cannot work correctly
	 * @return false if planarization fails; true otherwise.
	 */
	bool setEmbeddingFromGraph(
		PlanRep &PG,
		GraphAttributes &GA,
		adjEntry &adjExternal,
		bool setExternal = true,
		bool reuseGAEmbedding = false);

	//! Sorts the edges around all nodes of \a GA corresponding to the layout given in \a GA.
	/**
	 * There is no check of the embedding afterwards because this method could be used as a first step of a planarization
	 *
	 * @param G  is the input graph whose adjacency lists get sorted.
	 * @param GA is the input layout.
	 */
	void sortEdgesFromLayout(Graph &G, GraphAttributes &GA);

	face getExternalFace(PlanRep &PG, const GraphAttributes &AG);

	double faceSum(PlanRep &PG, const GraphAttributes &AG, face f);

protected:
	//compute a planarization, i.e. insert crossing vertices,
	//corresponding to the AG layout
	void planarizeFromLayout(PlanRep &PG,
							 GraphAttributes &AG);
	//compute crossing point and return if existing
	bool hasCrossing(EdgeLeg* legA, EdgeLeg* legB, DPoint& xp);
	//check if node v is a crossing of two edges with a common
	//endpoint adjacent to v, crossing is removed if flip is set
	bool checkFlipCrossing(PlanRep &PG,node v, bool flip = true);

	void postProcess(PlanRep &PG);
	void handleImprecision(PlanRep &PG);
	bool skipable(EdgeLeg* legA, EdgeLeg* legB);

private:
	//compare vectors for sorting
	int compare_vectors(const double& x1, const double& y1,
						const double& x2, const double& y2);
	//compute and return the angle defined by p-q,p-r
	double angle(DPoint p, DPoint q, DPoint r);
	//we have to save the position of the inserted crossing vertices
	//in order to compute the external face
	NodeArray<DPoint> m_crossPosition;

	//we save a list of EdgeLegs for all original edges in
	//AG
	EdgeArray< List<EdgeLeg*> > m_eLegs;


	//option settings as bits
	int m_options;

};//TopologyModule


//! Sorts EdgeLegs according to their xp distance to a reference point.
class PointComparer {
public:
	PointComparer(DPoint refPoint) : m_refPoint(refPoint) {}
	//compares the crossing points stored in the EdgeLeg
	int compare(const ListIterator<EdgeLeg*> &ep1,
		const ListIterator<EdgeLeg*> &ep2) const;
	OGDF_AUGMENT_COMPARER(ListIterator<EdgeLeg*>)

	// undefined methods to avoid automatic creation
	PointComparer &operator=(const PointComparer &);

private:
	const DPoint m_refPoint;
};//PointComparer

//! Helper class for the computation of crossings
/**
 * Represents a part of the edge between two consecutive bends (in the layout, there are no bends
 *  allowed in the representation) or crossings. There can be multiple EdgeLegs associated to one
 * copy edge in the PlanRep because of bends.
 */
class EdgeLeg
{
public:
	EdgeLeg() : m_topDown(false)
		{m_copyEdge = 0; m_xp = DPoint(0.0, 0.0);}
	EdgeLeg(edge e, int number, DPoint p1, DPoint p2) :
		m_xp(DPoint(0.0,0.0)), m_topDown(false),
		m_copyEdge(e), m_p1(p1), m_p2(p2), m_number(number)
		{}

	DPoint& start() {return m_p1;}
	DPoint& end()   {return m_p2;}
	int& number()    {return m_number;}
	edge& copyEdge() { return m_copyEdge;}

	//to avoid sorting both edgelegs and crossing points,
	//do not store a pair of them, but allow the xp to be
	//stored in the edgeleg
	DPoint m_xp;
	//we store the direction of the crossed EdgeLeg, too
	//if crossingEdgeLeg is horizontally left to right
	bool m_topDown;

	//each edgeLeg holds an entry with a ListIterator pointing to
	//its entry in a <edgeLeg*> List for an original edge
	ListIterator< EdgeLeg* > m_eIterator;

private:
	edge m_copyEdge; //the edge in the PlanRep copy corresponding to the EdgeLeg
	DPoint m_p1, m_p2;  //"Starting" and "End" point of the EdgeLeg
	int    m_number;    //the order nuumber on the edge, starting at 0

};//edgeleg


} // end namespace ogdf

#endif