00001 /* 00002 * $Revision: 2299 $ 00003 * 00004 * last checkin: 00005 * $Author: gutwenger $ 00006 * $Date: 2012-05-07 15:57:08 +0200 (Mon, 07 May 2012) $ 00007 ***************************************************************/ 00008 00047 #ifdef _MSC_VER 00048 #pragma once 00049 #endif 00050 00051 00052 #ifndef OGDF_TOPOLOGYMODULE_H 00053 #define OGDF_TOPOLOGYMODULE_H 00054 00055 00056 00057 #include <ogdf/planarity/PlanRep.h> 00058 #include <ogdf/basic/GraphAttributes.h> 00059 #include <ogdf/basic/EdgeComparer.h> 00060 00061 namespace ogdf { 00062 00063 class EdgeLeg; 00064 00065 //=============================================== 00066 //main function(s): 00067 // setEmbeddingFromGraph(PlanRep&, GraphAttributes&) 00068 // assumes that PG(AG) without bend nodes in PG 00069 // 00070 // sortEdgesFromLayout(GraphAttributes &AG) 00071 // sort the edges in AG, no crossing insertion 00072 //=============================================== 00073 00074 class OGDF_EXPORT TopologyModule 00075 { 00076 public: 00077 TopologyModule() : m_options(opDegOneCrossings | opGenToAss | 00078 opCrossFlip | opLoop | opFlipUML) {} 00079 virtual ~TopologyModule() {} 00080 00081 //the (pre/post)processing options 00082 //opCrossFlip increases running time by const*n, 00083 //opLoop increases running time by const*m 00084 enum Options { 00085 opDegOneCrossings = 0x0001, //should degree one node's edge be crossed 00086 opGenToAss = 0x0002, //should generalizations be turned into associations 00087 opCrossFlip = 0x0004,//if there is a crossing (first ~) between two edges with 00088 //same start or end point, should there position 00089 //at the node be flipped and the crossing be skipped? 00090 //(postprocessing) 00091 opFlipUML = 0x0010, //only flip if same edge type 00092 opLoop = 0x0008 //should loops between crossings (consecutive on both 00093 //crossing edges) be deleted (we dont check for enclosed 00094 //CC's. Therefore it is safe to remove the crossing 00095 }; 00096 00097 void setOptions(int i) {m_options = i;} 00098 void addOption(TopologyModule::Options o) {m_options = (m_options | o);} 00099 //use AG layout to determine an embedding for PG. 00100 //non-constness of AG in the following methods is only 00101 //used when resolving problems, e.g. setting edge types 00102 //if two generalizations cross in the input layout 00103 00104 //Parameter setExternal: run over faces to compute external face 00105 //Parameter reuseAGEmbedding: If true, the call only 00106 //checks for a correct embedding of PG and tries to insert 00107 //crossings detected in the given layout otherwise. 00108 //this allows to assign already sorted UMLGraphs 00109 //NOTE: if the sorting of the edges does not correspond 00110 //to the layout given in AG, this cannot work correctly 00111 //returns false if planarization fails 00112 bool setEmbeddingFromGraph(PlanRep &PG, 00113 GraphAttributes &AG, 00114 adjEntry &adjExternal, 00115 bool setExternal = true, 00116 bool reuseAGEmbedding = false); 00117 00118 //sorts the edges around all nodes of AG corresponding to the 00119 //layout given in AG 00120 //there is no check of the embedding afterwards because this 00121 //method could be used as a first step of a planarization 00122 void sortEdgesFromLayout(Graph &G, GraphAttributes &AG); 00123 00124 face getExternalFace(PlanRep &PG, const GraphAttributes &AG); 00125 00126 double faceSum(PlanRep &PG, const GraphAttributes &AG, face f); 00127 00128 protected: 00129 //compute a planarization, i.e. insert crossing vertices, 00130 //corresponding to the AG layout 00131 void planarizeFromLayout(PlanRep &PG, 00132 GraphAttributes &AG); 00133 //compute crossing point and return if existing 00134 bool hasCrossing(EdgeLeg* legA, EdgeLeg* legB, DPoint& xp); 00135 //check if node v is a crossing of two edges with a common 00136 //endpoint adjacent to v, crossing is removed if flip is set 00137 bool checkFlipCrossing(PlanRep &PG,node v, bool flip = true); 00138 00139 void postProcess(PlanRep &PG); 00140 void handleImprecision(PlanRep &PG); 00141 bool skipable(EdgeLeg* legA, EdgeLeg* legB); 00142 00143 private: 00144 //compare vectors for sorting 00145 int compare_vectors(const double& x1, const double& y1, 00146 const double& x2, const double& y2); 00147 //compute and return the angle defined by p-q,p-r 00148 double angle(DPoint p, DPoint q, DPoint r); 00149 //we have to save the position of the inserted crossing vertices 00150 //in order to compute the external face 00151 NodeArray<DPoint> m_crossPosition; 00152 00153 //we save a list of EdgeLegs for all original edges in 00154 //AG 00155 EdgeArray< List<EdgeLeg*> > m_eLegs; 00156 00157 00158 //option settings as bits 00159 int m_options; 00160 00161 };//TopologyModule 00162 00163 00164 //sorts EdgeLegs according to their xp distance to a reference point 00165 class PointComparer { 00166 public: 00167 PointComparer(DPoint refPoint) : m_refPoint(refPoint) {} 00168 //compares the crossing points stored in the EdgeLeg 00169 int compare(const ListIterator<EdgeLeg*> &ep1, 00170 const ListIterator<EdgeLeg*> &ep2) const; 00171 OGDF_AUGMENT_COMPARER(ListIterator<EdgeLeg*>) 00172 00173 // undefined methods to avoid automatic creation 00174 PointComparer &operator=(const PointComparer &); 00175 00176 private: 00177 const DPoint m_refPoint; 00178 };//PointComparer 00179 00180 //helper class for the computation of crossings 00181 //represents a part of the edge between two consecutive 00182 //bends (in the layout, there are no bends allowed in 00183 //the representation) or crossings 00184 //there can be multiple EdgeLegs associated to one copy 00185 //edge in the PlanRep because of bends 00186 class EdgeLeg 00187 { 00188 public: 00189 EdgeLeg() : m_topDown(false) 00190 {m_copyEdge = 0; m_xp = DPoint(0.0, 0.0);} 00191 EdgeLeg(edge e, int number, DPoint p1, DPoint p2) : 00192 m_xp(DPoint(0.0,0.0)), m_topDown(false), 00193 m_copyEdge(e), m_p1(p1), m_p2(p2), m_number(number) 00194 {} 00195 00196 DPoint& start() {return m_p1;} 00197 DPoint& end() {return m_p2;} 00198 int& number() {return m_number;} 00199 edge& copyEdge() { return m_copyEdge;} 00200 00201 //to avoid sorting both edgelegs and crossing points, 00202 //do not store a pair of them, but allow the xp to be 00203 //stored in the edgeleg 00204 DPoint m_xp; 00205 //we store the direction of the crossed EdgeLeg, too 00206 //if crossingEdgeLeg is horizontally left to right 00207 bool m_topDown; 00208 00209 //each edgeLeg holds an entry with a ListIterator pointing to 00210 //its entry in a <edgeLeg*> List for an original edge 00211 ListIterator< EdgeLeg* > m_eIterator; 00212 00213 private: 00214 edge m_copyEdge; //the edge in the PlanRep copy corresponding 00215 //to the EdgeLeg 00216 DPoint m_p1, m_p2; //"Starting" and "End" point of the EdgeLeg 00217 int m_number; //the order nuumber on the edge, starting at 0 00218 00219 };//edgeleg 00220 00221 00222 /* 00223 EdgeArray<ListIterator<edge> > m_eIterator; // position of copy edge in chain 00224 00225 NodeArray<node> m_vCopy; // corresponding node in graph copy 00226 EdgeArray<List<edge> > m_eCopy; // corresponding chain of edges in graph copy 00227 00228 */ 00229 } // end namespace ogdf 00230 00231 #endif