1 /** \file 2 * \brief Declaration of a base class for planar representations 3 * of graphs and cluster graphs. 4 * 5 * \author Karsten Klein, 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 34 // PlanRep should not know about generalizations and association, 35 // but we already set types in Attributedgraph, therefore set them 36 // in PlanRep, too 37 38 #pragma once 39 40 #include <ogdf/basic/GraphCopy.h> 41 #include <ogdf/planarity/EdgeTypePatterns.h> 42 #include <ogdf/planarity/NodeTypePatterns.h> 43 #include <ogdf/basic/Layout.h> 44 #include <ogdf/basic/GridLayout.h> 45 46 47 namespace ogdf { 48 49 class OrthoRep; 50 51 52 //! Planarized representations (of a connected component) of a graph. 53 /** 54 * @ingroup plan-rep 55 * 56 * Maintains types of edges (generalization, association) and nodes, 57 * and the connected components of the graph. 58 */ 59 class OGDF_EXPORT PlanRep : public GraphCopy 60 { 61 public: 62 //! Information for restoring degree-1 nodes. 63 struct Deg1RestoreInfo 64 { Deg1RestoreInfoDeg1RestoreInfo65 Deg1RestoreInfo() : m_eOriginal(nullptr), m_deg1Original(nullptr), m_adjRef(nullptr) { } Deg1RestoreInfoDeg1RestoreInfo66 Deg1RestoreInfo(edge eOrig, node deg1Orig, adjEntry adjRef) 67 : m_eOriginal(eOrig), m_deg1Original(deg1Orig), m_adjRef(adjRef) { } 68 69 edge m_eOriginal; //!< the original edge leading to the deg-1 node 70 node m_deg1Original; //!< the original deg-1 node 71 adjEntry m_adjRef; //!< the reference adjacency entry for restoring the edge 72 }; 73 74 75 //@{ 76 //! Creates a planarized representation of graph \p G. 77 explicit PlanRep(const Graph& G); 78 79 //! Creates a planarized representation of graph \p AG. 80 explicit PlanRep(const GraphAttributes& AG); 81 ~PlanRep()82 virtual ~PlanRep() { } 83 84 //@} 85 86 /** 87 * @name Processing connected components 88 * Planarized representations provide a mechanism for always representing 89 * a copy of a single component of the original graph. 90 */ 91 //@{ 92 93 //! Returns the number of connected components in the original graph. numberOfCCs()94 int numberOfCCs() const { 95 return m_ccInfo.numberOfCCs(); 96 } 97 98 //! Returns the index of the current connected component (-1 if not yet initialized). currentCC()99 int currentCC() const { 100 return m_currentCC; 101 } 102 103 //! Returns the connected components info structure. ccInfo()104 const CCsInfo &ccInfo() const { return m_ccInfo; } 105 106 //! Returns the number of nodes in the current connected component. numberOfNodesInCC()107 int numberOfNodesInCC() const { return numberOfNodesInCC(m_currentCC); } 108 109 //! Returns the number of nodes in connected component \p cc. numberOfNodesInCC(int cc)110 int numberOfNodesInCC(int cc) const { 111 return stopNode(cc) - startNode(cc); 112 } 113 114 //! Returns node \p i in the list of all original nodes. v(int i)115 node v(int i) const { return m_ccInfo.v(i); } 116 117 //! Returns edge \p i in the list of all original edges. e(int i)118 edge e(int i) const { return m_ccInfo.e(i); } 119 120 //! Returns the index of the first node in this connected component. startNode()121 int startNode() const { return m_ccInfo.startNode(m_currentCC); } 122 123 //! Returns the index of the first node in connected component \p cc. startNode(int cc)124 int startNode(int cc) const { return m_ccInfo.startNode(cc); } 125 126 //! Returns the index of (one past) the last node in this connected component. stopNode()127 int stopNode() const { return m_ccInfo.stopNode(m_currentCC); } 128 129 //! Returns the index of (one past) the last node in connected component \p cc. stopNode(int cc)130 int stopNode(int cc) const { return m_ccInfo.stopNode(cc); } 131 132 //! Returns the index of the first edge in this connected component. startEdge()133 int startEdge() const { return m_ccInfo.startEdge(m_currentCC); } 134 135 //! Returns the index of (one past) the last edge in this connected component. stopEdge()136 int stopEdge() const { return m_ccInfo.stopEdge(m_currentCC); } 137 138 //! Initializes the planarized representation for connected component \p cc. 139 /** 140 * This initialization is always required. After performing this initialization, 141 * the planarized representation represents a copy of the connected 142 * component \p cc of the original graph, where connected components are numbered 143 * 0,1,2,... 144 */ 145 void initCC(int cc); 146 147 //@} 148 149 /** 150 * @name Node expansion 151 */ 152 //@{ 153 154 /** 155 * \brief Returns the adjacency entry of a node of an expanded face. 156 * 157 * If no such entry is stored at node \p v, 0 is returned. 158 */ expandAdj(node v)159 adjEntry expandAdj(node v) const { 160 return m_expandAdj[v]; 161 } 162 expandAdj(node v)163 adjEntry& expandAdj(node v) { 164 return m_expandAdj[v]; 165 } 166 167 //@} 168 /** 169 * @name Clique boundary 170 */ 171 //@{ 172 173 /** 174 * Returns the adjacency entry of the first edge of the inserted boundary 175 * at a center node (original) of a clique, 0 if no boundary exists 176 */ boundaryAdj(node v)177 adjEntry boundaryAdj(node v) const { 178 return m_boundaryAdj[v]; 179 } 180 181 /** 182 * Returns a reference to the adjacency entry of the first edge of the inserted boundary 183 * at a center node (original) of a clique, 0 if no boundary exists 184 */ boundaryAdj(node v)185 adjEntry& boundaryAdj(node v){ 186 return m_boundaryAdj[v]; 187 } 188 189 //edge on the clique boundary, adjSource setCliqueBoundary(edge e)190 void setCliqueBoundary(edge e) { 191 setEdgeTypeOf(e, edgeTypeOf(e) | cliquePattern()); 192 } isCliqueBoundary(edge e)193 bool isCliqueBoundary(edge e) const { 194 return (edgeTypeOf(e) & cliquePattern()) == cliquePattern(); 195 } 196 197 198 //@} 199 /** 200 * @name Node types 201 */ 202 //@{ 203 204 /** 205 * \brief Returns the type of node \p v. 206 * @param v is a node in the planarized representation. 207 */ typeOf(node v)208 Graph::NodeType typeOf(node v) const { 209 return m_vType[v]; 210 } 211 212 /** 213 * \brief Returns a reference to the type of node \p v. 214 * @param v is a node in the planarized representation. 215 */ typeOf(node v)216 Graph::NodeType& typeOf(node v) { 217 return m_vType[v]; 218 } 219 220 /** 221 * \brief Returns true if the node represents a "real" object in the original graph. 222 * 223 * \todo It is necessary to check for several different possible types. 224 * This should be solved by combining representation types (vertex, dummy,...) 225 * with semantic types (class, interface,...) within GraphAttributes; 226 * we then can return to vertex only. 227 */ isVertex(node v)228 inline bool isVertex(node v) const 229 { 230 return typeOf(v) == Graph::NodeType::vertex 231 || typeOf(v) == Graph::NodeType::associationClass; 232 } 233 234 /** 235 * \brief Returns the extended node type of \p v. 236 * @param v is a node in the planarized representation. 237 */ nodeTypeOf(node v)238 nodeType nodeTypeOf(node v) 239 { 240 return m_nodeTypes[v]; 241 } 242 243 /** 244 * \brief Classifies node \p v as a crossing. 245 * @param v is a node in the planarized representation. 246 */ setCrossingType(node v)247 void setCrossingType(node v) 248 { 249 m_nodeTypes[v] |= UMLNodeTypeConstants::TerCrossing << UMLNodeTypeOffsets::Tertiary; 250 } 251 252 /** 253 * \brief Returns true iff node \p v is classified as a crossing. 254 * @param v is a node in the planarized representation. 255 */ isCrossingType(node v)256 bool isCrossingType(node v) const 257 { 258 return (m_nodeTypes[v] & (UMLNodeTypeConstants::TerCrossing << UMLNodeTypeOffsets::Tertiary)) != 0; 259 } 260 261 //@} 262 /** 263 * @name Edge types 264 */ 265 //@{ 266 267 /** 268 * \brief Returns the type of edge \p e. 269 * @param e is an edge in the planarized representation. 270 */ typeOf(edge e)271 EdgeType typeOf(edge e) const { 272 return m_eType[e]; 273 } 274 275 /** 276 * \brief Returns a reference to the type of edge \p e. 277 * @param e is an edge in the planarized representation. 278 */ typeOf(edge e)279 EdgeType& typeOf(edge e) { 280 return m_eType[e]; 281 } 282 283 /** 284 * \brief Returns a reference to the type of original edge \p e. 285 * @param e is an edge in the original graph. 286 */ oriEdgeTypes(edge e)287 edgeType& oriEdgeTypes(edge e) 288 { 289 return m_oriEdgeTypes[e]; 290 } 291 292 /** 293 * \brief Returns the new type field of \p e. 294 * @param e is an edge in the planarized representation. 295 */ edgeTypeOf(edge e)296 edgeType edgeTypeOf(edge e) const 297 { 298 return m_edgeTypes[e]; 299 } 300 301 /** 302 * \brief Returns a reference to the new type field of \p e. 303 * @param e is an edge in the planarized representation. 304 */ edgeTypes(edge e)305 edgeType& edgeTypes(edge e) 306 { 307 return m_edgeTypes[e]; 308 } 309 310 /** 311 * \brief Sets the new type field of edge \p e to \p et. 312 * @param e is an edge in the planarized representation. 313 * @param et is the type assigned to \p e. 314 */ setEdgeTypeOf(edge e,edgeType et)315 void setEdgeTypeOf(edge e, edgeType et) 316 { 317 m_edgeTypes[e] = et; 318 } 319 320 /** 321 * \brief Set both type values of \p e at once. 322 * 323 * This is a temporary solution that sets both type values; this way, all 324 * additional edge types in the new field are lost. 325 * @param e is an edge in the planarized representation. 326 * @param et is the type assigned to \p e. 327 */ setType(edge e,EdgeType et)328 void setType(edge e, EdgeType et) 329 { 330 m_eType[e] = et; 331 switch (et) 332 { 333 case Graph::EdgeType::association: m_edgeTypes[e] = static_cast<edgeType>(UMLEdgeTypeConstants::PrimAssociation);break; 334 case Graph::EdgeType::generalization: m_edgeTypes[e] = static_cast<edgeType>(UMLEdgeTypeConstants::PrimGeneralization); 335 break; 336 case Graph::EdgeType::dependency: m_edgeTypes[e] = static_cast<edgeType>(UMLEdgeTypeConstants::PrimDependency); break; 337 default: break; 338 } 339 } 340 341 // new edge types 342 // to set or check edge types use the pattern function in the private section 343 344 // primary level types 345 346 //! Returns true iff edge \p e is classified as generalization. isGeneralization(edge e)347 bool isGeneralization(edge e) const { 348 bool check = (((m_edgeTypes[e] & UMLEdgeTypePatterns::Primary) & UMLEdgeTypeConstants::PrimGeneralization) == UMLEdgeTypeConstants::PrimGeneralization); 349 return check; 350 } 351 352 //! Classifies edge \p e as generalization (primary type). setGeneralization(edge e)353 void setGeneralization(edge e) { 354 setPrimaryType(e, UMLEdgeTypeConstants::PrimGeneralization); 355 356 //preliminary set old array too 357 m_eType[e] = EdgeType::generalization; //can be removed if edgetypes work properly 358 } 359 360 //! Returns true iff edge \p e is classified as dependency. isDependency(edge e)361 bool isDependency(edge e) const { 362 bool check = (((m_edgeTypes[e] & UMLEdgeTypePatterns::Primary) & UMLEdgeTypeConstants::PrimDependency) == UMLEdgeTypeConstants::PrimDependency); 363 return check; 364 } 365 366 //! Classifies edge \p e as dependency (primary type). setDependency(edge e)367 void setDependency(edge e) { 368 setPrimaryType(e, UMLEdgeTypeConstants::PrimDependency); 369 370 //preliminary set old array too 371 m_eType[e] = EdgeType::dependency; //can be removed if edgetypes work properly 372 } 373 374 //! Classifies edge \p e as association (primary type). setAssociation(edge e)375 void setAssociation(edge e) { 376 setPrimaryType(e, UMLEdgeTypeConstants::PrimAssociation); 377 378 //preliminary set old array too 379 m_eType[e] = EdgeType::association; //can be removed if edgetypes work properly 380 } 381 382 //second level types 383 384 //in contrast to setsecondarytype: do not delete old value 385 386 //! Classifies edge \p e as expansion edge (secondary type). setExpansion(edge e)387 void setExpansion(edge e) { 388 m_edgeTypes[e] |= expansionPattern(); 389 390 //preliminary set old array too 391 m_expansionEdge[e] = 1;//can be removed if edgetypes work properly 392 } 393 394 //! Returns true iff edge \p e is classified as expansion edge. isExpansion(edge e)395 bool isExpansion(edge e) const { 396 return (m_edgeTypes[e] & expansionPattern()) == expansionPattern(); 397 } 398 399 //should add things like cluster and clique boundaries that need rectangle shape 400 401 //! Returns true iff edge \p e is a clique boundary. isBoundary(edge e)402 bool isBoundary(edge e) const { 403 return isCliqueBoundary(e); 404 } 405 406 //tertiary types 407 408 //! Classifies edge \p e as connection at an association class (tertiary type). setAssClass(edge e)409 void setAssClass(edge e) 410 { 411 m_edgeTypes[e] |= assClassPattern(); 412 } 413 414 //! Returns true iff edge \p e is classified as connection at an association class. isAssClass(edge e)415 bool isAssClass(edge e) const 416 { 417 return (m_edgeTypes[e] & assClassPattern()) == assClassPattern(); 418 } 419 420 //fourth level types 421 422 //! Classifies edge \p e as connection between hierarchy neighbours (fourth level type). setBrother(edge e)423 void setBrother(edge e) { 424 m_edgeTypes[e] |= brotherPattern(); 425 } 426 427 //! Classifies edge \p e as connection between ... (fourth level type). setHalfBrother(edge e)428 void setHalfBrother(edge e) { 429 m_edgeTypes[e] |= halfBrotherPattern(); 430 } 431 432 //! Returns true if edge \p e is classified as brother. isBrother(edge e)433 bool isBrother(edge e) const { 434 return ( (m_edgeTypes[e] & UMLEdgeTypePatterns::Fourth & brotherPattern()) >> UMLEdgeTypeOffsets::Fourth) == UMLEdgeTypeConstants::Brother; 435 } 436 437 //! Returns true if edge \p e is classified as half-brother. isHalfBrother(edge e)438 bool isHalfBrother(edge e) const { 439 return ( (m_edgeTypes[e] & UMLEdgeTypePatterns::Fourth & halfBrotherPattern()) >> UMLEdgeTypeOffsets::Fourth) == UMLEdgeTypeConstants::HalfBrother; 440 } 441 442 //set generic types 443 444 //! Sets type of edge \p e to current type (bitwise) AND \p et. edgeTypeAND(edge e,edgeType et)445 edgeType edgeTypeAND(edge e, edgeType et) {m_edgeTypes[e] &= et; return m_edgeTypes[e];} 446 447 //! Sets type of edge \p e to current type (bitwise) OR \p et. edgeTypeOR(edge e,edgeType et)448 edgeType edgeTypeOR(edge e, edgeType et) {m_edgeTypes[e] |= et; return m_edgeTypes[e];} 449 450 //! Sets primary edge type of edge \p e to primary edge type in \p et (deletes old primary value). setPrimaryType(edge e,edgeType et)451 void setPrimaryType(edge e, edgeType et) { 452 m_edgeTypes[e] &= 0xfffffff0; 453 m_edgeTypes[e] |= (UMLEdgeTypePatterns::Primary & et); 454 } 455 456 //! Sets primary edge type of edge \p e to primary edge type in \p et (deletes old primary value). setPrimaryType(edge e,UMLEdgeTypeConstants et)457 void setPrimaryType(edge e, UMLEdgeTypeConstants et) { 458 setPrimaryType(e, static_cast<edgeType>(et)); 459 } 460 461 //! Sets secondary edge type of edge \p e to primary edge type in \p et. setSecondaryType(edge e,edgeType et)462 void setSecondaryType(edge e, edgeType et) { 463 m_edgeTypes[e] &= 0xffffff0f; 464 m_edgeTypes[e] |= (UMLEdgeTypePatterns::Secondary & ( et << UMLEdgeTypeOffsets::Secondary)); 465 } 466 467 //! Sets primary type of \p e to bitwise AND of \p et's primary value and old value. edgeTypePrimaryAND(edge e,edgeType et)468 edgeType edgeTypePrimaryAND(edge e, edgeType et) {m_edgeTypes[e] &= (UMLEdgeTypePatterns::All & et); return m_edgeTypes[e];} 469 470 //! Sets primary type of \p e to bitwise OR of \p et's primary value and old value. edgeTypePrimaryOR(edge e,edgeType et)471 edgeType edgeTypePrimaryOR(edge e, edgeType et) {m_edgeTypes[e] |= et; return m_edgeTypes[e];} 472 473 //! Sets user defined type locally. setUserType(edge e,edgeType et)474 void setUserType(edge e, edgeType et) 475 { 476 OGDF_ASSERT( et < 147); 477 m_edgeTypes[e] |= (et << UMLEdgeTypeOffsets::User); 478 } 479 480 //! Returns user defined type. isUserType(edge e,edgeType et)481 bool isUserType(edge e, edgeType et) const 482 { 483 OGDF_ASSERT( et < 147); 484 return (m_edgeTypes[e] & (et << UMLEdgeTypeOffsets::User)) == (et << UMLEdgeTypeOffsets::User); 485 } 486 487 // old edge types 488 489 //this is pure nonsense, cause we have uml-edgetype and m_etype, and should be able to 490 //use them with different types, but as long as they arent used correctly (switch instead of xor), 491 //use this function to return if e is expansionedge 492 //if it is implemented correctly later, delete the array and return m_etype == Graph::expand 493 //(the whole function then is obsolete, cause you can check it directly, but for convenience...) 494 //should use genexpand, nodeexpand, dissect instead of bool 495 496 //! Sets the expansion edge type of \p e to \p expType. setExpansionEdge(edge e,int expType)497 void setExpansionEdge(edge e, int expType) { 498 m_expansionEdge[e] = expType; 499 } 500 501 //! Returns if \p e is an expansion edge. isExpansionEdge(edge e)502 bool isExpansionEdge(edge e) const { 503 return m_expansionEdge[e] > 0; 504 } 505 506 //! Returns the expansion edge type of \p e. expansionType(edge e)507 int expansionType(edge e) const { return m_expansionEdge[e]; } 508 509 //precondition normalized 510 //! Returns if \p e is a degree expansion edge. isDegreeExpansionEdge(edge e)511 bool isDegreeExpansionEdge(edge e) const { 512 #if 0 513 return (m_eType[e] == Graph::expand); 514 #else 515 return m_expansionEdge[e] == 2; 516 #endif 517 } 518 519 520 //@} 521 /** 522 * @name Access to attributes in original graph 523 * These methods provide easy access to attributes of original nodes and 524 * edges. 525 */ 526 //@{ 527 528 529 //! Gives access to the node array of the widths of original nodes. widthOrig()530 const NodeArray<double> &widthOrig() const { 531 OGDF_ASSERT(m_pGraphAttributes != nullptr); 532 return m_pGraphAttributes->width(); 533 } 534 535 //! Returns the width of original node \p v. widthOrig(node v)536 double widthOrig(node v) const { 537 OGDF_ASSERT(m_pGraphAttributes != nullptr); 538 return m_pGraphAttributes->width(v); 539 } 540 541 //! Gives access to the node array of the heights of original nodes. heightOrig()542 const NodeArray<double> &heightOrig() const { 543 OGDF_ASSERT(m_pGraphAttributes != nullptr); 544 return m_pGraphAttributes->height(); 545 } 546 547 //! Returns the height of original node \p v. heightOrig(node v)548 double heightOrig(node v) const { 549 OGDF_ASSERT(m_pGraphAttributes != nullptr); 550 return m_pGraphAttributes->height(v); 551 } 552 553 //! Returns the type of original edge \p e. typeOrig(edge e)554 EdgeType typeOrig(edge e) const { 555 OGDF_ASSERT(m_pGraphAttributes != nullptr); 556 return m_pGraphAttributes->type(e); 557 } 558 559 //! Returns the graph attributes of the original graph (the pointer may be 0). getGraphAttributes()560 const GraphAttributes &getGraphAttributes() const { 561 OGDF_ASSERT(m_pGraphAttributes != nullptr); 562 return *m_pGraphAttributes; 563 } 564 565 //@} 566 /** 567 * @name Structural alterations 568 */ 569 //@{ 570 571 // Expands nodes with degree > 4 and merge nodes for generalizations 572 virtual void expand(bool lowDegreeExpand = false); 573 574 void expandLowDegreeVertices(OrthoRep &OR); 575 576 void collapseVertices(const OrthoRep &OR, Layout &drawing); 577 void collapseVertices(const OrthoRep &OR, GridLayout &drawing); 578 579 void removeCrossing(node v); //removes the crossing at node v 580 581 //model a boundary around a star subgraph centered at center 582 //and keep external face information (outside the clique 583 void insertBoundary(node center, adjEntry& adjExternal); 584 585 586 //@} 587 /** 588 * @name Extension of methods defined by GraphCopys 589 */ 590 //@{ 591 592 //! Splits edge \p e. 593 virtual edge split(edge e) override; 594 595 596 //returns node which was expanded using v expandedNode(node v)597 node expandedNode(node v) const { return m_expandedNode[v]; } 598 setExpandedNode(node v,node w)599 void setExpandedNode(node v, node w) { m_expandedNode[v] = w; } 600 601 602 //@} 603 /** 604 * @name Creation of new nodes and edges 605 */ 606 //@{ 607 608 /** 609 * \brief Creates a new node with node type \p vType in the planarized representation. 610 * @param vOrig becomes the original node of the new node. 611 * @param vType becomes the type of the new node. 612 */ 613 node newCopy(node vOrig, Graph::NodeType vType); 614 615 /** 616 * \brief Creates a new edge in the planarized representation. 617 * @param v is the source node of the new edge. 618 * @param adjAfter is the adjacency entry at the target node, after which the 619 * new edge is inserted. 620 * @param eOrig becomes the original edge of the new edge. 621 */ 622 edge newCopy(node v, adjEntry adjAfter, edge eOrig); 623 624 /** 625 * \brief Creates a new edge in the planarized representation while updating the embedding \p E. 626 * @param v is the source node of the new edge. 627 * @param adjAfter is the adjacency entry at the target node, after which the 628 * new edge is inserted. 629 * @param eOrig becomes the original edge of the new edge. 630 * @param E is an embedding of the planarized representation. 631 */ 632 edge newCopy(node v, adjEntry adjAfter, edge eOrig, CombinatorialEmbedding &E); 633 634 635 //@} 636 /** 637 * @name Crossings 638 */ 639 //@{ 640 641 //! Re-inserts edge \p eOrig by "crossing" the edges in \p crossedEdges. 642 /** 643 * Splits each edge in crossedEdges. 644 * 645 * \pre \p eOrig is an edge in the original graph and the edges in \p crossedEdges are in this graph. 646 */ 647 void insertEdgePath(edge eOrig, const SList<adjEntry> &crossedEdges); 648 649 //! Same as insertEdgePath, but for embedded graphs. 650 void insertEdgePathEmbedded( 651 edge eOrig, 652 CombinatorialEmbedding &E, 653 const SList<adjEntry> &crossedEdges); 654 655 //! Removes the complete edge path for edge \p eOrig while preserving the embedding. 656 /** 657 * \pre \p eOrig s an edge in the original graph. 658 */ removeEdgePathEmbedded(CombinatorialEmbedding & E,edge eOrig,FaceSet<false> & newFaces)659 void removeEdgePathEmbedded(CombinatorialEmbedding &E, 660 edge eOrig, 661 FaceSet<false> &newFaces) { 662 GraphCopy::removeEdgePathEmbedded(E,eOrig,newFaces); 663 } 664 665 //! Inserts crossings between two copy edges. 666 /** 667 * This method is used in TopologyModule. 668 * 669 * Let \p crossingEdge = (\a a, \a b) and \p crossedEdge = (\a v, \a w). 670 * Then \p crossedEdge is split creating two edges \p crossedEdge = (\a v, \a u) 671 * and (\a u, \a w), \p crossingEdge is removed and replaced by two new edges 672 * \a e1 = (\a a, \a u) and \a e1 = (\a u, \a b). 673 * Finally it sets \p crossingEdge to \a e2 and returns (\a u, \a w). 674 * 675 * @param crossingEdge is the edge that gets split. 676 * @param crossedEdge is the edge that is replaced by two new edges. 677 * @param topDown is used as follows: If set to true, \p crossingEdge will cross 678 * \p crossedEdge from right to left, otherwise from left to right. 679 */ 680 edge insertCrossing( 681 edge &crossingEdge, 682 edge crossedEdge, 683 bool topDown); 684 685 //@} 686 /** 687 * @name Degree-1 nodes 688 * These methods realize a mechanism for temporarily removing degree-1 nodes. 689 */ 690 //@{ 691 692 /** 693 * \brief Removes all marked degree-1 nodes from the graph copy and stores restore information in \p S. 694 * @param S returns the restore information required by restoreDeg1Nodes(). 695 * @param mark defines which nodes are marked for removal; all nodes \a v with 696 * <I>mark</I>[<I>a</I>]=<B>true</B> are removed. 697 * \pre Only nodes with degree 1 may be marked. 698 */ 699 void removeDeg1Nodes(ArrayBuffer<Deg1RestoreInfo> &S, const NodeArray<bool> &mark); 700 701 /** 702 * \brief Restores degree-1 nodes previously removed with removeDeg1Nodes(). 703 * @param S contains the restore information. 704 * @param deg1s returns the list of newly created nodes in the copy. 705 */ 706 void restoreDeg1Nodes(ArrayBuffer<Deg1RestoreInfo> &S, List<node> °1s); 707 708 //@} 709 void writeGML(const char *fileName, const OrthoRep &OR, const GridLayout &drawing); 710 void writeGML(std::ostream &os, const OrthoRep &OR, const GridLayout &drawing); 711 712 protected: 713 714 int m_currentCC; //!< The index of the current component. 715 Graph::CCsInfo m_ccInfo; 716 //int m_numCC; //!< The number of components in the original graph. 717 718 //Array<List<node> > m_nodesInCC; //!< The list of original nodes in each component. 719 720 const GraphAttributes* m_pGraphAttributes; //!< Pointer to graph attributes of original graph. 721 722 // object types 723 724 //set the type of eCopy according to the type of eOrig 725 //should be virtual if PlanRepUML gets its own 726 void setCopyType(edge eCopy, edge eOrig); 727 728 //helper to cope with the edge types, shifting to the right place generalizationPattern()729 edgeType generalizationPattern() const {return static_cast<edgeType>(UMLEdgeTypeConstants::PrimGeneralization);} associationPattern()730 edgeType associationPattern() const {return static_cast<edgeType>(UMLEdgeTypeConstants::PrimAssociation);} expansionPattern()731 edgeType expansionPattern() const {return UMLEdgeTypeConstants::SecExpansion << UMLEdgeTypeOffsets::Secondary;} assClassPattern()732 edgeType assClassPattern() const {return UMLEdgeTypeConstants::AssClass << UMLEdgeTypeOffsets::Tertiary;} brotherPattern()733 edgeType brotherPattern() const {return UMLEdgeTypeConstants::Brother << UMLEdgeTypeOffsets::Fourth;} halfBrotherPattern()734 edgeType halfBrotherPattern() const {return UMLEdgeTypeConstants::HalfBrother << UMLEdgeTypeOffsets::Fourth;} cliquePattern()735 edgeType cliquePattern() const {return UMLEdgeTypeConstants::SecClique << UMLEdgeTypeOffsets::Secondary;} //boundary 736 737 NodeArray<NodeType> m_vType; //!< Simple node types. 738 739 NodeArray<nodeType> m_nodeTypes; //!< Node types for extended semantic information. 740 741 NodeArray<node> m_expandedNode; //!< For all expansion nodes, save expanded node. 742 NodeArray<adjEntry> m_expandAdj; 743 744 //clique handling: We save an adjEntry of the first edge of an inserted 745 //boundary around a clique at its center v 746 NodeArray<adjEntry> m_boundaryAdj; 747 748 //zusammenlegbare Typen 749 EdgeArray<int> m_expansionEdge; //1 genmerge, 2 degree (2 highdegree, 3 lowdegree) 750 EdgeArray<EdgeType> m_eType; 751 752 //m_edgeTypes stores semantic edge type information on several levels: 753 //primary type: generalization, association,... 754 //secondary type: merger,... 755 //tertiary type: vertical in hierarchy, inner, outer, ... 756 //fourth type: neighbour relation (brother, cousin in hierarchy) 757 //user types: user defined for local changes 758 EdgeArray<edgeType> m_edgeTypes; //store all type information 759 760 //workaround fuer typsuche in insertedgepathembed 761 //speichere kopietyp auf originalen 762 //maybe it's enough to set gen/ass without extra array 763 EdgeArray<edgeType> m_oriEdgeTypes; 764 765 EdgeArray<edge> m_eAuxCopy; // auxiliary (GraphCopy::initByNodes()) 766 }; 767 768 } 769