2
* \brief A block structure defined over the variables
4
* A block structure defined over the variables such that each block contains
5
* 1 or more variables, with the invariant that all constraints inside a block
6
* are satisfied by keeping the variables fixed relative to one another
9
* Tim Dwyer <tgdwyer@gmail.com>
11
* Copyright (C) 2005 Authors
13
* Released under GNU LGPL. Read the file 'COPYING' for more information.
18
#include "constraint.h"
19
#ifdef RECTANGLE_OVERLAP_LOGGING
33
Blocks::Blocks(const int n, Variable *vs[]) : vs(vs),nvs(n) {
35
for(int i=0;i<nvs;i++) {
36
insert(new Block(vs[i]));
42
for(set<Block*>::iterator i=begin();i!=end();++i) {
49
* returns a list of variables with total ordering determined by the constraint
52
list<Variable*> *Blocks::totalOrder() {
53
list<Variable*> *order = new list<Variable*>;
54
for(int i=0;i<nvs;i++) {
57
for(int i=0;i<nvs;i++) {
58
if(vs[i]->in.size()==0) {
59
dfsVisit(vs[i],order);
64
// Recursive depth first search giving total order by pushing nodes in the DAG
65
// onto the front of the list when we finish searching them
66
void Blocks::dfsVisit(Variable *v, list<Variable*> *order) {
68
vector<Constraint*>::iterator it=v->out.begin();
69
for(;it!=v->out.end();++it) {
71
if(!c->right->visited) {
72
dfsVisit(c->right, order);
75
#ifdef RECTANGLE_OVERLAP_LOGGING
76
ofstream f(LOGFILE,ios::app);
77
f<<" order="<<*v<<endl;
82
* Processes incoming constraints, most violated to least, merging with the
83
* neighbouring (left) block until no more violated constraints are found
85
void Blocks::mergeLeft(Block *r) {
86
#ifdef RECTANGLE_OVERLAP_LOGGING
87
ofstream f(LOGFILE,ios::app);
88
f<<"mergeLeft called on "<<*r<<endl;
90
r->timeStamp=++blockTimeCtr;
91
r->setUpInConstraints();
92
Constraint *c=r->findMinInConstraint();
93
while (c != NULL && c->slack()<0) {
94
#ifdef RECTANGLE_OVERLAP_LOGGING
95
f<<"mergeLeft on constraint: "<<*c<<endl;
97
r->deleteMinInConstraint();
98
Block *l = c->left->block;
99
if (l->in==NULL) l->setUpInConstraints();
100
double dist = c->right->offset - c->left->offset - c->gap;
101
if (r->vars->size() < l->vars->size()) {
106
r->merge(l, c, dist);
108
r->timeStamp=blockTimeCtr;
110
c=r->findMinInConstraint();
112
#ifdef RECTANGLE_OVERLAP_LOGGING
113
f<<"merged "<<*r<<endl;
117
* Symmetrical to mergeLeft
119
void Blocks::mergeRight(Block *l) {
120
#ifdef RECTANGLE_OVERLAP_LOGGING
121
ofstream f(LOGFILE,ios::app);
122
f<<"mergeRight called on "<<*l<<endl;
124
l->setUpOutConstraints();
125
Constraint *c = l->findMinOutConstraint();
126
while (c != NULL && c->slack()<0) {
127
#ifdef RECTANGLE_OVERLAP_LOGGING
128
f<<"mergeRight on constraint: "<<*c<<endl;
130
l->deleteMinOutConstraint();
131
Block *r = c->right->block;
132
r->setUpOutConstraints();
133
double dist = c->left->offset + c->gap - c->right->offset;
134
if (l->vars->size() > r->vars->size()) {
138
l->merge(r, c, dist);
141
c=l->findMinOutConstraint();
143
#ifdef RECTANGLE_OVERLAP_LOGGING
144
f<<"merged "<<*l<<endl;
147
void Blocks::removeBlock(Block *doomed) {
148
doomed->deleted=true;
151
void Blocks::cleanup() {
152
vector<Block*> bcopy(begin(),end());
153
for(vector<Block*>::iterator i=bcopy.begin();i!=bcopy.end();++i) {
162
* Splits block b across constraint c into two new blocks, l and r (c's left
163
* and right sides respectively)
165
void Blocks::split(Block *b, Block *&l, Block *&r, Constraint *c) {
167
#ifdef RECTANGLE_OVERLAP_LOGGING
168
ofstream f(LOGFILE,ios::app);
169
f<<"Split left: "<<*l<<endl;
170
f<<"Split right: "<<*r<<endl;
173
r->wposn = r->posn * r->weight;
175
// r may have been merged!
177
r->wposn = r->desiredWeightedPosition();
178
r->posn = r->wposn / r->weight;
186
* returns the cost total squared distance of variables from their desired
189
double Blocks::cost() {
191
for(set<Block*>::iterator i=begin();i!=end();++i) {