Open
Graph Drawing
Framework

 v.2012.07
 

UMLGraph.h
Go to the documentation of this file.
1 /*
2  * $Revision: 2564 $
3  *
4  * last checkin:
5  * $Author: gutwenger $
6  * $Date: 2012-07-07 00:03:48 +0200 (Sa, 07. Jul 2012) $
7  ***************************************************************/
8 
44 #ifdef _MSC_VER
45 #pragma once
46 #endif
47 
48 #ifndef OGDF_UML_GRAPH_H
49 #define OGDF_UML_GRAPH_H
50 
51 
54 #include <ogdf/basic/SList.h>
55 
56 
57 namespace ogdf {
58 
60 {
61 public:
62  // construction
63 
64  // dummy default constructor (place-holder)
65  UMLGraph() : GraphAttributes(), m_pG(0) { }
66 
67  // creates UML graph in which each edge is an association
68  explicit UMLGraph(Graph &G, long initAttributes = 0);
69 
70  // destruction
71  virtual ~UMLGraph();
72 
73  //(re)initialization
74  virtual void init(Graph &G, long initAttr)
75  {
76  m_pG = &G;
77  GraphAttributes::init(G, initAttr);
78  m_hierarchyParent.init(constGraph(), 0);
79  m_upwardEdge.init(constGraph(), false);
80  }
81 
82  operator const Graph &() const { return *m_pGraph; }
83 
84  //----------------------------------------------------------------------------
85  //structural changes
86  //merge generalizations at a common superclass
87  void insertGenMergers();
88  //insert mergers per node with given edges
89  node doInsertMergers(node v, SList<edge> &inGens);
90  void undoGenMergers();
91 
92  //replace (dense) subgraphs given in list clique by
93  //inserting a center node connected to each node (=>star)
94  //and deleting all edges between nodes in clique
95  //returns center node
96  void replaceByStar(List< List<node> > &cliques);
97 
98  //undo clique replacements
99  void undoStars();
100  //boolean switches restore of all hidden edges in single clique call
101  void undoStar(node center, bool restoreAllEdges);
102 
103  //returns the size of a circular drawing for a clique around center v
104  DRect cliqueRect(node v)
105  {
106  return m_cliqueCircleSize[v];
107  }
108  DPoint cliquePos(node v)
109  {
110  return m_cliqueCirclePos[v];
111  }
112 
113  //compute circle positions for all nodes around center
114  //using the ordering given in this UMLGraph, calls
115  //ccP(List...)
116  //rectMin is a temporary solution until compaction with constraints allows stretching
117  //of rect to clique size, it gives the min(w,h) of the given fixed size rect around the clique
118  void computeCliquePosition(node center, double rectMin);//, const adjEntry &startAdj);
119  //compute positions for the nodes in adjNodes on a circle
120  //tries to keep the relative placement of the nodes in the clique
121  //rectangle (left, right,...) to avoid clique crossings of outgoing edges
122  void computeCliquePosition(List<node> &adjNodes, node center, double rectMin = -1.0);
123 
124  //allow change, but should not be declared const
125  Graph& pureGraph() const {return *m_pG;}
126 
127  //set status value
128  //void setAlign(edge e, bool b) {m_alignEdge[e] = b;}
129  //set status of edges to be specially embedded (if alignment)
130  void setUpwards(adjEntry a, bool b) {m_upwardEdge[a] = b;}
131  bool upwards(adjEntry a) const {return m_upwardEdge[a];}
132 
133  // writes attributed graph in GML format to file fileName
134  void writeGML(const char *fileName);
135 
136  // writes attributed graph in GML format to output stream os
137  void writeGML(ostream &os);
138 
139  //adjust the parent field for all nodes after insertion of
140  //mergers. If insertion is done per node via doinsert, adjust
141  //has to be called afterwards. Otherwise, insertgenmergers calls it.
142  void adjustHierarchyParents();
143 
144  //use the node position and bend position information to
145  //derive an ordering of the edges around each node
146  //this does not need to result in a correct combinatorial embedding
147  void sortEdgesFromLayout();
148 
149  //-------------------
150  //status retrieval
151  //returns true if edge was inserted during clique replacement
152  //TODO: check here how to guarantee that value is defined,
153  //edgearray is only valid if there are cliques replaced
154  bool isReplacement(edge e)
155  {
156  return m_replacementEdge[e];
157  }
158 
159  const SListPure<node> &centerNodes() {return m_centerNodes;}
160 
161  //default size of inserted clique replacement center nodes
162  void setDefaultCliqueCenterSize(double i) {m_cliqueCenterSize = max(i, 1.0);}
163  double getDefaultCliqueCenterSize() {return m_cliqueCenterSize;}
164 
165  //-------------------------------------------------------------------------
166  //modelling of association classes
168  public:
169  AssociationClass(edge e, double width = 1.0, double height = 1.0,
170  double x = 0.0, double y = 0.0)
171  : m_width(width), m_height(height), m_x(x), m_y(y), m_edge(e), m_node(0)
172  { }
173 
174  double m_width;
175  double m_height;
176  double m_x;
177  double m_y;
180  };
181  const SListPure<AssociationClass*> &assClassList() const {return m_assClassList;}
182 
183  const AssociationClass* assClass(edge e) const {return m_assClass[e];}
184 
185  //adds association class to edge e
186  //void createAssociationClass(edge e, double width = 1.0, double height = 1.0)
187  node createAssociationClass(edge e, double width = 1.0, double height = 1.0)
188  {
189  AssociationClass* ac = new AssociationClass(e, width, height);
190  m_assClass[e] = ac;
191  m_assClassList.pushBack(ac);
192  //we already insert the node here, but not the edge
193  //when we always insert this node here, we can remove the associationclass
194  //class and information later on
195  node v = m_pG->newNode();
196  m_height[v] = ac->m_height;
197  m_width[v] = ac->m_width;
198  m_associationClassModel[ac->m_edge] = v;
199  ac->m_node = v;
200  //guarantee correct angle at edge to edge connection
201  if (m_attributes & GraphAttributes::nodeType)
202  {
203  m_vType[v] = Graph::associationClass;
204  }
205  return v;
206 
207  }
208  //this modelling should only take place in the preprocessing steps
209  //of the drawing algorithms?
210  //insert representation for association class in underlying graph
211  void modelAssociationClasses()
212  {
213  SListIterator<UMLGraph::AssociationClass*> it = m_assClassList.begin();
214  while (it.valid())
215  {
216  modelAssociationClass((*it));
217  it++;
218  }//while
219  }
220  node modelAssociationClass(AssociationClass* ac)
221  {
222  node dummy = m_pG->split(ac->m_edge)->source();
223 
224  m_height[dummy] = 1; //just a dummy size
225  m_width[dummy] = 1;
226  OGDF_ASSERT(ac->m_node)
227  m_pG->newEdge(ac->m_node, dummy);
228 
229  return dummy;
230  }
231 
232  void undoAssociationClasses()
233  {
234  SListIterator<UMLGraph::AssociationClass*> it = m_assClassList.begin();
235  while (it.valid())
236  {
237  undoAssociationClass((*it));
238  it++;
239  }//while
240  }
241  //remove the modeling of the association class without removing the information
242  void undoAssociationClass(AssociationClass* ac)
243  {
244  node v = m_associationClassModel[ac->m_edge];
245  OGDF_ASSERT(v)
246  OGDF_ASSERT(v->degree() == 1)
247  if (v->degree() != 1) throw AlgorithmFailureException(afcLabel);
248  //save layout information
249  ac->m_x = x(v);
250  ac->m_y = y(v);
251 
252  //remove node and unsplit edge
253 
254  //run around the dummy node connected to v
255  adjEntry outAdj = v->firstAdj();
256  adjEntry dummyAdj = outAdj->twin();
257 
258  node dummy = dummyAdj->theNode();
259  OGDF_ASSERT(dummy->degree() == 3)
260 
261  //we do not delete the node if we already inserted it in create...
262  //because it is a part of the graph now (in contrast to the split node)
263  m_pG->delEdge(v->firstAdj()->theEdge());
264  OGDF_ASSERT(v->degree() == 0)
265 
266  m_pG->unsplit(dummy);
267  }//undoAssociationClass
268 
269 
270 
271 protected:
272 
273  node replaceByStar(List<node> &clique, NodeArray<int> &cliqueNum);
274  DRect circularBound(node center);
275 
276 private:
277 
279 
280  //information about edges that are deleted in clique processing
281  class CliqueInfo {
282  public:
283  CliqueInfo(node v, int i) : m_target(v), m_edgeIndex(i) {}
284  node m_target; //target node of deleted edge
285  int m_edgeIndex; //index of deleted edge, has to be restored
286  };
287  double m_cliqueCenterSize; //default size of inserted clique replacement center nodes
288 
290  SListPure<node> m_centerNodes; //center nodes introduced at clique replacement
291  EdgeArray<bool> m_replacementEdge; //used to mark clique replacement edges
292  //may be we can join this with edge type
293  NodeArray<DRect> m_cliqueCircleSize; //save the bounding box size of the
294  //circular drawing of the clique at center
295  NodeArray<DPoint> m_cliqueCirclePos; //save the position of the node in the
296  //circular drawing of the clique
297  //---------------------------------------------------
298  //structures for association classes
299  //may be replaced later by generic structures for different types
300  SListPure<AssociationClass*> m_assClassList; //saves all accociation classes
301  EdgeArray<AssociationClass*> m_assClass; //association class for list
302  EdgeArray<node> m_associationClassModel; //modelled classes are stored
303 
304 
305  //***************************************************
306  //the following arrays are only set and updated in insertgenmergers
307  //used to classify edges for embedding with alignment
309 
310  //used to derive edge types for alignment in PlanRepUML
311  //(same hierarchyparent => edge connects (half)brothers
312  //only set during insertgenmergers to avoid the extra computation
314 
315 };
316 
317 
318 } // end namespace ogdf
319 
320 #endif