6 * $Date: 2012-07-12 01:02:21 +0200 (Do, 12. Jul 2012) $
7 ***************************************************************/
10 * \brief Declaration of a base class for planar representations
11 * of graphs and cluster graphs.
13 * \author Karsten Klein
16 * This file is part of the Open Graph Drawing Framework (OGDF).
20 * See README.txt in the root directory of the OGDF installation for details.
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * Version 2 or 3 as published by the Free Software Foundation;
26 * see the file LICENSE.txt included in the packaging of this file
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
36 * You should have received a copy of the GNU General Public
37 * License along with this program; if not, write to the Free
38 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
39 * Boston, MA 02110-1301, USA.
41 * \see http://www.gnu.org/copyleft/gpl.html
42 ***************************************************************/
45 //PlanRep should not know about generalizations and association,
46 //but we already set types in Attributedgraph, therefore set them
53 #ifndef OGDF_PLANREP_H
54 #define OGDF_PLANREP_H
57 #include <ogdf/basic/GraphCopy.h>
58 #include <ogdf/planarity/EdgeTypePatterns.h>
59 #include <ogdf/planarity/NodeTypePatterns.h>
60 #include <ogdf/basic/Layout.h>
61 #include <ogdf/orthogonal/OrthoRep.h>
62 #include <ogdf/basic/GraphAttributes.h>
69 * \brief Planarized representations (of a connected component) of a graph.
71 * Maintains types of edges (generalization, association) and nodes,
72 * and the connected components of the graph.
74 class OGDF_EXPORT PlanRep
: public GraphCopy
77 //! Information for restoring degree-1 nodes.
78 struct Deg1RestoreInfo
80 Deg1RestoreInfo() : m_eOriginal(0), m_deg1Original(0), m_adjRef(0) { }
81 Deg1RestoreInfo(edge eOrig
, node deg1Orig
, adjEntry adjRef
)
82 : m_eOriginal(eOrig
), m_deg1Original(deg1Orig
), m_adjRef(adjRef
) { }
84 edge m_eOriginal
; //!< the original edge leading to the deg-1 node
85 node m_deg1Original
; //!< the original deg-1 node
86 adjEntry m_adjRef
; //!< the reference adjacency entry for restoring the edge
91 * \brief Creates a planarized representation of graph \a G.
93 PlanRep(const Graph
& G
);
96 * \brief Creates a planarized representation of graph \a AG.
98 PlanRep(const GraphAttributes
& AG
);
100 virtual ~PlanRep() {}
105 * @name Processing connected components
106 * Planarized representations provide a mechanism for always representing
107 * a copy of a single component of the original graph.
112 * \brief Returns the number of connected components in the original graph.
114 int numberOfCCs() const {
115 return m_nodesInCC
.size();
119 * \brief Returns the index of the current connected component (-1 if not yet initialized).
121 int currentCC() const {
126 * \brief Returns the list of (original) nodes in connected component \a i.
128 * Note that connected components are numbered 0,1,...
130 const List
<node
> &nodesInCC(int i
) const {
131 return m_nodesInCC
[i
];
135 * \brief Returns the list of (original) nodes in the current connected component.
137 const List
<node
> &nodesInCC() const {
138 return m_nodesInCC
[m_currentCC
];
142 * \brief Initializes the planarized representation for connected component \a i.
144 * This initialization is always required. After performing this initialization,
145 * the planarized representation represents a copy of the <i>i</i>-th connected
146 * component of the original graph, where connected components are numbered
154 * @name Node expansion
159 * \brief Returns the adjacency entry of a node of an expanded face.
161 * If no such entry is stored at node \a v, 0 is returned.
163 adjEntry
expandAdj(node v
) const {
164 return m_expandAdj
[v
];
167 adjEntry
& expandAdj(node v
) {
168 return m_expandAdj
[v
];
173 * @name Clique boundary
178 * Returns the adjacency entry of the first edge of the inserted boundary
179 * at a center node (original) of a clique, 0 if no boundary exists
181 adjEntry
boundaryAdj(node v
) const {
182 return m_boundaryAdj
[v
];
186 * Returns a reference to the adjacency entry of the first edge of the inserted boundary
187 * at a center node (original) of a clique, 0 if no boundary exists
189 adjEntry
& boundaryAdj(node v
){
190 return m_boundaryAdj
[v
];
193 //edge on the clique boundary, adjSource
194 void setCliqueBoundary(edge e
) {
195 setEdgeTypeOf(e
, edgeTypeOf(e
) | cliquePattern());
197 bool isCliqueBoundary(edge e
) {
198 return ((edgeTypeOf(e
) & cliquePattern()) == cliquePattern());
209 * \brief Returns the type of node \a v.
210 * @param v is a node in the planarized representation.
212 Graph::NodeType
typeOf(node v
) const {
217 * \brief Returns a reference to the type of node \a v.
218 * @param v is a node in the planarized representation.
220 Graph::NodeType
& typeOf(node v
) {
225 * \brief Returns true if the node represents a "real" object in the original graph.
227 * \todo It is necessary to check for several different possible types.
228 * This should be solved by combining representation types (vertex, dummy,...)
229 * with semantic types (class, interface,...) within GraphAttributes;
230 * we then can return to vertex only.
232 inline bool isVertex(node v
)
234 return ( (typeOf(v
) == Graph::vertex
) ||
235 (typeOf(v
) == Graph::associationClass
));
239 * \brief Returns the extended node type of \a v.
240 * @param v is a node in the planarized representation.
242 nodeType
nodeTypeOf(node v
)
244 return m_nodeTypes
[v
];
248 * \brief Classifies node \a v as a crossing.
249 * @param v is a node in the planarized representation.
251 void setCrossingType(node v
)
253 m_nodeTypes
[v
] |= ntTerCrossing
<< ntoTertiary
;
257 * \brief Returns true iff node \a v is classified as a crossing.
258 * @param v is a node in the planarized representation.
260 bool isCrossingType(node v
)
262 return (m_nodeTypes
[v
] &= (ntTerCrossing
<< ntoTertiary
)) != 0;
272 * \brief Returns the type of edge \a e.
273 * @param e is an edge in the planarized representation.
275 EdgeType
typeOf(edge e
) const {
280 * \brief Returns a reference to the type of edge \a e.
281 * @param e is an edge in the planarized representation.
283 EdgeType
& typeOf(edge e
) {
288 * \brief Returns a reference to the type of original edge \a e.
289 * @param e is an edge in the original graph.
291 edgeType
& oriEdgeTypes(edge e
)
293 return m_oriEdgeTypes
[e
];
297 * \brief Returns the new type field of \a e.
298 * @param e is an edge in the planarized representation.
300 edgeType
edgeTypeOf(edge e
)
302 return m_edgeTypes
[e
];
306 * \brief Returns a reference to the new type field of \a e.
307 * @param e is an edge in the planarized representation.
309 edgeType
& edgeTypes(edge e
)
311 return m_edgeTypes
[e
];
315 * \brief Sets the new type field of edge \a e to \a et.
316 * @param e is an edge in the planarized representation.
317 * @param et is the type assigned to \a e.
319 void setEdgeTypeOf(edge e
, edgeType et
)
325 * \brief Set both type values of \a e at once.
327 * This is a temporary solution that sets both type values; this way, all
328 * additional edge types in the new field are lost.
329 * @param e is an edge in the planarized representation.
330 * @param et is the type assigned to \a e.
332 void setType(edge e
, EdgeType et
)
337 case Graph::association
: m_edgeTypes
[e
] = etcPrimAssociation
;break;
338 case Graph::generalization
: m_edgeTypes
[e
] = etcPrimGeneralization
;
340 case Graph::dependency
: m_edgeTypes
[e
] = etcPrimDependency
; break;
345 //-------------------------------------------------------------------------
347 //to set or check edge types use the pattern function in the private section
349 //-------------------
350 //primary level types
352 //! Returns true iff edge \a e is classified as generalization.
353 bool isGeneralization(edge e
) {
354 bool check
= (((m_edgeTypes
[e
] & etpPrimary
) & etcPrimGeneralization
) == etcPrimGeneralization
);
358 //! Classifies edge \a e as generalization (primary type).
359 void setGeneralization(edge e
) {
360 setPrimaryType(e
, etcPrimGeneralization
);
362 //preliminary set old array too
363 m_eType
[e
] = generalization
; //can be removed if edgetypes work properly
366 //! Returns true iff edge \a e is classified as dependency.
367 bool isDependency(edge e
) {
368 bool check
= (((m_edgeTypes
[e
] & etpPrimary
) & etcPrimDependency
) == etcPrimDependency
);
372 //! Classifies edge \a e as dependency (primary type).
373 void setDependency(edge e
) {
374 setPrimaryType(e
, etcPrimDependency
);
376 //preliminary set old array too
377 m_eType
[e
] = dependency
; //can be removed if edgetypes work properly
380 //! Classifies edge \a e as association (primary type).
381 void setAssociation(edge e
) {
382 setPrimaryType(e
, etcPrimAssociation
);
384 //preliminary set old array too
385 m_eType
[e
] = association
; //can be removed if edgetypes work properly
391 //in contrast to setsecondarytype: do not delete old value
393 //! Classifies edge \a e as expansion edge (secondary type).
394 void setExpansion(edge e
) {
395 m_edgeTypes
[e
] |= expansionPattern();
397 //preliminary set old array too
398 m_expansionEdge
[e
] = 1;//can be removed if edgetypes work properly
401 //! Returns true iff edge \a e is classified as expansion edge.
402 bool isExpansion(edge e
) {
403 return ((m_edgeTypes
[e
] & expansionPattern()) == expansionPattern());
406 //should add things like cluster and clique boundaries that need rectangle shape
408 //! Returns true iff edge \a e is a clique boundary.
409 bool isBoundary(edge e
) {
410 return isCliqueBoundary(e
); }
415 //! Classifies edge \a e as connection at an association class (tertiary type).
416 void setAssClass(edge e
)
418 m_edgeTypes
[e
] |= assClassPattern();
421 //! Returns true iff edge \a e is classified as connection at an association class.
422 bool isAssClass(edge e
)
424 return ((m_edgeTypes
[e
] & assClassPattern()) == assClassPattern());
431 //! Classifies edge \a e as connection between hierarchy neighbours (fourth level type).
432 void setBrother(edge e
) {
433 m_edgeTypes
[e
] |= brotherPattern();
436 //! Classifies edge \a e as connection between ... (fourth level type).
437 void setHalfBrother(edge e
) {
438 m_edgeTypes
[e
] |= halfBrotherPattern();
441 //! Returns true if edge \a e is classified as brother.
442 bool isBrother(edge e
) {
443 return ( (((m_edgeTypes
[e
] & etpFourth
) & brotherPattern())>> etoFourth
) == etcBrother
);
446 //! Returns true if edge \a e is classified as half-brother.
447 bool isHalfBrother(edge e
) {
448 return ( (((m_edgeTypes
[e
] & etpFourth
) & halfBrotherPattern())>> etoFourth
) == etcHalfBrother
);
454 edgeType
edgeTypeAND(edge e
, edgeType et
) {m_edgeTypes
[e
] &= et
; return m_edgeTypes
[e
];}
456 edgeType
edgeTypeOR(edge e
, edgeType et
) {m_edgeTypes
[e
] |= et
; return m_edgeTypes
[e
];}
458 //set primary edge type of edge e to primary edge type in et
459 //deletes old primary value
460 void setPrimaryType(edge e
, edgeType et
) {
461 m_edgeTypes
[e
] &= 0xfffffff0;
462 m_edgeTypes
[e
] |= (etpPrimary
& et
);
465 void setSecondaryType(edge e
, edgeType et
) {
466 m_edgeTypes
[e
] &= 0xffffff0f;
467 m_edgeTypes
[e
] |= (etpSecondary
& ( et
<< etoSecondary
));
470 //sets primary type to bitwise AND of et's primary value and old value
471 edgeType
edgeTypePrimaryAND(edge e
, edgeType et
) {m_edgeTypes
[e
] &= (etpAll
& et
); return m_edgeTypes
[e
];}
473 //sets primary type to bitwise OR of et's primary value and old value
474 edgeType
edgeTypePrimaryOR(edge e
, edgeType et
) {m_edgeTypes
[e
] |= et
; return m_edgeTypes
[e
];}
476 //set user defined type locally
477 void setUserType(edge e
, edgeType et
)
479 OGDF_ASSERT( et
< 147);
480 m_edgeTypes
[e
] |= (et
<< etoUser
);
483 bool isUserType(edge e
, edgeType et
)
485 OGDF_ASSERT( et
< 147);
486 return ( (m_edgeTypes
[e
] & (et
<< etoUser
)) == (et
<< etoUser
));
493 //this is pure nonsense, cause we have uml-edgetype and m_etype, and should be able to
494 //use them with different types, but as long as they arent used correctly (switch instead of xor),
495 //use this function to return if e is expansionedge
496 //if it is implemented correctly later, delete the array and return m_etype == Graph::expand
497 //(the whole function then is obsolete, cause you can check it directly, but for convenience...)
498 //should use genexpand, nodeexpand, dissect instead of bool
499 void setExpansionEdge(edge e
, int expType
) {
500 m_expansionEdge
[e
] = expType
;
503 bool isExpansionEdge(edge e
) const {
504 return (m_expansionEdge
[e
] > 0);
507 int expansionType(edge e
) const { return m_expansionEdge
[e
]; }
509 //precondition normalized
510 bool isDegreeExpansionEdge(edge e
) const {
511 //return (m_eType[e] == Graph::expand);
512 return ( m_expansionEdge
[e
] == 2);
518 * @name Access to attributes in original graph
519 * These methods provide easy access to attributes of original nodes and
525 //! Gives access to the node array of the widths of original nodes.
526 const NodeArray
<double> &widthOrig() const {
527 return m_pGraphAttributes
->width();
530 //! Returns the width of original node \a v.
531 double widthOrig(node v
) const {
532 return m_pGraphAttributes
->width(v
);
535 //! Gives access to the node array of the heights of original nodes.
536 const NodeArray
<double> &heightOrig() const {
537 return m_pGraphAttributes
->height();
540 //! Returns the height of original node \a v.
541 double heightOrig(node v
) const {
542 return m_pGraphAttributes
->height(v
);
545 //! Returns the type of original edge \a e.
546 EdgeType
typeOrig(edge e
) const {
547 return m_pGraphAttributes
->type(e
);
550 //! Returns the graph attributes of the original graph (the pointer may be 0).
551 const GraphAttributes
&getGraphAttributes() const {
552 return *m_pGraphAttributes
;
557 * @name Structural alterations
561 // Expands nodes with degree > 4 and merge nodes for generalizations
562 void expand(bool lowDegreeExpand
= false);
564 void expandLowDegreeVertices(OrthoRep
&OR
);
566 void collapseVertices(const OrthoRep
&OR
, Layout
&drawing
);
568 void removeCrossing(node v
); //removes the crossing at node v
570 //model a boundary around a star subgraph centered at center
571 //and keep external face information (outside the clique
572 void insertBoundary(node center
, adjEntry
& adjExternal
);
577 * @name Extension of methods defined by GraphCopys
581 //! Splits edge \a e.
582 virtual edge
split(edge e
);
585 //returns node which was expanded using v
586 node
expandedNode(node v
) const { return m_expandedNode
[v
]; }
588 void setExpandedNode(node v
, node w
) { m_expandedNode
[v
] = w
; }
593 * @name Creation of new nodes and edges
598 * \brief Creates a new node with node type \a vType in the planarized representation.
599 * @param vOrig becomes the original node of the new node.
600 * @param vType becomes the type of the new node.
602 node
newCopy(node vOrig
, Graph::NodeType vType
);
605 * \brief Creates a new edge in the planarized representation.
606 * @param v is the source node of the new edge.
607 * @param adjAfter is the adjacency entry at the target node, after which the
608 * new edge is inserted.
609 * @param eOrig becomes the original edge of the new edge.
611 edge
newCopy(node v
, adjEntry adjAfter
, edge eOrig
);
614 * \brief Creates a new edge in the planarized representation while updating the embedding \a E.
615 * @param v is the source node of the new edge.
616 * @param adjAfter is the adjacency entry at the target node, after which the
617 * new edge is inserted.
618 * @param eOrig becomes the original edge of the new edge.
619 * @param E is an embedding of the planarized representation.
621 edge
newCopy(node v
, adjEntry adjAfter
, edge eOrig
, CombinatorialEmbedding
&E
);
630 // embeds current copy
633 // removes all crossing nodes which are actually only two "touching" edges
634 void removePseudoCrossings();
636 // re-inserts edge eOrig by "crossing" the edges in crossedEdges;
637 // splits each edge in crossedEdges
638 // Precond.: eOrig is an edge in the original graph,
639 // the edges in crossedEdges are in this graph
640 void insertEdgePath(edge eOrig
, const SList
<adjEntry
> &crossedEdges
);
642 // same as insertEdgePath, but assumes that the graph is embedded
643 void insertEdgePathEmbedded(
645 CombinatorialEmbedding
&E
,
646 const SList
<adjEntry
> &crossedEdges
);
648 // removes the complete edge path for edge eOrig
649 // Precond.: eOrig s an edge in the original graph
650 void removeEdgePathEmbedded(CombinatorialEmbedding
&E
,
652 FaceSetPure
&newFaces
) {
653 GraphCopy::removeEdgePathEmbedded(E
,eOrig
,newFaces
);
656 //! Inserts crossings between two copy edges.
658 * This method is used in TopologyModule.
660 * Let \a crossingEdge = (\a a, \a b) and \a crossedEdge = (\a v, \a w).
661 * Then \a crossedEdge is split creating two edges \a crossedEdge = (\a v, \a u)
662 * and (\a u, \a w), \a crossingEdge is removed and replaced by two new edges
663 * \a e1 = (\a a, \a u) and \a e1 = (\a u, \a b).
664 * Finally it sets \a crossingEdge to \a e2 and returns (\a u, \a w).
666 * @param crossingEdge is the edge that gets split.
667 * @param crossedEdge is the edge that is replaced by two new edges.
668 * @param topDown is used as follows: If set to true, \a crossingEdge will cross
669 * \a crossedEdge from right to left, otherwise from left to right.
678 * @name Degree-1 nodes
679 * These methods realize a mechanism for temporarily removing degree-1 nodes.
684 * \brief Removes all marked degree-1 nodes from the graph copy and stores restore information in \a S.
685 * @param S returns the restore information required by restoreDeg1Nodes().
686 * @param mark defines which nodes are marked for removal; all nodes \a v with
687 * <I>mark</I>[<I>v</I>]=<B>true</B> are removed.
688 * \pre Only nodes with degree 1 may be marked.
690 void removeDeg1Nodes(Stack
<Deg1RestoreInfo
> &S
, const NodeArray
<bool> &mark
);
693 * \brief Restores degree-1 nodes previously removed with removeDeg1Nodes().
694 * @param S contains the restore information.
695 * @param deg1s returns the list of newly created nodes in the copy.
697 void restoreDeg1Nodes(Stack
<Deg1RestoreInfo
> &S
, List
<node
> °1s
);
703 int m_currentCC
; //!< The index of the current component.
704 int m_numCC
; //!< The number of components in the original graph.
706 Array
<List
<node
> > m_nodesInCC
; //!< The list of original nodes in each component.
708 const GraphAttributes
* m_pGraphAttributes
; //!< Pointer to graph attributes of original graph.
713 //set the type of eCopy according to the type of eOrig
714 //should be virtual if PlanRepUML gets its own
715 void setCopyType(edge eCopy
, edge eOrig
);
717 //helper to cope with the edge types, shifting to the right place
718 edgeType
generalizationPattern() {return etcPrimGeneralization
;}
719 edgeType
associationPattern() {return etcPrimAssociation
;}
720 edgeType
expansionPattern() {return etcSecExpansion
<< etoSecondary
;}
721 edgeType
assClassPattern() {return etcAssClass
<< etoTertiary
;}
722 edgeType
brotherPattern() {return etcBrother
<< etoFourth
;}
723 edgeType
halfBrotherPattern() {return etcHalfBrother
<< etoFourth
;}
724 edgeType
cliquePattern() {return etcSecClique
<< etoSecondary
;} //boundary
727 void removeUnnecessaryCrossing(
733 //--------------------------------------------------------------------------
735 NodeArray
<NodeType
> m_vType
; //!< Simple node types.
737 NodeArray
<nodeType
> m_nodeTypes
; //!< Node types for extended semantic information.
739 NodeArray
<node
> m_expandedNode
; //!< For all expansion nodes, save expanded node.
740 NodeArray
<adjEntry
> m_expandAdj
;
742 //clique handling: We save an adjEntry of the first edge of an inserted
743 //boundary around a clique at its center v
744 NodeArray
<adjEntry
> m_boundaryAdj
;
746 //zusammenlegbare Typen
747 EdgeArray
<int> m_expansionEdge
; //1 genmerge, 2 degree (2 highdegree, 3 lowdegree)
748 EdgeArray
<EdgeType
> m_eType
;
750 //m_edgeTypes stores semantic edge type information on several levels:
751 //primary type: generalization, association,...
752 //secondary type: merger,...
753 //tertiary type: vertical in hierarchy, inner, outer, ...
754 //fourth type: neighbour relation (brother, cousin in hierarchy)
755 //user types: user defined for local changes
756 EdgeArray
<edgeType
> m_edgeTypes
; //store all type information
758 //workaround fuer typsuche in insertedgepathembed
759 //speichere kopietyp auf originalen
760 //maybe it's enough to set gen/ass without extra array
761 EdgeArray
<edgeType
> m_oriEdgeTypes
;
763 EdgeArray
<edge
> m_eAuxCopy
; // auxiliary (GraphCopy::initByNodes())
767 } // end namespace ogdf