connected_components.cpp revision fb5bcb25b81fe8e1f5903072c6005b3328c545a9
#include <map>
#include <list>
#include <libvpsc/remove_rectangle_overlap.h>
#include "cola.h"
using namespace std;
namespace cola {
Component::~Component() {
for(unsigned i=0;i<scx.size();i++) {
delete scx[i];
}
for(unsigned i=0;i<scy.size();i++) {
delete scy[i];
}
}
void Component::moveRectangles(double x, double y) {
for(unsigned i=0;i<rects.size();i++) {
rects[i]->moveCentreX(rects[i]->getCentreX()+x);
rects[i]->moveCentreY(rects[i]->getCentreY()+y);
}
}
Rectangle* Component::getBoundingBox() {
double llx=DBL_MAX, lly=DBL_MAX, urx=-DBL_MAX, ury=-DBL_MAX;
for(unsigned i=0;i<rects.size();i++) {
llx=min(llx,rects[i]->getMinX());
lly=min(lly,rects[i]->getMinY());
urx=max(urx,rects[i]->getMaxX());
ury=max(ury,rects[i]->getMaxY());
}
return new Rectangle(llx,urx,lly,ury);
}
namespace ccomponents {
struct Node {
unsigned id;
bool visited;
vector<Node*> neighbours;
list<Node*>::iterator listPos;
Rectangle* r;
};
// Depth first search traversal of graph to find connected component
void dfs(Node* v,
list<Node*>& remaining,
Component* component,
map<unsigned,pair<Component*,unsigned> > &cmap) {
v->visited=true;
remaining.erase(v->listPos);
cmap[v->id]=make_pair(component,component->node_ids.size());
component->node_ids.push_back(v->id);
component->rects.push_back(v->r);
for(unsigned i=0;i<v->neighbours.size();i++) {
Node* u=v->neighbours[i];
if(!u->visited) {
dfs(u,remaining,component,cmap);
}
}
}
}
using namespace ccomponents;
// for a graph of n nodes, return connected components
void connectedComponents(
const vector<Rectangle*> &rs,
const vector<Edge> &es,
const SimpleConstraints &scx,
const SimpleConstraints &scy,
vector<Component*> &components) {
unsigned n=rs.size();
vector<Node> vs(n);
list<Node*> remaining;
for(unsigned i=0;i<n;i++) {
vs[i].id=i;
vs[i].visited=false;
vs[i].r=rs[i];
vs[i].listPos = remaining.insert(remaining.end(),&vs[i]);
}
vector<Edge>::const_iterator ei;
SimpleConstraints::const_iterator ci;
for(ei=es.begin();ei!=es.end();ei++) {
vs[ei->first].neighbours.push_back(&vs[ei->second]);
vs[ei->second].neighbours.push_back(&vs[ei->first]);
}
map<unsigned,pair<Component*,unsigned> > cmap;
while(!remaining.empty()) {
Component* component=new Component;
Node* v=*remaining.begin();
dfs(v,remaining,component,cmap);
components.push_back(component);
}
for(ei=es.begin();ei!=es.end();ei++) {
pair<Component*,unsigned> u=cmap[ei->first],
v=cmap[ei->second];
assert(u.first==v.first);
u.first->edges.push_back(make_pair(u.second,v.second));
}
for(ci=scx.begin();ci!=scx.end();ci++) {
SimpleConstraint *c=*ci;
pair<Component*,unsigned> u=cmap[c->left],
v=cmap[c->right];
assert(u.first==v.first);
u.first->scx.push_back(
new SimpleConstraint(u.second,v.second,c->gap));
}
for(ci=scy.begin();ci!=scy.end();ci++) {
SimpleConstraint *c=*ci;
pair<Component*,unsigned> u=cmap[c->left],
v=cmap[c->right];
assert(u.first==v.first);
u.first->scy.push_back(
new SimpleConstraint(u.second,v.second,c->gap));
}
}
void separateComponents(const vector<Component*> &components) {
unsigned n=components.size();
Rectangle* bbs[n];
double origX[n], origY[n];
for(unsigned i=0;i<n;i++) {
bbs[i]=components[i]->getBoundingBox();
origX[i]=bbs[i]->getCentreX();
origY[i]=bbs[i]->getCentreY();
}
removeRectangleOverlap(n,bbs,0,0);
for(unsigned i=0;i<n;i++) {
components[i]->moveRectangles(
bbs[i]->getCentreX()-origX[i],
bbs[i]->getCentreY()-origY[i]);
delete bbs[i];
}
}
}
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4