summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 945a51e)
raw | patch | inline | side by side (parent: 945a51e)
| author | tgdwyer <tgdwyer@users.sourceforge.net> | |
| Wed, 10 May 2006 07:13:45 +0000 (07:13 +0000) | ||
| committer | tgdwyer <tgdwyer@users.sourceforge.net> | |
| Wed, 10 May 2006 07:13:45 +0000 (07:13 +0000) |
I can't reproduce the problem, however solve_VPSC code in inkscape
was getting quite out of date with that in www.sf.net/projects/adaptagrams.
I've updated the code, which may fix the problem, or at least if it's
reported again then I'll know it's still an issue.
was getting quite out of date with that in www.sf.net/projects/adaptagrams.
I've updated the code, which may fix the problem, or at least if it's
reported again then I'll know it's still an issue.
17 files changed:
index 7a2ab53af06afa0053f1d1d35e32452fa364051e..042d9fc3c24bf2eb4a1f2bb3754b4c5a5be96ccb 100644 (file)
/**
- * \brief Remove overlaps function
+ * \brief A block is a group of variables that must be moved together to improve
+ * the goal function without violating already active constraints.
+ * The variables in a block are spanned by a tree of active constraints.
*
* Authors:
* Tim Dwyer <tgdwyer@gmail.com>
*
* Copyright (C) 2005 Authors
*
- * Released under GNU GPL. Read the file 'COPYING' for more information.
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
#include <cassert>
+#include "pairingheap/PairingHeap.h"
#include "constraint.h"
#include "block.h"
#include "blocks.h"
-#include "pairingheap/PairingHeap.h"
#ifdef RECTANGLE_OVERLAP_LOGGING
#include <fstream>
using std::ios;
#endif
using std::vector;
+typedef vector<Constraint*>::iterator Cit;
+
void Block::addVariable(Variable *v) {
v->block=this;
vars->push_back(v);
double Block::desiredWeightedPosition() {
double wp = 0;
- for (vector<Variable*>::iterator v=vars->begin();v!=vars->end();v++) {
+ for (vector<Variable*>::iterator v=vars->begin();v!=vars->end();++v) {
wp += ((*v)->desiredPosition - (*v)->offset) * (*v)->weight;
}
return wp;
void Block::setUpConstraintHeap(PairingHeap<Constraint*>* &h,bool in) {
delete h;
h = new PairingHeap<Constraint*>(&compareConstraints);
- for (vector<Variable*>::iterator i=vars->begin();i!=vars->end();i++) {
+ for (vector<Variable*>::iterator i=vars->begin();i!=vars->end();++i) {
Variable *v=*i;
vector<Constraint*> *cs=in?&(v->in):&(v->out);
- for (vector<Constraint*>::iterator j=cs->begin();j!=cs->end();j++) {
+ for (Cit j=cs->begin();j!=cs->end();++j) {
Constraint *c=*j;
c->timeStamp=blockTimeCtr;
if (c->left->block != this && in || c->right->block != this && !in) {
}
}
}
+void Block::merge(Block* b, Constraint* c) {
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" merging on: "<<*c<<",c->left->offset="<<c->left->offset<<",c->right->offset="<<c->right->offset<<endl;
+#endif
+ double dist = c->right->offset - c->left->offset - c->gap;
+ Block *l=c->left->block;
+ Block *r=c->right->block;
+ if (vars->size() < b->vars->size()) {
+ r->merge(l,c,dist);
+ } else {
+ l->merge(r,c,-dist);
+ }
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ f<<" merged block="<<(b->deleted?*this:*b)<<endl;
+#endif
+}
/**
* Merges b into this block across c. Can be either a
* right merge or a left merge
* @param distance separation required to satisfy c
*/
void Block::merge(Block *b, Constraint *c, double dist) {
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" merging: "<<*b<<"dist="<<dist<<endl;
+#endif
c->active=true;
wposn+=b->wposn-dist*b->weight;
weight+=b->weight;
posn=wposn/weight;
- for(vector<Variable*>::iterator i=b->vars->begin();i!=b->vars->end();i++) {
+ for(vector<Variable*>::iterator i=b->vars->begin();i!=b->vars->end();++i) {
Variable *v=*i;
v->block=this;
v->offset+=dist;
vars->push_back(v);
}
+ b->deleted=true;
}
void Block::mergeIn(Block *b) {
break;
}
}
- for(vector<Constraint*>::iterator i=outOfDate.begin();i!=outOfDate.end();i++) {
+ for(Cit i=outOfDate.begin();i!=outOfDate.end();++i) {
v=*i;
v->timeStamp=blockTimeCtr;
in->insert(v);
// in min_lm
double Block::compute_dfdv(Variable *v, Variable *u, Constraint *&min_lm) {
double dfdv=v->weight*(v->position() - v->desiredPosition);
- for(vector<Constraint*>::iterator it=v->out.begin();it!=v->out.end();it++) {
+ for(Cit it=v->out.begin();it!=v->out.end();++it) {
Constraint *c=*it;
if(canFollowRight(c,u)) {
dfdv+=c->lm=compute_dfdv(c->right,v,min_lm);
- if(min_lm==NULL||c->lm<min_lm->lm) min_lm=c;
+ if(!c->equality&&(min_lm==NULL||c->lm<min_lm->lm)) min_lm=c;
}
}
- for(vector<Constraint*>::iterator it=v->in.begin();it!=v->in.end();it++) {
+ for(Cit it=v->in.begin();it!=v->in.end();++it) {
Constraint *c=*it;
if(canFollowLeft(c,u)) {
dfdv-=c->lm=-compute_dfdv(c->left,v,min_lm);
- if(min_lm==NULL||c->lm<min_lm->lm) min_lm=c;
+ if(!c->equality&&(min_lm==NULL||c->lm<min_lm->lm)) min_lm=c;
}
}
return dfdv;
}
+
+// computes dfdv for each variable and uses the sum of dfdv on either side of
+// the constraint c to compute the lagrangian multiplier lm_c.
+// The top level v and r are variables between which we want to find the
+// constraint with the smallest lm.
+// When we find r we pass NULL to subsequent recursive calls,
+// thus r=NULL indicates constraints are not on the shortest path.
+// Similarly, m is initially NULL and is only assigned a value if the next
+// variable to be visited is r or if a possible min constraint is returned from
+// a nested call (rather than NULL).
+// Then, the search for the m with minimum lm occurs as we return from
+// the recursion (checking only constraints traversed left-to-right
+// in order to avoid creating any new violations).
+// We also do not consider equality constraints as potential split points
+Block::Pair Block::compute_dfdv_between(Variable* r, Variable* v, Variable* u,
+ Direction dir = NONE, bool changedDirection = false) {
+ double dfdv=v->weight*(v->position() - v->desiredPosition);
+ Constraint *m=NULL;
+ for(Cit it(v->in.begin());it!=v->in.end();++it) {
+ Constraint *c=*it;
+ if(canFollowLeft(c,u)) {
+ if(dir==RIGHT) {
+ changedDirection = true;
+ }
+ if(c->left==r) {
+ r=NULL;
+ if(!c->equality) m=c;
+ }
+ Pair p=compute_dfdv_between(r,c->left,v,
+ LEFT,changedDirection);
+ dfdv -= c->lm = -p.first;
+ if(r && p.second)
+ m = p.second;
+ }
+ }
+ for(Cit it(v->out.begin());it!=v->out.end();++it) {
+ Constraint *c=*it;
+ if(canFollowRight(c,u)) {
+ if(dir==LEFT) {
+ changedDirection = true;
+ }
+ if(c->right==r) {
+ r=NULL;
+ if(!c->equality) m=c;
+ }
+ Pair p=compute_dfdv_between(r,c->right,v,
+ RIGHT,changedDirection);
+ dfdv += c->lm = p.first;
+ if(r && p.second)
+ m = changedDirection && !c->equality && c->lm < p.second->lm
+ ? c
+ : p.second;
+ }
+ }
+ return Pair(dfdv,m);
+}
+
// resets LMs for all active constraints to 0 by
// traversing active constraint tree starting from v,
// not back tracking over u
void Block::reset_active_lm(Variable *v, Variable *u) {
- for(vector<Constraint*>::iterator it=v->out.begin();it!=v->out.end();it++) {
+ for(Cit it=v->out.begin();it!=v->out.end();++it) {
Constraint *c=*it;
if(canFollowRight(c,u)) {
c->lm=0;
reset_active_lm(c->right,v);
}
}
- for(vector<Constraint*>::iterator it=v->in.begin();it!=v->in.end();it++) {
+ for(Cit it=v->in.begin();it!=v->in.end();++it) {
Constraint *c=*it;
if(canFollowLeft(c,u)) {
c->lm=0;
compute_dfdv(vars->front(),NULL,min_lm);
return min_lm;
}
+Constraint *Block::findMinLMBetween(Variable* lv, Variable* rv) {
+ Constraint *min_lm=NULL;
+ reset_active_lm(vars->front(),NULL);
+ min_lm=compute_dfdv_between(rv,lv,NULL).second;
+ return min_lm;
+}
// populates block b by traversing the active constraint tree adding variables as they're
// visited. Starts from variable v and does not backtrack over variable u.
void Block::populateSplitBlock(Block *b, Variable *v, Variable *u) {
b->addVariable(v);
- for (vector<Constraint*>::iterator c=v->in.begin();c!=v->in.end();c++) {
+ for (Cit c=v->in.begin();c!=v->in.end();++c) {
if (canFollowLeft(*c,u))
populateSplitBlock(b, (*c)->left, v);
}
- for (vector<Constraint*>::iterator c=v->out.begin();c!=v->out.end();c++) {
+ for (Cit c=v->out.begin();c!=v->out.end();++c) {
if (canFollowRight(*c,u))
populateSplitBlock(b, (*c)->right, v);
}
}
+/**
+ * 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
+ * with min lagrangrian multiplier and split at that point.
+ * Returns the split constraint
+ */
+Constraint* Block::splitBetween(Variable* vl, Variable* vr, Block* &lb, Block* &rb) {
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" need to split between: "<<*vl<<" and "<<*vr<<endl;
+#endif
+ Constraint *c=findMinLMBetween(vl, vr);
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ f<<" going to split on: "<<*c<<endl;
+#endif
+ split(lb,rb,c);
+ deleted = true;
+ return c;
+}
/**
* Creates two new blocks, l and r, and splits this block across constraint c,
* placing the left subtree of constraints (and associated variables) into l
- * and the right into r
+ * and the right into r.
*/
-void Block::split(Block *&l, Block *&r, Constraint *c) {
+void Block::split(Block* &l, Block* &r, Constraint* c) {
c->active=false;
l=new Block();
populateSplitBlock(l,c->left,c->right);
*/
double Block::cost() {
double c = 0;
- for (vector<Variable*>::iterator v=vars->begin();v!=vars->end();v++) {
+ for (vector<Variable*>::iterator v=vars->begin();v!=vars->end();++v) {
double diff = (*v)->position() - (*v)->desiredPosition;
c += (*v)->weight * diff * diff;
}
ostream& operator <<(ostream &os, const Block &b)
{
os<<"Block:";
- for(vector<Variable*>::iterator v=b.vars->begin();v!=b.vars->end();v++) {
+ for(vector<Variable*>::iterator v=b.vars->begin();v!=b.vars->end();++v) {
os<<" "<<**v;
}
+ if(b.deleted) {
+ os<<" Deleted!";
+ }
return os;
}
index 7905309bb08ffa1ee220edbc965c61164def462b..997009a553fa14a8a28868a1b0ca787df76f346a 100644 (file)
/**
- * \brief Remove overlaps function
+ * \brief A block is a group of variables that must be moved together to improve
+ * the goal function without violating already active constraints.
+ * The variables in a block are spanned by a tree of active constraints.
*
* Authors:
* Tim Dwyer <tgdwyer@gmail.com>
*
* Copyright (C) 2005 Authors
*
- * Released under GNU GPL. Read the file 'COPYING' for more information.
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
#ifndef SEEN_REMOVEOVERLAP_BLOCK_H
double wposn;
Block(Variable *v=NULL);
~Block(void);
- Constraint *findMinLM();
- Constraint *findMinInConstraint();
- Constraint *findMinOutConstraint();
+ Constraint* findMinLM();
+ Constraint* findMinLMBetween(Variable* lv, Variable* rv);
+ Constraint* findMinInConstraint();
+ Constraint* findMinOutConstraint();
void deleteMinInConstraint();
void deleteMinOutConstraint();
double desiredWeightedPosition();
void merge(Block *b, Constraint *c, double dist);
+ void merge(Block *b, Constraint *c);
void mergeIn(Block *b);
void mergeOut(Block *b);
void split(Block *&l, Block *&r, Constraint *c);
+ Constraint* splitBetween(Variable* vl, Variable* vr, Block* &lb, Block* &rb);
void setUpInConstraints();
void setUpOutConstraints();
double cost();
PairingHeap<Constraint*> *in;
PairingHeap<Constraint*> *out;
private:
+ typedef enum {NONE, LEFT, RIGHT} Direction;
+ typedef std::pair<double, Constraint*> Pair;
void reset_active_lm(Variable *v, Variable *u);
double compute_dfdv(Variable *v, Variable *u, Constraint *&min_lm);
+ Pair compute_dfdv_between(
+ Variable*, Variable*, Variable*, Direction, bool);
bool canFollowLeft(Constraint *c, Variable *last);
bool canFollowRight(Constraint *c, Variable *last);
void populateSplitBlock(Block *b, Variable *v, Variable *u);
index 13da8e15ed517c56c7d578a8fdda194c99850a8f..62b7e99f569d9c6105825334fc091763972a3f6f 100644 (file)
*
* Copyright (C) 2005 Authors
*
- * Released under GNU GPL. Read the file 'COPYING' for more information.
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
#include "blocks.h"
long blockTimeCtr;
-Blocks::Blocks(Variable *vs[], const int n) : vs(vs),nvs(n) {
+Blocks::Blocks(const int n, Variable *vs[]) : vs(vs),nvs(n) {
blockTimeCtr=0;
for(int i=0;i<nvs;i++) {
insert(new Block(vs[i]));
Blocks::~Blocks(void)
{
blockTimeCtr=0;
- for(set<Block*>::iterator i=begin();i!=end();i++) {
+ for(set<Block*>::iterator i=begin();i!=end();++i) {
delete *i;
}
clear();
void Blocks::dfsVisit(Variable *v, list<Variable*> *order) {
v->visited=true;
vector<Constraint*>::iterator it=v->out.begin();
- for(;it!=v->out.end();it++) {
+ for(;it!=v->out.end();++it) {
Constraint *c=*it;
if(!c->right->visited) {
dfsVisit(c->right, order);
//erase(doomed);
}
void Blocks::cleanup() {
- vector<Block*> bcopy(size());
- copy(begin(),end(),bcopy.begin());
- for(vector<Block*>::iterator i=bcopy.begin();i!=bcopy.end();i++) {
+ vector<Block*> bcopy(begin(),end());
+ for(vector<Block*>::iterator i=bcopy.begin();i!=bcopy.end();++i) {
Block *b=*i;
if(b->deleted) {
erase(b);
*/
double Blocks::cost() {
double c = 0;
- for(set<Block*>::iterator i=begin();i!=end();i++) {
+ for(set<Block*>::iterator i=begin();i!=end();++i) {
c += (*i)->cost();
}
return c;
index 437af63106dee6e2289f6e9c94081903a5eb6aa6..1a603eb41be27fd8e11cd9b43be3b324302d909f 100644 (file)
/**
- * \brief Remove overlaps function
+ * \brief A block structure defined over the variables
+ *
+ * A block structure defined over the variables such that each block contains
+ * 1 or more variables, with the invariant that all constraints inside a block
+ * are satisfied by keeping the variables fixed relative to one another
*
* Authors:
* Tim Dwyer <tgdwyer@gmail.com>
*
* Copyright (C) 2005 Authors
*
- * Released under GNU GPL. Read the file 'COPYING' for more information.
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
#ifndef SEEN_REMOVEOVERLAP_BLOCKS_H
class Blocks : public std::set<Block*>
{
public:
- Blocks(Variable *vs[], const int n);
+ Blocks(const int n, Variable *vs[]);
~Blocks(void);
void mergeLeft(Block *r);
void mergeRight(Block *l);
index bb889c4d9c8c301b5ce31ffef88e7985cb08446b..7c200878b6bbdb2dfbbd4dbf59448d8f2c626a78 100644 (file)
/**
- * \brief Remove overlaps function
+ * \brief A constraint determines a minimum or exact spacing required between
+ * two variables.
*
* Authors:
* Tim Dwyer <tgdwyer@gmail.com>
*
* Copyright (C) 2005 Authors
*
- * Released under GNU GPL. Read the file 'COPYING' for more information.
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
#include "constraint.h"
#include <cassert>
-Constraint::Constraint(Variable *left, Variable *right, double gap)
+Constraint::Constraint(Variable *left, Variable *right, double gap, bool equality)
: left(left),
right(right),
gap(gap),
timeStamp(0),
active(false),
- visited(false)
+ visited(false),
+ equality(equality)
{
left->out.push_back(this);
right->in.push_back(this);
}
+Constraint::~Constraint() {
+ Constraints::iterator i;
+ for(i=left->out.begin(); i!=left->out.end(); i++) {
+ if(*i==this) break;
+ }
+ left->out.erase(i);
+ for(i=right->in.begin(); i!=right->in.end(); i++) {
+ if(*i==this) break;
+ }
+ right->in.erase(i);
+}
std::ostream& operator <<(std::ostream &os, const Constraint &c)
{
- os<<*c.left<<"+"<<c.gap<<"<="<<*c.right<<"("<<c.slack()<<"):lts="<<c.left->block->timeStamp<<",cts="<<c.timeStamp;
+ if(&c==NULL) {
+ os<<"NULL";
+ } else {
+ const char *type=c.equality?"=":"<=";
+ os<<*c.left<<"+"<<c.gap<<type<<*c.right<<"("<<c.slack()<<")"<<(c.active?"-active":"");
+ }
return os;
}
index de8ccebd48763373c27db7fe8a1cba86c507ccc5..b207932b2277622bcbaf646ced4dc1bf9c47c9a7 100644 (file)
/**
- * \brief Remove overlaps function
+ * \brief A constraint determines a minimum or exact spacing required between
+ * two variables.
*
* Authors:
* Tim Dwyer <tgdwyer@gmail.com>
*
* Copyright (C) 2005 Authors
*
- * Released under GNU GPL. Read the file 'COPYING' for more information.
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
#ifndef SEEN_REMOVEOVERLAP_CONSTRAINT_H
Variable *right;
double gap;
double lm;
- Constraint(Variable *left, Variable *right, double gap);
- ~Constraint(void){};
- inline double slack() const { return right->position() - gap - left->position(); }
- //inline bool operator<(Constraint const &o) const { return slack() < o.slack(); }
+ Constraint(Variable *left, Variable *right, double gap, bool equality=false);
+ ~Constraint();
+ inline double Constraint::slack() const { return right->position() - gap - left->position(); }
long timeStamp;
bool active;
bool visited;
+ bool equality;
};
#include <float.h>
#include "block.h"
diff --git a/src/removeoverlap/generate-constraints.cpp b/src/removeoverlap/generate-constraints.cpp
index a8bfe28e7eaa20ef6ce8b462a9587bdf91aa7067..312ad960b92d09ae26b490c69095e6f9de08a1aa 100644 (file)
/**
- * \brief Remove overlaps function
+ * \brief Functions to automatically generate constraints for the
+ * rectangular node overlap removal problem.
*
* Authors:
* Tim Dwyer <tgdwyer@gmail.com>
*
* Copyright (C) 2005 Authors
*
- * Released under GNU GPL. Read the file 'COPYING' for more information.
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
#include <set>
void setNeighbours(NodeSet *left, NodeSet *right) {
leftNeighbours=left;
rightNeighbours=right;
- for(NodeSet::iterator i=left->begin();i!=left->end();i++) {
+ for(NodeSet::iterator i=left->begin();i!=left->end();++i) {
Node *v=*(i);
v->addRightNeighbour(this);
}
- for(NodeSet::iterator i=right->begin();i!=right->end();i++) {
+ for(NodeSet::iterator i=right->begin();i!=right->end();++i) {
Node *v=*(i);
v->addLeftNeighbour(this);
}
NodeSet* getRightNeighbours(NodeSet &scanline,Node *v) {
NodeSet *rightv = new NodeSet;
NodeSet::iterator i=scanline.find(v);
- for(i++;i!=scanline.end(); i++) {
+ for(++i;i!=scanline.end(); ++i) {
Node *u=*(i);
if(u->r->overlapX(v->r)<=0) {
rightv->insert(u);
}
/**
- * Prepares variables and constraints in order to apply VPSC horizontally.
+ * Prepares constraints in order to apply VPSC horizontally. Assumes variables have already been created.
* useNeighbourLists determines whether or not a heuristic is used to deciding whether to resolve
* all overlap in the x pass, or leave some overlaps for the y pass.
*/
-int generateXConstraints(Rectangle *rs[], double weights[], const int n, Variable **&vars, Constraint **&cs, bool useNeighbourLists) {
+int generateXConstraints(const int n, Rectangle** rs, Variable** vars, Constraint** &cs, const bool useNeighbourLists) {
events=new Event*[2*n];
int i,m,ctr=0;
- vector<Constraint*> constraints;
- vars=new Variable*[n];
for(i=0;i<n;i++) {
- vars[i]=new Variable(i,rs[i]->getCentreX(),weights[i]);
+ vars[i]->desiredPosition=rs[i]->getCentreX();
Node *v = new Node(vars[i],rs[i],rs[i]->getCentreX());
events[ctr++]=new Event(Open,v,rs[i]->getMinY());
events[ctr++]=new Event(Close,v,rs[i]->getMaxY());
@@ -177,6 +176,7 @@ int generateXConstraints(Rectangle *rs[], double weights[], const int n, Variabl
qsort((Event*)events, (size_t)2*n, sizeof(Event*), compare_events );
NodeSet scanline;
+ vector<Constraint*> constraints;
for(i=0;i<2*n;i++) {
Event *e=events[i];
Node *v=e->v;
@@ -247,21 +247,20 @@ int generateXConstraints(Rectangle *rs[], double weights[], const int n, Variabl
}
/**
- * Prepares variables and constraints in order to apply VPSC vertically to remove ALL overlap.
+ * Prepares constraints in order to apply VPSC vertically to remove ALL overlap.
*/
-int generateYConstraints(Rectangle *rs[], double weights[], const int n, Variable **&vars, Constraint **&cs) {
+int generateYConstraints(const int n, Rectangle** rs, Variable** vars, Constraint** &cs) {
events=new Event*[2*n];
int ctr=0,i,m;
- vector<Constraint*> constraints;
- vars=new Variable*[n];
for(i=0;i<n;i++) {
- vars[i]=new Variable(i,rs[i]->getCentreY(),weights[i]);
+ vars[i]->desiredPosition=rs[i]->getCentreY();
Node *v = new Node(vars[i],rs[i],rs[i]->getCentreY());
events[ctr++]=new Event(Open,v,rs[i]->getMinX());
events[ctr++]=new Event(Close,v,rs[i]->getMaxX());
}
qsort((Event*)events, (size_t)2*n, sizeof(Event*), compare_events );
NodeSet scanline;
+ vector<Constraint*> constraints;
for(i=0;i<2*n;i++) {
Event *e=events[i];
Node *v=e->v;
index ad9ccb1f9eb3b0f3d4c4e807e8faaf00813a5eec..56ee9536a2e7edf90b0766a741ea195e3520731e 100644 (file)
/**
- * \brief Remove overlaps function
+ * \brief Functions to automatically generate constraints for the
+ * rectangular node overlap removal problem.
*
* Authors:
* Tim Dwyer <tgdwyer@gmail.com>
*
* Copyright (C) 2005 Authors
*
- * Released under GNU GPL. Read the file 'COPYING' for more information.
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
-
#ifndef SEEN_REMOVEOVERLAP_GENERATE_CONSTRAINTS_H
#define SEEN_REMOVEOVERLAP_GENERATE_CONSTRAINTS_H
#include <iostream>
class Constraint;
// returns number of constraints generated
-int generateXConstraints(Rectangle *rs[], double weights[], const int n, Variable **&vs, Constraint **&cs,bool useNeighbourLists);
+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);
-int generateYConstraints(Rectangle *rs[], double weights[], const int n, Variable **&vs, Constraint **&cs);
#endif // SEEN_REMOVEOVERLAP_GENERATE_CONSTRAINTS_H
diff --git a/src/removeoverlap/remove_rectangle_overlap-test.cpp b/src/removeoverlap/remove_rectangle_overlap-test.cpp
index 9999d027e7d7b58bcb48e313738d50176a735e02..87cf4cbb055826f2d67d55ebaa17ac7b4df3e8fa 100644 (file)
rect2coords[i][2],
rect2coords[i][3]);
}
- removeRectangleOverlap(rs, n_rects, 0.0, 0.0);
+ removeRectangleOverlap(n_rects,rs,0.0, 0.0);
for (unsigned i = 0; i < n_rects; ++i) {
UTEST_ASSERT(possibly_eq(rs[i]->width(), (rect2coords[i][1] -
rect2coords[i][0] )));
diff --git a/src/removeoverlap/remove_rectangle_overlap.cpp b/src/removeoverlap/remove_rectangle_overlap.cpp
index 9f98d5811cf98c63edf41eac0aee00fcf1ebf8c5..6f6ace03ae0e88af16cc157dd91eb95071aa718c 100755 (executable)
+/**
+ * \brief remove overlaps between a set of rectangles.
+ *
+ * Authors:
+ * Tim Dwyer <tgdwyer@gmail.com>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
+ */
+
#include <iostream>
#include <cassert>
#include "generate-constraints.h"
* x-positions - this corrects the case where rectangles were moved
* too much in the first pass.
*/
-void removeRectangleOverlap(Rectangle *rs[], int n, double xBorder, double yBorder) {
+void removeRectangleOverlap(unsigned n, Rectangle *rs[], double xBorder, double yBorder) {
assert(0 <= n);
try {
// The extra gap avoids numerical imprecision problems
Rectangle::setXBorder(xBorder+EXTRA_GAP);
Rectangle::setYBorder(yBorder+EXTRA_GAP);
- double *ws=new double[n];
+ Variable **vs=new Variable*[n];
for(int i=0;i<n;i++) {
- ws[i]=1;
+ vs[i]=new Variable(i,0,1);
}
- Variable **vs;
Constraint **cs;
double *oldX = new double[n];
- int m=generateXConstraints(rs,ws,n,vs,cs,true);
+ int m=generateXConstraints(n,rs,vs,cs,true);
for(int i=0;i<n;i++) {
oldX[i]=vs[i]->desiredPosition;
}
- VPSC vpsc_x(vs,n,cs,m);
+ VPSC vpsc_x(n,vs,m,cs);
#ifdef RECTANGLE_OVERLAP_LOGGING
ofstream f(LOGFILE,ios::app);
f<<"Calling VPSC: Horizontal pass 1"<<endl;
vpsc_x.solve();
for(int i=0;i<n;i++) {
rs[i]->moveCentreX(vs[i]->position());
- delete vs[i];
}
- delete [] vs;
for(int i = 0; i < m; ++i) {
delete cs[i];
}
// Removing the extra gap here ensures things that were moved to be adjacent to
// one another above are not considered overlapping
Rectangle::setXBorder(Rectangle::xBorder-EXTRA_GAP);
- m=generateYConstraints(rs,ws,n,vs,cs);
- VPSC vpsc_y(vs,n,cs,m);
+ m=generateYConstraints(n,rs,vs,cs);
+ VPSC vpsc_y(n,vs,m,cs);
#ifdef RECTANGLE_OVERLAP_LOGGING
f.open(LOGFILE,ios::app);
f<<"Calling VPSC: Vertical pass"<<endl;
@@ -75,34 +83,31 @@ void removeRectangleOverlap(Rectangle *rs[], int n, double xBorder, double yBord
for(int i=0;i<n;i++) {
rs[i]->moveCentreY(vs[i]->position());
rs[i]->moveCentreX(oldX[i]);
- delete vs[i];
}
- delete [] vs;
delete [] oldX;
for(int i = 0; i < m; ++i) {
delete cs[i];
}
delete [] cs;
Rectangle::setYBorder(Rectangle::yBorder-EXTRA_GAP);
- m=generateXConstraints(rs,ws,n,vs,cs,false);
- VPSC vpsc_x2(vs,n,cs,m);
+ m=generateXConstraints(n,rs,vs,cs,false);
+ VPSC vpsc_x2(n,vs,m,cs);
#ifdef RECTANGLE_OVERLAP_LOGGING
f.open(LOGFILE,ios::app);
f<<"Calling VPSC: Horizontal pass 2"<<endl;
f.close();
#endif
vpsc_x2.solve();
+ for(int i = 0; i < m; ++i) {
+ delete cs[i];
+ }
+ delete [] cs;
for(int i=0;i<n;i++) {
rs[i]->moveCentreX(vs[i]->position());
delete vs[i];
}
delete [] vs;
- for(int i = 0; i < m; ++i) {
- delete cs[i];
- }
- delete [] cs;
- delete [] ws;
- } catch (char *str) {
+ } catch (char const *str) {
std::cerr<<str<<std::endl;
for(int i=0;i<n;i++) {
std::cerr << *rs[i]<<std::endl;
diff --git a/src/removeoverlap/remove_rectangle_overlap.h b/src/removeoverlap/remove_rectangle_overlap.h
index 9dc84f83a1b846a7413d89dcdfcfdc3970ede3e4..08b035e3126092fc2f98e8cf4bb15bdfeefacd3b 100755 (executable)
*
* Copyright (C) 2005 Authors
*
- * Released under GNU GPL. Read the file 'COPYING' for more information.
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
class Rectangle;
-void removeRectangleOverlap(Rectangle *rs[], int n, double xBorder, double yBorder);
+void removeRectangleOverlap(unsigned n, Rectangle *rs[], double xBorder, double yBorder);
#endif /* !REMOVE_RECTANGLE_OVERLAP_H_SEEN */
index 9d7beb45fa2d36b4754537d3e9f1e429d9aa79cb..d79fa9eab3eba284e7bddd31c2d2fea5cf27643d 100644 (file)
*
* Copyright (C) 2005 Authors
*
-* Released under GNU GPL. Read the file 'COPYING' for more information.
+* Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
#include "util/glib-list-iterators.h"
#include "sp-item.h"
std::list<SPItem *> selected;
selected.insert<GSListConstIterator<SPItem *> >(selected.end(), items, NULL);
if (selected.empty()) return;
- int n=selected.size();
+ unsigned n=selected.size();
//Check 2 or more selected objects
if (n < 2) return;
rs[i++] = new Rectangle(min[X], max[X],
min[Y], max[Y]);
}
- removeRectangleOverlap(rs, n, 0.0, 0.0);
+ removeRectangleOverlap(n, rs, 0.0, 0.0);
i=0;
for (std::list<SPItem *>::iterator it(selected.begin());
it != selected.end();
index b904f52f124e73319bea7503928aaf640bbe68e9..2fb26e79451d5ecea322a64456bc1285ebaaed37 100644 (file)
*
* Copyright (C) 2005 Authors
*
- * Released under GNU GPL. Read the file 'COPYING' for more information.
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
#ifndef SEEN_REMOVEOVERLAP_H
index f2a7f0e85871521d73f0521db663eef5d3583d95..21865c518ffdffc97a4ca4d5a4ef339d3700144b 100644 (file)
/**
- * \brief Remove overlaps function
+ * \brief Solve an instance of the "Variable Placement with Separation
+ * Constraints" problem.
*
* Authors:
* Tim Dwyer <tgdwyer@gmail.com>
*
* Copyright (C) 2005 Authors
*
- * Released under GNU GPL. Read the file 'COPYING' for more information.
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
#include <cassert>
#include "block.h"
#include "blocks.h"
#include "solve_VPSC.h"
+#include <math.h>
+#include <sstream>
#ifdef RECTANGLE_OVERLAP_LOGGING
#include <fstream>
using std::ios;
using std::endl;
#endif
+using std::ostringstream;
using std::list;
using std::set;
-VPSC::VPSC(Variable *vs[], const int n, Constraint *cs[], const int m) : cs(cs), m(m) {
- //assert(!constraintGraphIsCyclic(vs,n));
- bs=new Blocks(vs,n);
+IncVPSC::IncVPSC(const unsigned n, Variable *vs[], const unsigned m, Constraint *cs[])
+ : VPSC(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 *vs[], const unsigned m, Constraint *cs[]) : cs(cs), m(m), vs(vs) {
+ bs=new Blocks(n, vs);
#ifdef RECTANGLE_OVERLAP_LOGGING
printBlocks();
+ assert(!constraintGraphIsCyclic(n,vs));
#endif
}
VPSC::~VPSC() {
void VPSC::printBlocks() {
#ifdef RECTANGLE_OVERLAP_LOGGING
ofstream f(LOGFILE,ios::app);
- for(set<Block*>::iterator i=bs->begin();i!=bs->end();i++) {
+ for(set<Block*>::iterator i=bs->begin();i!=bs->end();++i) {
Block *b=*i;
f<<" "<<*b<<endl;
}
- for(int i=0;i<m;i++) {
+ for(unsigned i=0;i<m;i++) {
f<<" "<<*cs[i]<<endl;
}
#endif
*/
void VPSC::satisfy() {
list<Variable*> *vs=bs->totalOrder();
- for(list<Variable*>::iterator i=vs->begin();i!=vs->end();i++) {
+ for(list<Variable*>::iterator i=vs->begin();i!=vs->end();++i) {
Variable *v=*i;
if(!v->block->deleted) {
bs->mergeLeft(v->block);
}
}
bs->cleanup();
- for(int i=0;i<m;i++) {
+ for(unsigned i=0;i<m;i++) {
if(cs[i]->slack()<-0.0000001) {
#ifdef RECTANGLE_OVERLAP_LOGGING
ofstream f(LOGFILE,ios::app);
bool solved=false;
// Solve shouldn't loop indefinately
// ... but just to make sure we limit the number of iterations
- int maxtries=100;
+ unsigned maxtries=100;
while(!solved&&maxtries>=0) {
solved=true;
maxtries--;
- for(set<Block*>::const_iterator i=bs->begin();i!=bs->end();i++) {
+ for(set<Block*>::const_iterator i=bs->begin();i!=bs->end();++i) {
Block *b=*i;
b->setUpInConstraints();
b->setUpOutConstraints();
}
- for(set<Block*>::const_iterator i=bs->begin();i!=bs->end();i++) {
+ for(set<Block*>::const_iterator i=bs->begin();i!=bs->end();++i) {
Block *b=*i;
Constraint *c=b->findMinLM();
if(c!=NULL && c->lm<0) {
}
}
}
- for(int i=0;i<m;i++) {
+ for(unsigned i=0;i<m;i++) {
if(cs[i]->slack()<-0.0000001) {
assert(cs[i]->slack()>-0.0000001);
throw "Unsatisfied constraint";
refine();
}
+void IncVPSC::solve() {
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"solve_inc()..."<<endl;
+#endif
+ double lastcost,cost = bs->cost();
+ do {
+ lastcost=cost;
+ satisfy();
+ splitBlocks();
+ cost = bs->cost();
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ f<<" cost="<<cost<<endl;
+#endif
+ } while(fabs(lastcost-cost)>0.0001);
+}
/**
- * incremental version of solve that should allow refinement after blocks are
- * moved. Work in progress.
+ * incremental version of satisfy that allows refinement after blocks are
+ * moved.
+ *
+ * - move blocks to new positions
+ * - repeatedly merge across most violated constraint until no more
+ * violated constraints exist
+ *
+ * Note: there is a special case to handle when the most violated constraint
+ * is between two variables in the same block. Then, we must split the block
+ * over an active constraint between the two variables. We choose the
+ * constraint with the most negative lagrangian multiplier.
*/
-void VPSC::move_and_split() {
- //assert(!blockGraphIsCyclic());
- for(set<Block*>::const_iterator i=bs->begin();i!=bs->end();i++) {
- Block *b=*i;
- if(!b->deleted) {
- b->wposn = b->desiredWeightedPosition();
- b->posn = b->wposn / b->weight;
- Variable *v=b->vars->front();
- bs->mergeLeft(b);
- // b may be merged away, so get any new block from one of its members
- bs->mergeRight(v->block);
+void IncVPSC::satisfy() {
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"satisfy_inc()..."<<endl;
+#endif
+ splitBlocks();
+ long splitCtr = 0;
+ Constraint* v = NULL;
+ while((v=mostViolated(inactive))&&(v->equality || v->slack()<-0.000001)) {
+ assert(!v->active);
+ Block *lb = v->left->block, *rb = v->right->block;
+ if(lb != rb) {
+ lb->merge(rb,v);
+ } else {
+ if(splitCtr++>10000) {
+ throw "Cycle Error!";
+ }
+ // constraint is within block, need to split first
+ inactive.push_back(lb->splitBetween(v->left,v->right,lb,rb));
+ lb->merge(rb,v);
+ bs->insert(lb);
}
}
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ f<<" finished merges."<<endl;
+#endif
+ bs->cleanup();
+ for(unsigned i=0;i<m;i++) {
+ v=cs[i];
+ if(v->slack()<-0.0000001) {
+ //assert(cs[i]->slack()>-0.0000001);
+ ostringstream s;
+ s<<"Unsatisfied constraint: "<<*v;
+ throw s.str().c_str();
+ }
+ }
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ f<<" finished cleanup."<<endl;
+ printBlocks();
+#endif
+}
+void IncVPSC::moveBlocks() {
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"moveBlocks()..."<<endl;
+#endif
+ for(set<Block*>::const_iterator i(bs->begin());i!=bs->end();++i) {
+ Block *b = *i;
+ b->wposn = b->desiredWeightedPosition();
+ b->posn = b->wposn / b->weight;
+ }
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ f<<" moved blocks."<<endl;
+#endif
+}
+void IncVPSC::splitBlocks() {
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ ofstream f(LOGFILE,ios::app);
+#endif
+ moveBlocks();
+ splitCnt=0;
+ // Split each block if necessary on min LM
+ for(set<Block*>::const_iterator i(bs->begin());i!=bs->end();++i) {
+ Block* b = *i;
+ Constraint* v=b->findMinLM();
+ if(v!=NULL && v->lm < -0.0000001) {
+ assert(!v->equality);
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ f<<" found split point: "<<*v<<" lm="<<v->lm<<endl;
+#endif
+ splitCnt++;
+ Block *b = v->left->block, *l=NULL, *r=NULL;
+ assert(v->left->block == v->right->block);
+ double pos = b->posn;
+ b->split(l,r,v);
+ l->posn=r->posn=pos;
+ l->wposn = l->posn * l->weight;
+ r->wposn = r->posn * r->weight;
+ bs->insert(l);
+ bs->insert(r);
+ b->deleted=true;
+ inactive.push_back(v);
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ f<<" new blocks: "<<*l<<" and "<<*r<<endl;
+#endif
+ }
+ }
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ f<<" finished splits."<<endl;
+#endif
bs->cleanup();
- // assert(!blockGraphIsCyclic());
- refine();
+}
+
+/**
+ * Scan constraint list for the most violated constraint, or the first equality
+ * constraint
+ */
+Constraint* IncVPSC::mostViolated(ConstraintList &l) {
+ double minSlack = DBL_MAX;
+ Constraint* v=NULL;
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"Looking for most violated..."<<endl;
+#endif
+ ConstraintList::iterator end = l.end();
+ ConstraintList::iterator deletePoint = end;
+ for(ConstraintList::iterator i=l.begin();i!=end;++i) {
+ Constraint *c=*i;
+ double slack = c->slack();
+ if(c->equality || slack < minSlack) {
+ minSlack=slack;
+ v=c;
+ deletePoint=i;
+ if(c->equality) break;
+ }
+ }
+ // Because the constraint list is not order dependent we just
+ // move the last element over the deletePoint and resize
+ // downwards. There is always at least 1 element in the
+ // vector because of search.
+ if(deletePoint != end && (minSlack<-0.0000001||v->equality)) {
+ *deletePoint = l[l.size()-1];
+ l.resize(l.size()-1);
+ }
+#ifdef RECTANGLE_OVERLAP_LOGGING
+ f<<" most violated is: "<<*v<<endl;
+#endif
+ return v;
}
#include <map>
set<node*> in;
set<node*> out;
};
-/*
// useful in debugging - cycles would be BAD
-bool VPSC::constraintGraphIsCyclic(Variable *vs[], const int n) {
+bool VPSC::constraintGraphIsCyclic(const unsigned n, Variable *vs[]) {
map<Variable*, node*> varmap;
vector<node*> graph;
- for(int i=0;i<n;i++) {
+ for(unsigned i=0;i<n;i++) {
node *u=new node;
graph.push_back(u);
varmap[vs[i]]=u;
}
- for(int i=0;i<n;i++) {
- for(vector<Constraint*>::iterator c=vs[i]->in.begin();c!=vs[i]->in.end();c++) {
+ for(unsigned i=0;i<n;i++) {
+ for(vector<Constraint*>::iterator c=vs[i]->in.begin();c!=vs[i]->in.end();++c) {
Variable *l=(*c)->left;
varmap[vs[i]]->in.insert(varmap[l]);
}
- for(vector<Constraint*>::iterator c=vs[i]->out.begin();c!=vs[i]->out.end();c++) {
+ for(vector<Constraint*>::iterator c=vs[i]->out.begin();c!=vs[i]->out.end();++c) {
Variable *r=(*c)->right;
varmap[vs[i]]->out.insert(varmap[r]);
}
while(graph.size()>0) {
node *u=NULL;
vector<node*>::iterator i=graph.begin();
- for(;i!=graph.end();i++) {
+ for(;i!=graph.end();++i) {
u=*i;
if(u->in.size()==0) {
break;
return true;
} else {
graph.erase(i);
- for(set<node*>::iterator j=u->out.begin();j!=u->out.end();j++) {
+ for(set<node*>::iterator j=u->out.begin();j!=u->out.end();++j) {
node *v=*j;
v->in.erase(u);
}
delete u;
}
}
- for(unsigned i=0; i<graph.size(); i++) {
+ for(unsigned i=0; i<graph.size(); ++i) {
delete graph[i];
}
return false;
bool VPSC::blockGraphIsCyclic() {
map<Block*, node*> bmap;
vector<node*> graph;
- for(set<Block*>::const_iterator i=bs->begin();i!=bs->end();i++) {
+ for(set<Block*>::const_iterator i=bs->begin();i!=bs->end();++i) {
Block *b=*i;
node *u=new node;
graph.push_back(u);
bmap[b]=u;
}
- for(set<Block*>::const_iterator i=bs->begin();i!=bs->end();i++) {
+ for(set<Block*>::const_iterator i=bs->begin();i!=bs->end();++i) {
Block *b=*i;
b->setUpInConstraints();
Constraint *c=b->findMinInConstraint();
while(graph.size()>0) {
node *u=NULL;
vector<node*>::iterator i=graph.begin();
- for(;i!=graph.end();i++) {
+ for(;i!=graph.end();++i) {
u=*i;
if(u->in.size()==0) {
break;
return true;
} else {
graph.erase(i);
- for(set<node*>::iterator j=u->out.begin();j!=u->out.end();j++) {
+ for(set<node*>::iterator j=u->out.begin();j!=u->out.end();++j) {
node *v=*j;
v->in.erase(u);
}
}
return false;
}
-*/
index c7da502fb53b297a1fa8febe0f5156a7b2f54682..9f6244a5aacac4fb47702c062e9105bb06afa00e 100644 (file)
/**
-* \brief Remove overlaps function
-*
-* Authors:
-* Tim Dwyer <tgdwyer@gmail.com>
-*
-* Copyright (C) 2005 Authors
-*
-* Released under GNU GPL. Read the file 'COPYING' for more information.
-*/
-
+ * \brief Solve an instance of the "Variable Placement with Separation
+ * Constraints" problem.
+ *
+ * Authors:
+ * Tim Dwyer <tgdwyer@gmail.com>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
+ */
#ifndef SEEN_REMOVEOVERLAP_SOLVE_VPSC_H
#define SEEN_REMOVEOVERLAP_SOLVE_VPSC_H
+#include <vector>
class Variable;
class Constraint;
class Blocks;
*/
class VPSC {
public:
- void satisfy();
- void solve();
+ virtual void satisfy();
+ virtual void solve();
- void move_and_split();
- VPSC(Variable *vs[], const int n, Constraint *cs[], const int m);
- ~VPSC();
+ VPSC(const unsigned n, Variable *vs[], const unsigned m, Constraint *cs[]);
+ virtual ~VPSC();
+ Constraint** getConstraints() { return cs; }
+ Variable** getVariables() { return vs; }
protected:
Blocks *bs;
- void refine();
-private:
+ Constraint **cs;
+ unsigned m;
+ Variable **vs;
void printBlocks();
- bool constraintGraphIsCyclic(Variable *vs[], const int n);
+private:
+ void refine();
+ bool constraintGraphIsCyclic(const unsigned n, Variable *vs[]);
bool blockGraphIsCyclic();
- Constraint **cs;
- int m;
};
+class IncVPSC : public VPSC {
+public:
+ unsigned splitCnt;
+ void satisfy();
+ void solve();
+ void moveBlocks();
+ void splitBlocks();
+ IncVPSC(const unsigned n, Variable *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 0cf2e28a7677cbf97b57da5f49731d74df824a6c..1890f788ede978d2836a5c7c4bc5923a52a28425 100644 (file)
/**
- * \brief Remove overlaps function
*
* Authors:
* Tim Dwyer <tgdwyer@gmail.com>
*
* Copyright (C) 2005 Authors
*
- * Released under GNU GPL. Read the file 'COPYING' for more information.
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
#include "variable.h"
std::ostream& operator <<(std::ostream &os, const Variable &v) {
return os;
}
-#include "block.h"
-double Variable::position() const {
- return block->posn+offset;
-}
index e682dd7df4eaac30450e2f392accfa3550e13b4c..86e16737e1d024374626f4a943c4fb3b84f5ad1c 100644 (file)
/**
- * \brief Remove overlaps function
*
* Authors:
* Tim Dwyer <tgdwyer@gmail.com>
*
* Copyright (C) 2005 Authors
*
- * Released under GNU GPL. Read the file 'COPYING' for more information.
+ * Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
-
#ifndef SEEN_REMOVEOVERLAP_VARIABLE_H
#define SEEN_REMOVEOVERLAP_VARIABLE_H
#include <iostream>
class Block;
class Constraint;
+#include "block.h"
+typedef std::vector<Constraint*> Constraints;
class Variable
{
friend std::ostream& operator <<(std::ostream &os, const Variable &v);
public:
- static const unsigned int _TOSTRINGBUFFSIZE=20;
const int id; // useful in log files
double desiredPosition;
const double weight;
double offset;
Block *block;
bool visited;
- std::vector<Constraint*> in;
- std::vector<Constraint*> out;
+ Constraints in;
+ Constraints out;
char *toString();
inline Variable(const int id, const double desiredPos, const double weight)
: id(id)
, desiredPosition(desiredPos)
, weight(weight)
, offset(0)
+ , block(NULL)
, visited(false)
{
}
- double position() const;
+ inline double Variable::position() const {
+ return block->posn+offset;
+ }
+ //double position() const;
~Variable(void){
in.clear();
out.clear();