diff options
| author | Tim Dwyer <tgdwyer@gmail.com> | 2006-07-14 04:09:40 +0000 |
|---|---|---|
| committer | tgdwyer <tgdwyer@users.sourceforge.net> | 2006-07-14 04:09:40 +0000 |
| commit | d18b8150ba16f4a930b213dae1f4fb369cb3d0bf (patch) | |
| tree | 72afddfbcafd6b51e6797a7674c963886cce75b0 /src/libvpsc | |
| parent | * src/libavoid/router.cpp: Fixed a bug in the libavoid function (diff) | |
| download | inkscape-d18b8150ba16f4a930b213dae1f4fb369cb3d0bf.tar.gz inkscape-d18b8150ba16f4a930b213dae1f4fb369cb3d0bf.zip | |
- Connectors with end-markers now constrained to point downwards in graph layout
- vpsc namespace added to libvpsc
(bzr r1408)
Diffstat (limited to 'src/libvpsc')
| -rw-r--r-- | src/libvpsc/block.cpp | 18 | ||||
| -rw-r--r-- | src/libvpsc/block.h | 6 | ||||
| -rw-r--r-- | src/libvpsc/blocks.cpp | 3 | ||||
| -rw-r--r-- | src/libvpsc/blocks.h | 2 | ||||
| -rw-r--r-- | src/libvpsc/constraint.cpp | 2 | ||||
| -rw-r--r-- | src/libvpsc/constraint.h | 2 | ||||
| -rw-r--r-- | src/libvpsc/csolve_VPSC.cpp | 19 | ||||
| -rw-r--r-- | src/libvpsc/csolve_VPSC.h | 28 | ||||
| -rw-r--r-- | src/libvpsc/generate-constraints.cpp | 3 | ||||
| -rw-r--r-- | src/libvpsc/generate-constraints.h | 2 | ||||
| -rw-r--r-- | src/libvpsc/remove_rectangle_overlap.cpp | 7 | ||||
| -rw-r--r-- | src/libvpsc/remove_rectangle_overlap.h | 4 | ||||
| -rw-r--r-- | src/libvpsc/solve_VPSC.cpp | 52 | ||||
| -rw-r--r-- | src/libvpsc/solve_VPSC.h | 15 | ||||
| -rw-r--r-- | src/libvpsc/variable.cpp | 3 | ||||
| -rw-r--r-- | src/libvpsc/variable.h | 6 |
16 files changed, 110 insertions, 62 deletions
diff --git a/src/libvpsc/block.cpp b/src/libvpsc/block.cpp index 69a439cd7..221df536a 100644 --- a/src/libvpsc/block.cpp +++ b/src/libvpsc/block.cpp @@ -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; } +} diff --git a/src/libvpsc/block.h b/src/libvpsc/block.h index 81e6c7637..9c285f311 100644 --- a/src/libvpsc/block.h +++ b/src/libvpsc/block.h @@ -16,10 +16,10 @@ #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 diff --git a/src/libvpsc/blocks.cpp b/src/libvpsc/blocks.cpp index 48f0237bf..fe0caacfc 100644 --- a/src/libvpsc/blocks.cpp +++ b/src/libvpsc/blocks.cpp @@ -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; } +} diff --git a/src/libvpsc/blocks.h b/src/libvpsc/blocks.h index 0be1d7636..72363ef66 100644 --- a/src/libvpsc/blocks.h +++ b/src/libvpsc/blocks.h @@ -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 diff --git a/src/libvpsc/constraint.cpp b/src/libvpsc/constraint.cpp index 7c200878b..af5da941a 100644 --- a/src/libvpsc/constraint.cpp +++ b/src/libvpsc/constraint.cpp @@ -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; } +} diff --git a/src/libvpsc/constraint.h b/src/libvpsc/constraint.h index 3da7449cd..c73776daf 100644 --- a/src/libvpsc/constraint.h +++ b/src/libvpsc/constraint.h @@ -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 diff --git a/src/libvpsc/csolve_VPSC.cpp b/src/libvpsc/csolve_VPSC.cpp index b78b01054..bd7db5ab2 100644 --- a/src/libvpsc/csolve_VPSC.cpp +++ b/src/libvpsc/csolve_VPSC.cpp @@ -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) { diff --git a/src/libvpsc/csolve_VPSC.h b/src/libvpsc/csolve_VPSC.h index cd879effe..81e50d990 100644 --- a/src/libvpsc/csolve_VPSC.h +++ b/src/libvpsc/csolve_VPSC.h @@ -11,19 +11,26 @@ #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 diff --git a/src/libvpsc/generate-constraints.cpp b/src/libvpsc/generate-constraints.cpp index 312ad960b..3b69e7968 100644 --- a/src/libvpsc/generate-constraints.cpp +++ b/src/libvpsc/generate-constraints.cpp @@ -20,10 +20,12 @@ 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; } +} diff --git a/src/libvpsc/generate-constraints.h b/src/libvpsc/generate-constraints.h index 56ee9536a..8b858af3f 100644 --- a/src/libvpsc/generate-constraints.h +++ b/src/libvpsc/generate-constraints.h @@ -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 diff --git a/src/libvpsc/remove_rectangle_overlap.cpp b/src/libvpsc/remove_rectangle_overlap.cpp index 6f6ace03a..78df24b22 100644 --- a/src/libvpsc/remove_rectangle_overlap.cpp +++ b/src/libvpsc/remove_rectangle_overlap.cpp @@ -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; diff --git a/src/libvpsc/remove_rectangle_overlap.h b/src/libvpsc/remove_rectangle_overlap.h index 08b035e31..82f3ef494 100644 --- a/src/libvpsc/remove_rectangle_overlap.h +++ b/src/libvpsc/remove_rectangle_overlap.h @@ -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 */ diff --git a/src/libvpsc/solve_VPSC.cpp b/src/libvpsc/solve_VPSC.cpp index 44918951d..ff0ff96bf 100644 --- a/src/libvpsc/solve_VPSC.cpp +++ b/src/libvpsc/solve_VPSC.cpp @@ -19,37 +19,35 @@ #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; } - +} diff --git a/src/libvpsc/solve_VPSC.h b/src/libvpsc/solve_VPSC.h index 4cd5559d6..0f919a22a 100644 --- a/src/libvpsc/solve_VPSC.h +++ b/src/libvpsc/solve_VPSC.h @@ -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 diff --git a/src/libvpsc/variable.cpp b/src/libvpsc/variable.cpp index 1890f788e..19dc0746a 100644 --- a/src/libvpsc/variable.cpp +++ b/src/libvpsc/variable.cpp @@ -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; } - +} diff --git a/src/libvpsc/variable.h b/src/libvpsc/variable.h index b1ab66c95..d2c689723 100644 --- a/src/libvpsc/variable.h +++ b/src/libvpsc/variable.h @@ -12,10 +12,11 @@ #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 |
