Open
Graph Drawing
Framework

 v.2012.05
 

precondition.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  
00044 #ifdef _MSC_VER
00045 #pragma once
00046 #endif
00047 
00048 
00049 #ifndef OREAS_PRECONDITION_H
00050 #define OREAS_PRECONDITION_H
00051 
00052 
00053 #include <ogdf/orthogonal/EdgeRouter.h>
00054 
00055 
00056 namespace ogdf {
00057 
00058 //descent the hierarchy tree at "sink" v recursively
00059 bool dfsGenTreeRec(
00060     UMLGraph& UG,
00061     EdgeArray<bool> &used,
00062     NodeArray<int> &hierNumber, //number of hierarchy tree
00063                                //node is visited if number != 0
00064     int hierNum,
00065     node v,
00066     List<edge>& fakedGens, //temporary
00067     bool fakeTree)
00068 {
00069     OGDF_ASSERT(hierNumber[v] == 0);
00070     hierNumber[v] = hierNum;
00071  
00072     bool returnValue = true;
00073 
00074     edge e;
00075     forall_adj_edges(e,v) {
00076         if (e->source() == v) continue;
00077         if (!(UG.type(e) == Graph::generalization)) continue;
00078         if (used[e]) continue; //error ??
00079         used[e] = true;
00080 
00081         node w = e->opposite(v);
00082 
00083         if (hierNumber[w]) 
00084             //temporarily fake trees 
00085             //if (hierNumber[w] == hierNum) //forward search edge
00086             if (fakeTree)
00087             {
00088               //UG.type(e) = Graph::association;
00089               fakedGens.pushBack(e);
00090               continue;
00091             }
00092             else return false;//reached w over unused edge => no tree
00093 
00094         returnValue = dfsGenTreeRec(UG, used, hierNumber, hierNum, w, fakedGens, fakeTree);
00095         //shortcut
00096         if (!returnValue) return false;
00097     }
00098 
00099     return returnValue;
00100 }
00101 
00102 edge firstOutGen(UMLGraph& UG, node v, EdgeArray<bool>& /* used */)
00103 {
00104     //pruefen: kann es hier bereits ausgehende besuchte Kanten geben???
00105     edge e;
00106     forall_adj_edges(e, v)
00107     {
00108         if (e->target() == v) continue;
00109         if (UG.type(e) == Graph::generalization)
00110         {
00111             //OGDF_ASSERT(!used[e]);
00112             return e;
00113         }
00114         else continue;
00115     }//forall
00116     return 0;
00117 }//firstOutGen
00118 
00119 bool dfsGenTree(
00120     UMLGraph& UG, 
00121     List<edge>& fakedGens, 
00122     bool fakeTree)
00123 {
00124     edge e;
00125     EdgeArray<bool> used(UG, false);
00126     //NodeArray<bool> visited(UG,false);
00127     NodeArray<int>  hierNumber(UG, 0);
00128 
00129     int hierNum = 0; //number of hierarchy tree
00130 
00131     const Graph& G = UG;
00132     forall_edges(e, G)
00133     {
00134         //descent in the hierarchy containing e
00135         if ((!used[e]) && (UG.type(e) == Graph::generalization))
00136         {
00137             hierNum++; //current hierarchy tree
00138             //first we search for the sink
00139             node sink = e->target();
00140             edge sinkPath = firstOutGen(UG, e->target(), used);
00141             int cycleCounter = 0;
00142             while (sinkPath)
00143             {
00144                 sink = sinkPath->target();
00145                 sinkPath = firstOutGen(UG, sinkPath->target(), used);    
00146                 cycleCounter++;
00147                 //if theres no sink, ?throw errGenCycle?, or convert Gens to Ass and draw
00148                 if (cycleCounter > G.numberOfEdges()) 
00149                 {
00150                     //versuche workaround: eigentlich werden die Typen erst spaeter
00151                     //gesetzt, damit es nicht zu Fehlern bei der Erkennung kommt, aber
00152                     //zum Abbruch wird hier bereits eine gesetzt (geht es auch ohne?)
00153                     UG.type(sinkPath) = Graph::association;
00154                     fakedGens.pushBack(sinkPath);
00155                     sink = sinkPath->source();
00156                     sinkPath = 0;
00157                     //throw OgdfException(errGenCycle); //vorlaeufig 
00158                 }
00159             }
00160 
00161             //now sink is the hierarchy sink
00162               
00163             //used is set in dfsGenTreeRec
00164             bool isTree = dfsGenTreeRec(UG, used, hierNumber, hierNum, sink, fakedGens, fakeTree);
00165             if (!isTree) return false;
00166         }
00167       
00168     }//forall_edges
00169 
00170     return true;    
00171 }
00172 
00173 }//end namespace ogdf
00174 
00175 #endif