Open
Graph Drawing
Framework

 v.2012.05
 

EdgeLabel.h
Go to the documentation of this file.
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  
00042 #ifdef _MSC_VER
00043 #pragma once
00044 #endif
00045 
00046 #ifndef OGDF_EDGE_LABEL_H
00047 #define OGDF_EDGE_LABEL_H
00048 
00049 
00050 #include <ogdf/basic/geometry.h>
00051 #include <ogdf/basic/List.h>
00052 #include <ogdf/basic/BinaryHeap2.h>
00053 #include <ogdf/basic/Graph.h>
00054 #include <ogdf/basic/GraphCopy.h>
00055 #include <ogdf/planarity/PlanRepUML.h>
00056 #include <ogdf/basic/GridLayoutMapped.h>
00057 #include <ogdf/orthogonal/OrthoRep.h>
00058 
00059 #include <ogdf/labeling/ELabelInterface.h>
00060 
00061 
00062 //debug
00063 //#define foutput
00064 
00065 namespace ogdf {
00066 
00067 //*******************************************************
00068 //all label types are declared in ELabelInterface
00069 
00070 //every edge has a number of labels associated with it
00071 //current status:
00072 
00073 //two end labels 
00074 //two end multiplicities
00075 //a name
00076 
00077 //each label has two coordinates and its input size
00078 //*******************************************************
00079 
00080 
00081 //*******************************************************
00082 //there are some discrete phases:
00083 // *compute(UML)Candidates:
00084 //  assign candidate positions to all input labels
00085 // *test(UML)FeatureIntersect:
00086 //  test intersection of graph features by position candidates
00087 //  currently, only nodes are considered 
00088 // *test(UML)AllIntersect:
00089 //  test label position intersection against each other
00090 //  and save the resulting information
00091 // *Assignment of "good" candidates
00092 //  different heuristics can be applied
00093 //*******************************************************
00094 
00095 
00096 //parameter values for write(UML)GML - output function
00097 enum OutputParameter {opStandard, opOmitIntersect, opOmitFIntersect, opResult};
00098 
00099 //the candidate status values have the following meaning
00100 //csActive: candidate can be assigned
00101 //csAssigned: another candidate was assigned for that label 
00102 //csFIntersect: label would intersect Graph node
00103 //csUsed: this candidate was used for the label
00104 
00105 //csActive and csUsed are both counted as active candidates
00106 //in PosInfo structure, cause they can have influence on the number 
00107 //of necessary intersections
00108 enum candStatus {csAssigned, csFIntersect, csActive, csUsed};
00109 
00110 
00111 
00112 //class ELabelPos is responsible for computation of edge label positions
00113 
00114 //this should NOT be a template class
00115 //UG call is for double only, PRU call for int, PRU call maybe be considered obsolete
00116 //and is no longer maintained (but works)
00117 template <class coordType>
00118 class ELabelPos {
00119 
00120 public:
00121     //construction and destruction
00122     ELabelPos();
00123 
00124     ~ELabelPos() {}
00125 
00126     //we can call the positioner on a given PlanRepUML (grid)drawing or
00127     //just with given (double)positions for all graph features and label sizes
00128     virtual void call(PlanRepUML& pru, GridLayoutMapped& L, ELabelInterface<coordType>& eli); //int
00129 
00130     virtual void call(GraphAttributes& ug, ELabelInterface<coordType>& eli); //double
00131 
00132     //set the edge-label distance
00133     void setDefaultDistance(coordType dist)
00134     {m_defaultDistance = dist;}
00135 
00136     void setDistance(edge e, eLabelTyp elt, coordType dist)
00137     {(m_distance[elt])[e] = dist;}
00138 
00139     //switch if all label types should be distributed evenly on the edge length
00140     void setEndLabelPlacement(bool b) {m_endLabelPlacement = b;}
00141 
00142     void writeGML(const char *filename="labelgraph.gml", 
00143                   OutputParameter sectOmit = opStandard);
00144     void writeUMLGML(const char *filename="labelgraphUML.gml", 
00145                   OutputParameter sectOmit = opStandard);
00146 
00147 protected:
00148 
00149     //**********************************************************
00150     //needed structures
00151 
00152     struct SegmentInfo {
00153         //SegmentInfo() {length = 0; number = 0; direction = odNorth;}
00154 
00155         coordType length;
00156         int number;
00157         coordType min_x, max_x, min_y, max_y;
00158         OrthoDir direction;
00159     };//Segmentinfo
00160     
00161 
00162     struct FeatureInfo {
00163         coordType min_x, max_x, min_y, max_y, size_x, size_y;
00164     };//FeatureInfo
00165 
00166     //Candidate positions have the following properties:
00167     //*active/passive (if intersection)
00168     //*pointer list, pointers to all intersecting candidates
00169     //*Number of intersections with status active (=> if number == 0, this 
00170     //candidate can be assigned,fuer andere Kandidaten deren Ueberlappungspartner --Anzahl
00171     //sowie die aktiven Ueberlappungen vorlaeufig sperren 
00172     struct PosInfo {
00173         GenericPoint<coordType> m_coord; //position of middle 
00174         List< PosInfo* >  m_intersect;
00175         int m_numActive; //active label intersections
00176         int m_numFeatures; //number of intersected features     
00177         int m_posIndex; //holds the relative position of candidates
00178 
00179         edge m_edge;
00180         eLabelTyp m_typ;
00181         candStatus m_active; //csAssigned assigned, csFIntersect  node, csActive 
00182 
00183         double m_cost; //costs for intersections, placement
00184 
00185         PosInfo() {m_edge = 0; m_active = csActive; m_posIndex = 0; m_numActive = 0;
00186                     m_typ = elName;
00187                     m_cost = 0.0;
00188         }
00189         PosInfo(edge e, eLabelTyp elt, GenericPoint<coordType> gp, int posIndex = -1) 
00190         {
00191             m_edge = e;
00192             m_typ = elt;
00193             m_coord = gp; 
00194             m_numActive = 0; 
00195             m_numFeatures = 0;
00196             m_posIndex = posIndex;
00197             m_active = csActive;
00198             m_cost = 0.0;
00199         }
00200         PosInfo(edge e, eLabelTyp elt) 
00201         {
00202             m_edge = e;
00203             m_typ = elt;
00204             m_numActive = 0; 
00205             m_numFeatures = 0;
00206             m_posIndex = 0;
00207             m_active = csActive;
00208             m_cost = 0.0;
00209         }
00210 
00211         bool active() {return (m_active == csActive) || (m_active == csUsed);}
00212         //deactivate candidate
00213         void deactivate() {}
00214 
00215     };//PosInfo
00216 
00217 
00218     //used for sorting and intersection graph buildup
00219     struct FeatureLink {
00220         FeatureInfo m_fi;
00221         edge m_edge;
00222         eLabelTyp m_elt;
00223         int m_index; //index of label position entry in list
00224         node m_node; //representant in intersection graph
00225         PosInfo* m_posInfo;
00226 
00227         FeatureLink() {m_edge = 0; m_elt = (eLabelTyp)0; m_index = 0; m_node = 0; m_posInfo = 0;}
00228         FeatureLink(edge e, eLabelTyp elt, node v, FeatureInfo& fi, int index)
00229         {
00230           m_edge = e;
00231           m_elt = elt;
00232           m_node = v;
00233           m_fi = fi;
00234           m_index = index;
00235           m_posInfo = 0;
00236         }
00237         FeatureLink(edge e, eLabelTyp elt, node v, FeatureInfo& fi, int index, PosInfo& pi)
00238         {
00239           m_edge = e;
00240           m_elt = elt;
00241           m_node = v;
00242           m_fi = fi;
00243           m_index = index;
00244           m_posInfo = &pi;
00245         }
00246         
00247     };//FeatureLink
00248 
00249     struct LabelInfo {
00250         edge m_e;
00251         int m_labelTyp;
00252 
00253         int m_index; //index in der PosListe
00254 
00255         LabelInfo() {m_e = 0; m_labelTyp = m_index = 0;}
00256         LabelInfo(edge e, int l, int i) {m_e = e; m_labelTyp = l; m_index = i;}
00257     };//LabelInfo
00258 
00259 
00260     //**********************************************************
00261     //modification
00262 
00263     //********
00264     //settings 
00265     //cost for feature (node?) intersection
00266     double costFI()  {return m_posNum*5.0;} 
00267     //cost for label intersection
00268     double costLI()  {return 0.9;}//2.0;} 
00269     //cost for edge intersection
00270     double costEI()  {return 0.7;} 
00271     //cost for distance from standard position,
00272     double costPos() {return 0.6;} //e.g. edge start for start label
00273     //cost for non-symmetry at start/end label pairs                               
00274     double costSym() {return 1.3;} 
00275 
00276     coordType segmentMargin() {return m_segMargin;} //defining the size of the rectangle 
00277                                        //around a segment for intersection testing
00278 
00279     bool usePosCost() {return m_posCost;}
00280     bool useSymCost() {return m_symCost;}
00281 
00282     //**********************************************************
00283     //main parts of the algorithm
00284     //check edges for segment structure
00285     void initSegments();
00286     void initUMLSegments();
00287 
00288     //build rectangle structures for all graph features
00289     void initFeatureRectangles();
00290     void initUMLFeatureRectangles();
00291 
00292     //computes the candidate positions, fills the lists
00293     void computeCandidates();
00294     void computeUMLCandidates();
00295 
00296     //build up data structure to decide feasible solutions
00297     //only needed if labeltree not already build 
00298     void initStructure();
00299 
00300     //check label candidates for feature intersection, delete from list
00301     void testFeatureIntersect();
00302     void testUMLFeatureIntersect();
00303 
00304     //assign special candidate to avoid empty list after featuretest
00305     void saveRecovery(EdgeArray< GenericPoint<coordType> > (&saveCandidate)[labelNum]);
00306     void saveUMLRecovery(EdgeArray< GenericPoint<coordType> > (&saveCandidate)[labelNum]);
00307 
00308     //check label candidates for label intersection
00309     void testAllIntersect();
00310     void testUMLAllIntersect();
00311 
00312 
00313     //return the list of all label position candidates (PlanRepUML)
00314     List< GenericPoint<coordType> >& posList(edge e, int lnum) {return (m_candPosList[lnum])[e];}
00315     //return the list of all label position candidates
00316     List< PosInfo >& candList(edge e, int lnum) {return (m_candList[lnum])[e];}
00317     
00318 
00319     //****************************
00320     //information about the segments
00321     //return number of segments for original edge e
00322     int segNumber(edge e) {return m_poly[e].size() - 1;}
00323     //return direction (?ver/hor?) of edge segments, dynamic version
00324     //of SegInfo.dir
00325     OrthoDir segDir(edge e, int segNum)
00326         {
00327           OrthoDir od;
00328           if (segNum > segNumber(e)) OGDF_THROW(Exception);
00329 
00330           IPoint ip1 = (*m_poly[e].get(segNum - 1));
00331           IPoint ip2 = (*m_poly[e].get(segNum));
00332           bool isHor = (ip1.m_y == ip2.m_y); //may still be same place
00333           if (isHor)
00334           {
00335             if (ip1.m_x > ip2.m_x) od = odWest;
00336             else od = odEast;
00337           }//if isHor
00338           else
00339           {
00340               //check m_x == m_x
00341             if (ip1.m_y < ip2.m_y) od = odNorth;
00342             else od = odSouth;
00343           }//else
00344 
00345           return od;
00346     }//segDir
00347 
00348  
00349 private:
00350 
00351 
00352     //settings
00353     int m_numAssignment; //number of necessary assignments
00354 
00355     int m_candStyle; //defines the style how pos cands are computed
00356     int m_placeHeuristic; //defines how candidates are chosen
00357     bool m_endInsertion; //should candidates nearest to endnode be chosen
00358 
00359     bool m_endLabelPlacement; //are endlabels candidates computed near the nodes
00360 
00361     bool m_posCost; //should end label distance to end give a cost for candidates
00362     bool m_symCost; //should non-symmetric assignment for end label pairs -"-
00363 
00364     //number of candidates for every label
00365     //end pos. candidates get double the number , cause a position 
00366     //on both sides of the edge is possible for these values
00367     int m_posNum; //number of pos. cand. for candstyle 1, like ppinch
00368 
00369     //only internally used option: dont stop after first feature intersection,
00370     //allows weighting over number of feature intersections
00371     bool m_countFeatureIntersect; 
00372 
00373     coordType m_segMargin;
00374 
00375     //pointers to the PlanRepUML input instances
00376     PlanRepUML* m_prup;
00377     GridLayoutMapped* m_gl; //the existing drawing
00378     
00379     //pointers to the AttributedGraph input instances
00380     GraphAttributes* m_ug;
00381 
00382     //pointers to the generic input instances
00383     ELabelInterface<coordType>* m_eli;//the input/output interface
00384     
00385     //maybe this should be a parameter, reference
00386     //forall label types the cand. pos.
00387     EdgeArray< List<GenericPoint<coordType> > > m_candPosList[labelNum]; 
00388     //wird ersetzt durch: Liste von PosInfos 
00389     EdgeArray< List < PosInfo > > m_candList[labelNum];
00390     //structure holding all intersection free labels
00391     List< PosInfo* > m_freeLabels;
00392     //structure holding all intersecting labels (should be PQ)
00393     List< PosInfo* > m_sectLabels;
00394     //structure holding candidates sorted by associated costs
00395     BinaryHeap2<double, PosInfo*> m_candidateHeap;
00396 
00397     //the bends and crossings, in the UML call use AttributedGraph::bends
00398     EdgeArray< List<GenericPoint<coordType> > > m_poly;
00399     
00400     //list of segment info 
00401     EdgeArray< List<SegmentInfo> > m_segInfo;
00402     EdgeArray<coordType> m_edgeLength;
00403 
00404     //list of graph feature(nodes,...) info
00405     NodeArray<FeatureInfo> m_featureInfo; //on prup-original
00406 
00407     //save the intersections
00408     EdgeArray< List< List<LabelInfo> > > m_intersect[labelNum];
00409 
00410     EdgeArray<bool> m_assigned[labelNum]; //edges with already assigned labels?
00411 
00412     //allow specific edge to label distance, there is a default value
00413     EdgeArray<coordType> m_distance[labelNum]; 
00414     coordType m_defaultDistance;
00415 
00416     Graph m_intersectGraph;
00417 
00418     void init(PlanRepUML& pru, GridLayoutMapped& L, ELabelInterface<coordType>& eli); //int
00419 
00420     void initUML(GraphAttributes& ug, ELabelInterface<coordType>& eli); //double
00421 
00422 //intersection test section
00423     //we have to sort the features and therefore define a special method
00424       class FeatureComparer;
00425       friend class FeatureComparer;
00426       class FeatureComparer
00427       {
00428         public:
00429         //we sort from lower (bottom side) to upper and from left to right side
00430         static int compare(const FeatureLink &f1, const FeatureLink &f2) {
00431             coordType d1 = f1.m_fi.min_y;
00432             coordType d2 = f2.m_fi.min_y;
00433 
00434             if (DIsLess(d1, d2)) return -1;
00435             else if (DIsGreater(d1, d2)) return 1;
00436                  else
00437                  {
00438                    if (DIsLess(f1.m_fi.min_x, f2.m_fi.min_x)) return -1;
00439                    else if (DIsGreater(f1.m_fi.min_x, f2.m_fi.min_x)) return 1;
00440                          
00441                    return 0;
00442                  }
00443         }
00444         OGDF_AUGMENT_STATICCOMPARER(FeatureLink)
00445     };
00446 
00447 
00448 };//ELabelPos
00449 
00450 }//namespace
00451 
00452 //#if defined(_MSC_VER) || defined(__BORLANDC__)
00453 #include <src/orthogonal/EdgeLabel-impl.h>
00454 //#endif
00455 
00456 #endif