Code

- Connectors with end-markers now constrained to point downwards in graph layout
authortgdwyer <tgdwyer@users.sourceforge.net>
Fri, 14 Jul 2006 04:09:40 +0000 (04:09 +0000)
committertgdwyer <tgdwyer@users.sourceforge.net>
Fri, 14 Jul 2006 04:09:40 +0000 (04:09 +0000)
 - vpsc namespace added to libvpsc

24 files changed:
src/connector-context.cpp
src/graphlayout/graphlayout.cpp
src/libcola/cola.cpp
src/libcola/cola.h
src/libcola/gradient_projection.cpp
src/libcola/gradient_projection.h
src/libcola/straightener.h
src/libvpsc/block.cpp
src/libvpsc/block.h
src/libvpsc/blocks.cpp
src/libvpsc/blocks.h
src/libvpsc/constraint.cpp
src/libvpsc/constraint.h
src/libvpsc/csolve_VPSC.cpp
src/libvpsc/csolve_VPSC.h
src/libvpsc/generate-constraints.cpp
src/libvpsc/generate-constraints.h
src/libvpsc/remove_rectangle_overlap.cpp
src/libvpsc/remove_rectangle_overlap.h
src/libvpsc/solve_VPSC.cpp
src/libvpsc/solve_VPSC.h
src/libvpsc/variable.cpp
src/libvpsc/variable.h
src/removeoverlap/removeoverlap.cpp

index e68c8f52187a550f73c8c9bc4364bde09f39eeaf..bb0c8e7401f919bfed26fef261dbe9f1ff0f654b 100644 (file)
@@ -9,7 +9,7 @@
  * Released under GNU GPL, read the file 'COPYING' for more information
  *
  * TODO:
- *  o  Have shapes avoid coonvex hulls of objects, rather than their
+ *  o  Have shapes avoid convex hulls of objects, rather than their
  *     bounding box.  Possibly implement the unfinished ConvexHull
  *     class in libnr.
  *     (HOWEVER, using the convex hull C of a shape S does the wrong thing if a
index ac2d5429f4ae1518e50d73706d01567b37f12a88..432f3c942c58518f9452c50c4fb7f5048af170f1 100644 (file)
@@ -22,6 +22,7 @@
 #include "sp-item.h"
 #include "sp-item-transform.h"
 #include "sp-conn-end-pair.h"
+#include "style.h"
 #include "conn-avoid-ref.h"
 #include "libavoid/connector.h"
 #include "libavoid/geomtypes.h"
@@ -31,6 +32,7 @@
 
 using namespace std;
 using namespace cola;
+using namespace vpsc;
 
 /**
  * Returns true if item is a connector
@@ -90,9 +92,28 @@ void graphlayout(GSList const *const items) {
                minX=min(ll[0],minX); minY=min(ll[1],minY);
                maxX=max(ur[0],maxX); maxY=max(ur[1],maxY);
                nodelookup[u->id]=rs.size();
+               cout << "Node " << rs.size() << endl;
                rs.push_back(new Rectangle(ll[0],ur[0],ll[1],ur[1]));
        }
 
+       SimpleConstraints scy;
+       double ideal_connector_length = prefs_get_double_attribute("tools.connector","length",100);
+       double directed_edge_height_modifier = 1.0;
+       gchar const *directed_str = NULL, *overlaps_str = NULL;
+       directed_str = prefs_get_string_attribute("tools.connector",
+                       "directedlayout");
+       overlaps_str = prefs_get_string_attribute("tools.connector",
+                       "avoidoverlaplayout");
+       bool avoid_overlaps = false;
+       bool directed = false;
+        if (directed_str && !strcmp(directed_str, "true")) {
+            cout << "Directed layout requested.\n";
+           directed = true;
+       }
+        if (overlaps_str && !strcmp(overlaps_str, "true")) {
+            cout << "Avoid overlaps requested.\n";
+           avoid_overlaps = true;
+       }
 
        for (list<SPItem *>::iterator i(selected.begin());
                i != selected.end();
@@ -100,17 +121,38 @@ void graphlayout(GSList const *const items) {
        {
                SPItem *iu=*i;
                unsigned u=nodelookup[iu->id];
-               GSList *nlist=iu->avoidRef->getAttachedShapes(Avoid::runningFrom);
-               list<SPItem *> neighbours;
-               neighbours.insert<GSListConstIterator<SPItem *> >(neighbours.end(),nlist,NULL);
-               for (list<SPItem *>::iterator j(neighbours.begin());
-                               j != neighbours.end();
+               GSList *nlist=iu->avoidRef->getAttachedConnectors(Avoid::runningFrom);
+               list<SPItem *> connectors;
+               
+               connectors.insert<GSListConstIterator<SPItem *> >(connectors.end(),nlist,NULL);
+               for (list<SPItem *>::iterator j(connectors.begin());
+                               j != connectors.end();
                                ++j) {
-                       
-                       SPItem *iv=*j;
+                       SPItem *conn=*j;
+                       SPItem *iv;
+                       SPItem *items[2];
+                       assert(isConnector(conn));
+                       SP_PATH(conn)->connEndPair.getAttachedItems(items);
+                       if(items[0]==iu) {
+                               iv=items[1];
+                       } else {
+                               iv=items[0];
+                       }
+               
                        // What do we do if iv not in nodelookup?!?!
-                       unsigned v=nodelookup[iv->id];
-                       es.push_back(make_pair(u,v));
+                       map<string,unsigned>::iterator v_pair=nodelookup.find(iv->id);
+                       if(v_pair!=nodelookup.end()) {
+                               unsigned v=v_pair->second;
+                               cout << "Edge: (" << u <<","<<v<<")"<<endl;
+                               es.push_back(make_pair(u,v));
+                               if(conn->style->marker[SP_MARKER_LOC_END].set) {
+                                       if(directed && strcmp(conn->style->marker[SP_MARKER_LOC_END].value,"none")) {
+                                               cout << conn->style->marker[SP_MARKER_LOC_END].value << endl;
+                                               scy.push_back(new SimpleConstraint(v, u, 
+                                    (ideal_connector_length * directed_edge_height_modifier)));
+                                       }
+                               }
+                       }
                }
                if(nlist) {
                        g_slist_free(nlist);
@@ -122,24 +164,9 @@ void graphlayout(GSList const *const items) {
        double eweights[E];
        fill(eweights,eweights+E,1);
 
-       ConstrainedMajorizationLayout alg(rs,es,eweights,
-               prefs_get_double_attribute("tools.connector","length",100));
-       gchar const *directed = NULL, *overlaps = NULL;
-       directed = prefs_get_string_attribute("tools.connector",
-                       "directedlayout");
-       overlaps = prefs_get_string_attribute("tools.connector",
-                       "avoidoverlaplayout");
-       bool avoid_overlaps = false;
-        if (directed && !strcmp(directed, "true")) {
-            cout << "Directed layout requested, but not yet implemented\n";
-            cout << "  because we haven't coded cyclic removal alg...\n";
-       }
-        if (overlaps && !strcmp(overlaps, "true")) {
-            cout << "Avoid overlaps requested.\n";
-           avoid_overlaps = true;
-       }
+       ConstrainedMajorizationLayout alg(rs,es,eweights,ideal_connector_length);
        alg.setupConstraints(NULL,NULL,avoid_overlaps,
-                       NULL,NULL,NULL,NULL,NULL,NULL);
+                       NULL,NULL,NULL,&scy,NULL,NULL);
        alg.run();
        
        for (list<SPItem *>::iterator it(selected.begin());
@@ -156,3 +183,5 @@ void graphlayout(GSList const *const items) {
                }
        }
 }
+// vim: set cindent 
+// vim: ts=4 sw=4 et tw=0 wm=0
index 74663f5018e93e451e4b72b606a73f583851a4ae..3499d729a6110db3b2bd8851d43d9b5348416262 100644 (file)
@@ -253,7 +253,7 @@ void ConstrainedMajorizationLayout::straighten(vector<straightener::Edge*>& sedg
         }
     }
        GradientProjection gp(dim,n,Q,coords,tol,100,
-            (AlignmentConstraints*)NULL,false,(Rectangle**)NULL,(PageBoundaryConstraints*)NULL,&cs);
+            (AlignmentConstraints*)NULL,false,(vpsc::Rectangle**)NULL,(PageBoundaryConstraints*)NULL,&cs);
     constrainedLayout = true;
     majlayout(Dij,&gp,coords,b);
     for(unsigned i=0;i<sedges.size();i++) {
index d4b0d1421435a9d7a91b65a21427ebe9c485c581..cc99515bf9b78a52d75f668751b591230f1b580f 100644 (file)
@@ -121,7 +121,7 @@ namespace cola {
        class ConstrainedMajorizationLayout {
     public:
                ConstrainedMajorizationLayout(
-                vector<Rectangle*>& rs,
+                vector<vpsc::Rectangle*>& rs,
                 vector<Edge>& es,
                                double* eweights,
                 double idealLength,
@@ -141,7 +141,7 @@ namespace cola {
               straightenEdges(NULL)
         {
             assert(rs.size()==n);
-            boundingBoxes = new Rectangle*[rs.size()];
+            boundingBoxes = new vpsc::Rectangle*[rs.size()];
             copy(rs.begin(),rs.end(),boundingBoxes);
 
             double** D=new double*[n];
@@ -229,7 +229,7 @@ namespace cola {
         double** Dij;
         double tol;
                TestConvergence& done;
-        Rectangle** boundingBoxes;
+        vpsc::Rectangle** boundingBoxes;
         double *X, *Y;
         Clusters* clusters;
         double edge_length;
index 061ba0f1a10b6176bea1be7abaddcfc5bfe77f2f..cec59c57ad37d01f356dfd9160a9686b87013c60 100644 (file)
 #include <iostream>
 
 using namespace std;
+using namespace vpsc;
 //#define CONMAJ_LOGGING 1
 
-static void dumpVPSCException(char const *str, IncVPSC* vpsc) {
+static void dumpVPSCException(char const *str, IncSolver* solver) {
     cerr<<str<<endl;
     unsigned m;
-    Constraint** cs = vpsc->getConstraints(m);
+    Constraint** cs = solver->getConstraints(m);
     for(unsigned i=0;i<m;i++) {
         cerr << *cs[i] << endl;
     }
@@ -41,9 +42,9 @@ unsigned GradientProjection::solve(double * b) {
 
        bool converged=false;
 
-    IncVPSC* vpsc=NULL;
+    IncSolver* solver=NULL;
 
-    vpsc = setupVPSC();
+    solver = setupVPSC();
     //cerr << "in gradient projection: n=" << n << endl;
     for (i=0;i<n;i++) {
         assert(!isnan(place[i]));
@@ -51,9 +52,9 @@ unsigned GradientProjection::solve(double * b) {
         vars[i]->desiredPosition=place[i];
     }
     try {
-        vpsc->satisfy();
+        solver->satisfy();
     } catch (char const *str) {
-        dumpVPSCException(str,vpsc);
+        dumpVPSCException(str,solver);
        }
 
     for (i=0;i<n;i++) {
@@ -104,9 +105,9 @@ unsigned GradientProjection::solve(double * b) {
 
         //project to constraint boundary
         try {
-            vpsc->satisfy();
+            solver->satisfy();
         } catch (char const *str) {
-            dumpVPSCException(str,vpsc);
+            dumpVPSCException(str,solver);
         }
         for (i=0;i<n;i++) {
             place[i]=vars[i]->position();
@@ -155,7 +156,7 @@ unsigned GradientProjection::solve(double * b) {
                        converged=false;
                }
        }
-    destroyVPSC(vpsc);
+    destroyVPSC(solver);
        return counter;
 }
 // Setup an instance of the Variable Placement with Separation Constraints
@@ -164,7 +165,7 @@ unsigned GradientProjection::solve(double * b) {
 // --- that are only relevant to one iteration, and merge these with the
 // global constraint list (including alignment constraints,
 // dir-edge constraints, containment constraints, etc).
-IncVPSC* GradientProjection::setupVPSC() {
+IncSolver* GradientProjection::setupVPSC() {
     Constraint **cs;
     //assert(lcs.size()==0);
     
@@ -192,13 +193,13 @@ IncVPSC* GradientProjection::setupVPSC() {
     }
     cs = new Constraint*[lcs.size() + gcs.size()];
     unsigned m = 0 ;
-    for(Constraints::iterator ci = lcs.begin();ci!=lcs.end();++ci) {
+    for(vector<Constraint*>::iterator ci = lcs.begin();ci!=lcs.end();++ci) {
         cs[m++] = *ci;
     }
-    for(Constraints::iterator ci = gcs.begin();ci!=gcs.end();++ci) {
+    for(vector<Constraint*>::iterator ci = gcs.begin();ci!=gcs.end();++ci) {
         cs[m++] = *ci;
     }
-    return new IncVPSC(vars.size(),vs,m,cs);
+    return new IncSolver(vars.size(),vs,m,cs);
 }
 void GradientProjection::clearDummyVars() {
     for(DummyVars::iterator i=dummy_vars.begin();i!=dummy_vars.end();++i) {
@@ -206,7 +207,7 @@ void GradientProjection::clearDummyVars() {
     }
     dummy_vars.clear();
 }
-void GradientProjection::destroyVPSC(IncVPSC *vpsc) {
+void GradientProjection::destroyVPSC(IncSolver *vpsc) {
     if(acs) {
         for(AlignmentConstraints::iterator ac=acs->begin(); ac!=acs->end();++ac) {
             (*ac)->updatePosition();
@@ -218,7 +219,7 @@ void GradientProjection::destroyVPSC(IncVPSC *vpsc) {
     delete vpsc;
     delete [] cs;
     delete [] vs;
-    for(Constraints::iterator i=lcs.begin();i!=lcs.end();i++) {
+    for(vector<Constraint*>::iterator i=lcs.begin();i!=lcs.end();i++) {
             delete *i;
     }
     lcs.clear();
index e8b72180bd1b7cf3d9d69bcf8cf54a4685b685c4..9ee3ff5c517ec0d1839fd7a8b57664728888107e 100644 (file)
@@ -11,8 +11,8 @@
 
 using namespace std;
 
-typedef vector<Constraint*> Constraints;
-typedef vector<Variable*> Variables;
+typedef vector<vpsc::Constraint*> Constraints;
+typedef vector<vpsc::Variable*> Variables;
 typedef vector<pair<unsigned,double> > OffsetList;
 
 class SimpleConstraint {
@@ -35,7 +35,7 @@ public:
     void* guide;
     double position;
 private:
-    Variable* variable;
+    vpsc::Variable* variable;
 };
 typedef vector<AlignmentConstraint*> AlignmentConstraints;
 
@@ -44,16 +44,16 @@ public:
     PageBoundaryConstraints(double lm, double rm, double w)
         : leftMargin(lm), rightMargin(rm), weight(w) { }
     void createVarsAndConstraints(Variables &vs, Constraints &cs) {
-        Variable* vl, * vr;
+        vpsc::Variable* vl, * vr;
         // create 2 dummy vars, based on the dimension we are in
-        vs.push_back(vl=new Variable(vs.size(), leftMargin, weight));
-        vs.push_back(vr=new Variable(vs.size(), rightMargin, weight));
+        vs.push_back(vl=new vpsc::Variable(vs.size(), leftMargin, weight));
+        vs.push_back(vr=new vpsc::Variable(vs.size(), rightMargin, weight));
 
         // for each of the "real" variables, create a constraint that puts that var
         // between our two new dummy vars, depending on the dimension.
         for(OffsetList::iterator o=offsets.begin(); o!=offsets.end(); ++o)  {
-            cs.push_back(new Constraint(vl, vs[o->first], o->second));
-            cs.push_back(new Constraint(vs[o->first], vr, o->second));
+            cs.push_back(new vpsc::Constraint(vl, vs[o->first], o->second));
+            cs.push_back(new vpsc::Constraint(vs[o->first], vr, o->second));
         }
     }
     OffsetList offsets;
@@ -99,19 +99,19 @@ friend class GradientProjection;
      */
     void setupVPSC(Variables &vars, Constraints &cs) {
         double weight=1;
-        left = new Variable(vars.size(),place_l,weight);
+        left = new vpsc::Variable(vars.size(),place_l,weight);
         vars.push_back(left);
-        right = new Variable(vars.size(),place_r,weight);
+        right = new vpsc::Variable(vars.size(),place_r,weight);
         vars.push_back(right);
         for(CList::iterator cit=leftof.begin();
                 cit!=leftof.end(); ++cit) {
-            Variable* v = vars[(*cit).first];
-            cs.push_back(new Constraint(left,v,(*cit).second)); 
+            vpsc::Variable* v = vars[(*cit).first];
+            cs.push_back(new vpsc::Constraint(left,v,(*cit).second)); 
         }
         for(CList::iterator cit=rightof.begin();
                 cit!=rightof.end(); ++cit) {
-            Variable* v = vars[(*cit).first];
-            cs.push_back(new Constraint(v,right,(*cit).second)); 
+            vpsc::Variable* v = vars[(*cit).first];
+            cs.push_back(new vpsc::Constraint(v,right,(*cit).second)); 
         }
     }
     /**
@@ -163,8 +163,8 @@ friend class GradientProjection;
     }
     double dist; // ideal distance between vars
     double b; // linear coefficient in quad form for left (b_right = -b)
-    Variable* left; // Variables used in constraints
-    Variable* right;
+    vpsc::Variable* left; // Variables used in constraints
+    vpsc::Variable* right;
     double lap2; // laplacian entry
     double g; // descent vec for quad form for left (g_right = -g)
     double old_place_l; // old_place is where the descent vec g was computed
@@ -185,7 +185,7 @@ public:
                unsigned max_iterations,
         AlignmentConstraints* acs=NULL,
         bool nonOverlapConstraints=false,
-        Rectangle** rs=NULL,
+        vpsc::Rectangle** rs=NULL,
         PageBoundaryConstraints *pbc = NULL,
         SimpleConstraints *sc = NULL)
             : k(k), n(n), A(A), place(x), rs(rs),
@@ -195,18 +195,18 @@ public:
               constrained(false)
     {
         for(unsigned i=0;i<n;i++) {
-            vars.push_back(new Variable(i,1,1));
+            vars.push_back(new vpsc::Variable(i,1,1));
         }
         if(acs) {
             for(AlignmentConstraints::iterator iac=acs->begin();
                     iac!=acs->end();++iac) {
                 AlignmentConstraint* ac=*iac;
-                Variable *v=ac->variable=new Variable(vars.size(),ac->position,0.0001);
+                vpsc::Variable *v=ac->variable=new vpsc::Variable(vars.size(),ac->position,0.0001);
                 vars.push_back(v);
                 for(OffsetList::iterator o=ac->offsets.begin();
                         o!=ac->offsets.end();
                         o++) {
-                    gcs.push_back(new Constraint(v,vars[o->first],o->second,true));
+                    gcs.push_back(new vpsc::Constraint(v,vars[o->first],o->second,true));
                 }
             }
         }
@@ -215,7 +215,7 @@ public:
         }
         if (sc) {
             for(SimpleConstraints::iterator c=sc->begin(); c!=sc->end();++c) {
-                gcs.push_back(new Constraint(
+                gcs.push_back(new vpsc::Constraint(
                         vars[(*c)->left],vars[(*c)->right],(*c)->gap));
             }
         }
@@ -239,8 +239,8 @@ public:
        unsigned solve(double* b);
     DummyVars dummy_vars; // special vars that must be considered in Lapl.
 private:
-    IncVPSC* setupVPSC();
-    void destroyVPSC(IncVPSC *vpsc);
+    vpsc::IncSolver* setupVPSC();
+    void destroyVPSC(vpsc::IncSolver *vpsc);
     Dim k;
        unsigned n; // number of actual vars
        double** A; // Graph laplacian matrix
@@ -250,7 +250,7 @@ private:
     Constraints gcs; /* global constraints - persist throughout all
                                 iterations */
     Constraints lcs; /* local constraints - only for current iteration */
-    Rectangle** rs;
+    vpsc::Rectangle** rs;
     bool nonOverlapConstraints;
     double tolerance;
     AlignmentConstraints* acs;
index 33af0c697574d3664b786cc31d6f0281788caa16..e2c50a3a624ac44a36a518719406027bca8b19bc 100644 (file)
@@ -97,7 +97,7 @@ namespace straightener {
         bool dummy;
         double weight;
         bool open;
-        Node(unsigned id, Rectangle* r) :
+        Node(unsigned id, vpsc::Rectangle* r) :
             id(id),x(r->getCentreX()),y(r->getCentreY()), width(r->width()), height(r->height()),
             xmin(x-width/2),xmax(x+width/2),
             ymin(y-height/2),ymax(y+height/2),
index 69a439cd793cda9804da9182081ba701348dc9f4..221df536a2945a9d3d742b6f1ca2bc728b20d843 100644 (file)
@@ -23,6 +23,7 @@ using std::endl;
 #endif
 using std::vector;
 
+namespace vpsc {
 void Block::addVariable(Variable* const v) {
        v->block=this;
        vars->push_back(v);
@@ -346,6 +347,22 @@ void Block::populateSplitBlock(Block *b, Variable* const v, Variable* const u) {
                        populateSplitBlock(b, (*c)->right, v);
        }
 }
+// Search active constraint tree from u to see if there is a directed path to v.
+// Returns true if path is found with all constraints in path having their visited flag
+// set true.
+bool Block::isActiveDirectedPathBetween(Variable* u, Variable *v) {
+       if(u==v) return true;
+       for (Cit c=u->out.begin();c!=u->out.end();++c) {
+               if(canFollowRight(*c,NULL)) {
+                       if(isActiveDirectedPathBetween((*c)->right,v)) {
+                               (*c)->visited=true;
+                               return true;
+                       }
+                       (*c)->visited=false;
+               }
+       }
+       return false;
+}
 /**
  * Block needs to be split because of a violated constraint between vl and vr.
  * We need to search the active constraint tree between l and r and find the constraint
@@ -402,3 +419,4 @@ ostream& operator <<(ostream &os, const Block& b)
        }
     return os;
 }
+}
index 81e6c763772b88ed4d134e9cfe65fd4946c0045d..9c285f311dc053f23f49f9ad11c7f11a5b6d086d 100644 (file)
 
 #include <vector>
 #include <iostream>
+template <class T> class PairingHeap;
+namespace vpsc {
 class Variable;
 class Constraint;
-template <class T> class PairingHeap;
-class StupidPriorityQueue;
 
 class Block
 {
@@ -55,6 +55,7 @@ public:
        long timeStamp;
        PairingHeap<Constraint*> *in;
        PairingHeap<Constraint*> *out;
+       bool isActiveDirectedPathBetween(Variable* u, Variable *v);
 private:
        typedef enum {NONE, LEFT, RIGHT} Direction;
        typedef std::pair<double, Constraint*> Pair;
@@ -71,4 +72,5 @@ private:
        void setUpConstraintHeap(PairingHeap<Constraint*>* &h,bool in);
 };
 
+}
 #endif // SEEN_REMOVEOVERLAP_BLOCK_H
index 48f0237bf12221beec9e65450bb1a70994eaa62f..fe0caacfcf2d04066108a3de0dabf3c6ccd00d0a 100644 (file)
@@ -28,6 +28,8 @@ using std::iterator;
 using std::list;
 using std::copy;
 
+namespace vpsc {
+
 long blockTimeCtr;
 
 Blocks::Blocks(const int n, Variable* const vs[]) : vs(vs),nvs(n) {
@@ -194,3 +196,4 @@ double Blocks::cost() {
        return c;
 }
 
+}
index 0be1d76367791f328adef31962c001673a6b95ab..72363ef66e0d90224c083c8e38828b8de9e1a82d 100644 (file)
@@ -23,6 +23,7 @@
 #include <set>
 #include <list>
 
+namespace vpsc {
 class Block;
 class Variable;
 class Constraint;
@@ -50,4 +51,5 @@ private:
 };
 
 extern long blockTimeCtr;
+}
 #endif // SEEN_REMOVEOVERLAP_BLOCKS_H
index 7c200878b6bbdb2dfbbd4dbf59448d8f2c626a78..af5da941aab0919c19940fb2c6e489badf72ea21 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "constraint.h"
 #include <cassert>
+namespace vpsc {
 Constraint::Constraint(Variable *left, Variable *right, double gap, bool equality)
 : left(left),
   right(right),
@@ -45,3 +46,4 @@ std::ostream& operator <<(std::ostream &os, const Constraint &c)
        }
        return os;
 }
+}
index 3da7449cd247792c16f6cdf2109220443e16e1e8..c73776daf07787ed02bb153bd9a7c554bb49ed61 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <iostream>
 #include "variable.h"
+namespace vpsc {
 
 class Constraint
 {
@@ -54,5 +55,6 @@ static inline bool compareConstraints(Constraint *const &l, Constraint *const &r
        }
        return sl < sr;
 }
+}
 
 #endif // SEEN_REMOVEOVERLAP_CONSTRAINT_H
index b78b01054fa715871f200336d4fc3ac53cc948fb..bd7db5ab21ffb0b41d7d3f1b4bd4a2a3ec8a979e 100644 (file)
@@ -15,6 +15,7 @@
 #include "generate-constraints.h"
 #include "solve_VPSC.h"
 #include "csolve_VPSC.h"
+using namespace vpsc;
 extern "C" {
 Variable* newVariable(int id, double desiredPos, double weight) {
        return new Variable(id,desiredPos,weight);
@@ -22,11 +23,11 @@ Variable* newVariable(int id, double desiredPos, double weight) {
 Constraint* newConstraint(Variable* left, Variable* right, double gap) {
        return new Constraint(left,right,gap);
 }
-VPSC* newVPSC(int n, Variable* vs[], int m, Constraint* cs[]) {
-       return new VPSC(n,vs,m,cs);
+Solver* newSolver(int n, Variable* vs[], int m, Constraint* cs[]) {
+       return new Solver(n,vs,m,cs);
 }
-VPSC* newIncVPSC(int n, Variable* vs[], int m, Constraint* cs[]) {
-       return (VPSC*)new IncVPSC(n,vs,m,cs);
+Solver* newIncSolver(int n, Variable* vs[], int m, Constraint* cs[]) {
+       return (Solver*)new vpsc::IncSolver(n,vs,m,cs);
 }
 
 int genXConstraints(int n, boxf* bb, Variable** vs, Constraint*** cs,int transitiveClosure) {
@@ -67,7 +68,7 @@ void deleteConstraint(Constraint* c) {
 void deleteVariable(Variable* v) {
        delete v;
 }
-void satisfyVPSC(VPSC* vpsc) {
+void satisfyVPSC(Solver* vpsc) {
        try {
                vpsc->satisfy();
        } catch(const char *e) {
@@ -75,17 +76,17 @@ void satisfyVPSC(VPSC* vpsc) {
                exit(1);
        }
 }
-int getSplitCnt(IncVPSC *vpsc) {
+int getSplitCnt(IncSolver *vpsc) {
        return vpsc->splitCnt;
 }
-void deleteVPSC(VPSC *vpsc) {
+void deleteVPSC(Solver *vpsc) {
        assert(vpsc!=NULL);
        delete vpsc;
 }
-void solveVPSC(VPSC* vpsc) {
+void solveVPSC(Solver* vpsc) {
        vpsc->solve();
 }
-void splitIncVPSC(IncVPSC* vpsc) {
+void splitIncVPSC(IncSolver* vpsc) {
        vpsc->splitBlocks();
 }
 void setVariableDesiredPos(Variable *v, double desiredPos) {
index cd879effe6036c010ff9ffe65d9b7d09cdb822bf..81e50d990886f8bfd0e13396275fd08dd075acdb 100644 (file)
 #ifndef _CSOLVE_VPSC_H_
 #define _CSOLVE_VPSC_H_
 #ifdef __cplusplus
+class vpsc::Variable;
+class vpsc::Constraint;
+class vpsc::Solver;
+class vpsc::IncSolver;
+using namespace vpsc;
 extern "C" {
-#endif
+#else
 typedef struct Variable Variable;
+typedef struct Constraint Constraint;
+typedef struct Solver Solver;
+typedef struct IncSolver IncSolver;
+#endif
 Variable* newVariable(int id, double desiredPos, double weight);
 void setVariableDesiredPos(Variable *, double desiredPos);
 double getVariablePos(Variable*);
 
-typedef struct Constraint Constraint;
 Constraint* newConstraint(Variable* left, Variable* right, double gap);
 
-typedef struct VPSC VPSC;
-VPSC* newVPSC(int n, Variable* vs[], int m, Constraint* cs[]);
-void deleteVPSC(VPSC*);
+Solver* newSolver(int n, Variable* vs[], int m, Constraint* cs[]);
+void deleteSolver(Solver*);
 void deleteConstraint(Constraint*);
 void deleteVariable(Variable*);
 Constraint** newConstraints(int m);
@@ -42,12 +49,11 @@ int genXConstraints(int n, boxf[], Variable** vs, Constraint*** cs,
                int transitiveClosure);
 int genYConstraints(int n, boxf[], Variable** vs, Constraint*** cs);
 
-void satisfyVPSC(VPSC*);
-void solveVPSC(VPSC*);
-typedef struct IncVPSC IncVPSC;
-VPSC* newIncVPSC(int n, Variable* vs[], int m, Constraint* cs[]);
-void splitIncVPSC(IncVPSC*);
-int getSplitCnt(IncVPSC *vpsc);
+void satisfyVPSC(Solver*);
+void solveVPSC(Solver*);
+Solver* newIncSolver(int n, Variable* vs[], int m, Constraint* cs[]);
+void splitIncSolver(IncSolver*);
+int getSplitCnt(IncSolver *vpsc);
 #ifdef __cplusplus
 }
 #endif
index 312ad960b92d09ae26b490c69095e6f9de08a1aa..3b69e7968a25d4de31c4bae6689e6992dbecf4e3 100644 (file)
 using std::set;
 using std::vector;
 
+namespace vpsc {
 std::ostream& operator <<(std::ostream &os, const Rectangle &r) {
        os << "{"<<r.minX<<","<<r.maxX<<","<<r.minY<<","<<r.maxY<<"},";
        return os;
 }
+
 Rectangle::Rectangle(double x, double X, double y, double Y) 
 : minX(x),maxX(X),minY(y),maxY(Y) {
                assert(x<=X);
@@ -301,3 +303,4 @@ int generateYConstraints(const int n, Rectangle** rs, Variable** vars, Constrain
        for(i=0;i<m;i++) cs[i]=constraints[i];
        return m;
 }
+}
index 56ee9536a2e7edf90b0766a741ea195e3520731e..8b858af3f0d9bbd1070532addf0c371225e22375 100644 (file)
@@ -13,6 +13,7 @@
 #define SEEN_REMOVEOVERLAP_GENERATE_CONSTRAINTS_H
 #include <iostream>
 
+namespace vpsc {
 class Rectangle {      
        friend std::ostream& operator <<(std::ostream &os, const Rectangle &r);
 public:
@@ -74,5 +75,6 @@ class Constraint;
 int generateXConstraints(const int n, Rectangle** rs, Variable** vars, Constraint** &cs, const bool useNeighbourLists);
 int generateYConstraints(const int n, Rectangle** rs, Variable** vars, Constraint** &cs);
 
+}
 
 #endif // SEEN_REMOVEOVERLAP_GENERATE_CONSTRAINTS_H
index 6f6ace03ae0e88af16cc157dd91eb95071aa718c..78df24b2287c46a725198acc33e35988149838e9 100644 (file)
@@ -24,6 +24,7 @@ using std::endl;
 #endif
 
 #define EXTRA_GAP 0.0001
+using namespace vpsc;
 
 double Rectangle::xBorder=0;
 double Rectangle::yBorder=0;
@@ -55,7 +56,7 @@ void removeRectangleOverlap(unsigned n, Rectangle *rs[], double xBorder, double
        for(int i=0;i<n;i++) {
                oldX[i]=vs[i]->desiredPosition;
        }
-       VPSC vpsc_x(n,vs,m,cs);
+       Solver vpsc_x(n,vs,m,cs);
 #ifdef RECTANGLE_OVERLAP_LOGGING
        ofstream f(LOGFILE,ios::app);
        f<<"Calling VPSC: Horizontal pass 1"<<endl;
@@ -73,7 +74,7 @@ void removeRectangleOverlap(unsigned n, Rectangle *rs[], double xBorder, double
        // one another above are not considered overlapping
        Rectangle::setXBorder(Rectangle::xBorder-EXTRA_GAP);
        m=generateYConstraints(n,rs,vs,cs);
-       VPSC vpsc_y(n,vs,m,cs);
+       Solver vpsc_y(n,vs,m,cs);
 #ifdef RECTANGLE_OVERLAP_LOGGING
        f.open(LOGFILE,ios::app);
        f<<"Calling VPSC: Vertical pass"<<endl;
@@ -91,7 +92,7 @@ void removeRectangleOverlap(unsigned n, Rectangle *rs[], double xBorder, double
        delete [] cs;
        Rectangle::setYBorder(Rectangle::yBorder-EXTRA_GAP);
        m=generateXConstraints(n,rs,vs,cs,false);
-       VPSC vpsc_x2(n,vs,m,cs);
+       Solver vpsc_x2(n,vs,m,cs);
 #ifdef RECTANGLE_OVERLAP_LOGGING
        f.open(LOGFILE,ios::app);
        f<<"Calling VPSC: Horizontal pass 2"<<endl;
index 08b035e3126092fc2f98e8cf4bb15bdfeefacd3b..82f3ef4948e6cd123efefb93b500c1ae7a06a663 100644 (file)
@@ -13,9 +13,9 @@
  * Released under GNU LGPL.  Read the file 'COPYING' for more information.
  */
 
-class Rectangle;
+class vpsc::Rectangle;
 
-void removeRectangleOverlap(unsigned n, Rectangle *rs[], double xBorder, double yBorder);
+void removeRectangleOverlap(unsigned n, vpsc::Rectangle *rs[], double xBorder, double yBorder);
 
 
 #endif /* !REMOVE_RECTANGLE_OVERLAP_H_SEEN */
index 44918951ddf530fe663c7243abd4e40bba55a705..ff0ff96bf373afb016d4dd4f7e232ba0184fcf12 100644 (file)
 #include <sstream>
 #ifdef RECTANGLE_OVERLAP_LOGGING
 #include <fstream>
-using std::ios;
-using std::ofstream;
-using std::endl;
 #endif
+#include <map>
+
+using namespace std;
 
-using std::ostringstream;
-using std::list;
-using std::set;
+namespace vpsc {
 
 static const double ZERO_UPPERBOUND=-0.0000001;
 
-IncVPSC::IncVPSC(const unsigned n, Variable* const vs[], const unsigned m, Constraint *cs[]) 
-       : VPSC(n,vs,m,cs) {
+IncSolver::IncSolver(const unsigned n, Variable* const vs[], const unsigned m, Constraint *cs[]) 
+       : Solver(n,vs,m,cs) {
        inactive.assign(cs,cs+m);
        for(ConstraintList::iterator i=inactive.begin();i!=inactive.end();++i) {
                (*i)->active=false;
        }
 }
-VPSC::VPSC(const unsigned n, Variable* const vs[], const unsigned m, Constraint *cs[]) : m(m), cs(cs), n(n), vs(vs) {
+Solver::Solver(const unsigned n, Variable* const vs[], const unsigned m, Constraint *cs[]) : m(m), cs(cs), n(n), vs(vs) {
        bs=new Blocks(n, vs);
 #ifdef RECTANGLE_OVERLAP_LOGGING
        printBlocks();
-       assert(!constraintGraphIsCyclic(n,vs));
+       //assert(!constraintGraphIsCyclic(n,vs));
 #endif
 }
-VPSC::~VPSC() {
+Solver::~Solver() {
        delete bs;
 }
 
 // useful in debugging
-void VPSC::printBlocks() {
+void Solver::printBlocks() {
 #ifdef RECTANGLE_OVERLAP_LOGGING
        ofstream f(LOGFILE,ios::app);
        for(set<Block*>::iterator i=bs->begin();i!=bs->end();++i) {
@@ -71,7 +69,7 @@ void VPSC::printBlocks() {
 * first) fixing the position of variables inside blocks relative to one
 * another so that constraints internal to the block are satisfied.
 */
-void VPSC::satisfy() {
+void Solver::satisfy() {
        list<Variable*> *vs=bs->totalOrder();
        for(list<Variable*>::iterator i=vs->begin();i!=vs->end();++i) {
                Variable *v=*i;
@@ -93,7 +91,7 @@ void VPSC::satisfy() {
        delete vs;
 }
 
-void VPSC::refine() {
+void Solver::refine() {
        bool solved=false;
        // Solve shouldn't loop indefinately
        // ... but just to make sure we limit the number of iterations
@@ -137,12 +135,12 @@ void VPSC::refine() {
  * refinement is possible by splitting the block. This is done repeatedly
  * until no further improvement is possible.
  */
-void VPSC::solve() {
+void Solver::solve() {
        satisfy();
        refine();
 }
 
-void IncVPSC::solve() {
+void IncSolver::solve() {
 #ifdef RECTANGLE_OVERLAP_LOGGING
        ofstream f(LOGFILE,ios::app);
        f<<"solve_inc()..."<<endl;
@@ -171,7 +169,7 @@ void IncVPSC::solve() {
  * over an active constraint between the two variables.  We choose the 
  * constraint with the most negative lagrangian multiplier. 
  */
-void IncVPSC::satisfy() {
+void IncSolver::satisfy() {
 #ifdef RECTANGLE_OVERLAP_LOGGING
        ofstream f(LOGFILE,ios::app);
        f<<"satisfy_inc()..."<<endl;
@@ -185,6 +183,11 @@ void IncVPSC::satisfy() {
                if(lb != rb) {
                        lb->merge(rb,v);
                } else {
+                       if(lb->isActiveDirectedPathBetween(v->right,v->left)) {
+                               // cycle found, relax the violated, cyclic constraint
+                               v->gap = v->slack();
+                               continue;
+                       }
                        if(splitCtr++>10000) {
                                throw "Cycle Error!";
                        }
@@ -215,7 +218,7 @@ void IncVPSC::satisfy() {
        printBlocks();
 #endif
 }
-void IncVPSC::moveBlocks() {
+void IncSolver::moveBlocks() {
 #ifdef RECTANGLE_OVERLAP_LOGGING
        ofstream f(LOGFILE,ios::app);
        f<<"moveBlocks()..."<<endl;
@@ -229,7 +232,7 @@ void IncVPSC::moveBlocks() {
        f<<"  moved blocks."<<endl;
 #endif
 }
-void IncVPSC::splitBlocks() {
+void IncSolver::splitBlocks() {
 #ifdef RECTANGLE_OVERLAP_LOGGING
        ofstream f(LOGFILE,ios::app);
 #endif
@@ -271,7 +274,7 @@ void IncVPSC::splitBlocks() {
  * Scan constraint list for the most violated constraint, or the first equality
  * constraint
  */
-Constraint* IncVPSC::mostViolated(ConstraintList &l) {
+Constraint* IncSolver::mostViolated(ConstraintList &l) {
        double minSlack = DBL_MAX;
        Constraint* v=NULL;
 #ifdef RECTANGLE_OVERLAP_LOGGING
@@ -304,15 +307,12 @@ Constraint* IncVPSC::mostViolated(ConstraintList &l) {
        return v;
 }
 
-#include <map>
-using std::map;
-using std::vector;
 struct node {
        set<node*> in;
        set<node*> out;
 };
 // useful in debugging - cycles would be BAD
-bool VPSC::constraintGraphIsCyclic(const unsigned n, Variable *vs[]) {
+bool Solver::constraintGraphIsCyclic(const unsigned n, Variable* const vs[]) {
        map<Variable*, node*> varmap;
        vector<node*> graph;
        for(unsigned i=0;i<n;i++) {
@@ -359,7 +359,7 @@ bool VPSC::constraintGraphIsCyclic(const unsigned n, Variable *vs[]) {
 }
 
 // useful in debugging - cycles would be BAD
-bool VPSC::blockGraphIsCyclic() {
+bool Solver::blockGraphIsCyclic() {
        map<Block*, node*> bmap;
        vector<node*> graph;
        for(set<Block*>::const_iterator i=bs->begin();i!=bs->end();++i) {
@@ -414,4 +414,4 @@ bool VPSC::blockGraphIsCyclic() {
        }
        return false;
 }
-
+}
index 4cd5559d600306eed13516225d9389aa226b2909..0f919a22a51a170025f3377d56b142800349fafb 100644 (file)
@@ -21,6 +21,8 @@
 #define SEEN_REMOVEOVERLAP_SOLVE_VPSC_H
 
 #include <vector>
+
+namespace vpsc {
 class Variable;
 class Constraint;
 class Blocks;
@@ -28,13 +30,13 @@ class Blocks;
 /**
  * Variable Placement with Separation Constraints problem instance
  */
-class VPSC {
+class Solver {
 public:
        virtual void satisfy();
        virtual void solve();
 
-       VPSC(const unsigned n, Variable* const vs[], const unsigned m, Constraint *cs[]);
-       virtual ~VPSC();
+       Solver(const unsigned n, Variable* const vs[], const unsigned m, Constraint *cs[]);
+       virtual ~Solver();
        Constraint** getConstraints(unsigned &m) { m=this->m; return cs; }
        const Variable* const * getVariables(unsigned &n) { n=this->n; return vs; }
 protected:
@@ -46,21 +48,22 @@ protected:
        void printBlocks();
 private:
        void refine();
-       bool constraintGraphIsCyclic(const unsigned n, Variable *vs[]);
+       bool constraintGraphIsCyclic(const unsigned n, Variable* const vs[]);
        bool blockGraphIsCyclic();
 };
 
-class IncVPSC : public VPSC {
+class IncSolver : public Solver {
 public:
        unsigned splitCnt;
        void satisfy();
        void solve();
        void moveBlocks();
        void splitBlocks();
-       IncVPSC(const unsigned n, Variable* const vs[], const unsigned m, Constraint *cs[]);
+       IncSolver(const unsigned n, Variable* const vs[], const unsigned m, Constraint *cs[]);
 private:
        typedef std::vector<Constraint*> ConstraintList;
        ConstraintList inactive;
        Constraint* mostViolated(ConstraintList &l);
 };
+}
 #endif // SEEN_REMOVEOVERLAP_SOLVE_VPSC_H
index 1890f788ede978d2836a5c7c4bc5923a52a28425..19dc0746a7f601e58662fb2d38afae2b13307a9b 100644 (file)
@@ -8,8 +8,9 @@
  * Released under GNU LGPL.  Read the file 'COPYING' for more information.
  */
 #include "variable.h"
+namespace vpsc {
 std::ostream& operator <<(std::ostream &os, const Variable &v) {
        os << "(" << v.id << "=" << v.position() << ")";
        return os;
 }
-
+}
index b1ab66c9579f889310c2d5a71a6644dfe6c43f00..d2c689723f49b61df02e5952a5b35d0ccfc609f9 100644 (file)
 
 #include <vector>
 #include <iostream>
-class Block;
-class Constraint;
 #include "block.h"
 
+namespace vpsc {
+
+class Constraint;
 typedef std::vector<Constraint*> Constraints;
 class Variable
 {
@@ -48,4 +49,5 @@ public:
                out.clear();
        }
 };
+}
 #endif // SEEN_REMOVEOVERLAP_VARIABLE_H
index 3a8481db2275e31612b6d090a004e76ef985a028..c640fb407ad308185562dcd1074715a6e55b60b7 100644 (file)
@@ -15,6 +15,8 @@
 #include "libvpsc/generate-constraints.h"
 #include "libvpsc/remove_rectangle_overlap.h"
 
+using vpsc::Rectangle;
+
 /**
 * Takes a list of inkscape items and moves them as little as possible
 * such that rectangular bounding boxes are separated by at least xGap