/* * vim: ts=4 sw=4 et tw=0 wm=0 * * libcola - A library providing force-directed network layout using the * stress-majorization method subject to separation constraints. * * Copyright (C) 2006-2008 Monash University * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * See the file LICENSE.LGPL distributed with the library. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * */ #include #include #include "libvpsc/rectangle.h" #include "libvpsc/assertions.h" #include "libcola/commondefs.h" #include "libcola/connected_components.h" using namespace std; using namespace vpsc; namespace cola { Component::~Component() { /* for(unsigned i=0;imoveCentreX(rects[i]->getCentreX()+x); rects[i]->moveCentreY(rects[i]->getCentreY()+y); } } Rectangle* Component::getBoundingBox() { Rectangle boundingBox; for (unsigned i = 0; i < rects.size(); ++i) { boundingBox = boundingBox.unionWith(*(rects[i])); } return new Rectangle(boundingBox); } namespace ccomponents { struct Node { unsigned id; bool visited; vector neighbours; list::iterator listPos; Rectangle* r; }; // Depth first search traversal of graph to find connected component void dfs(Node* v, list& remaining, Component* component, map > &cmap) { v->visited=true; remaining.erase(v->listPos); cmap[v->id]=make_pair(component,static_cast(component->node_ids.size())); component->node_ids.push_back(v->id); component->rects.push_back(v->r); for(unsigned i=0;ineighbours.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 &rs, const vector &es, //const SeparationConstraints &scx, //const SeparationConstraints &scy, vector &components) { unsigned n=rs.size(); vector vs(n); list remaining; for(unsigned i=0;i::const_iterator ei; 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 > 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 u=cmap[ei->first], v=cmap[ei->second]; COLA_ASSERT(u.first==v.first); u.first->edges.push_back(make_pair(u.second,v.second)); } /* SeparationConstraints::const_iterator ci; for(ci=scx.begin();ci!=scx.end();ci++) { SeparationConstraint *c=*ci; pair u=cmap[c->left], v=cmap[c->right]; COLA_ASSERT(u.first==v.first); u.first->scx.push_back( new SeparationConstraint(u.second,v.second,c->gap)); } for(ci=scy.begin();ci!=scy.end();ci++) { SeparationConstraint *c=*ci; pair u=cmap[c->left], v=cmap[c->right]; COLA_ASSERT(u.first==v.first); u.first->scy.push_back( new SeparationConstraint(u.second,v.second,c->gap)); } */ } void separateComponents(const vector &components) { unsigned n=components.size(); vector bbs(n); valarray origX(n); valarray origY(n); for(unsigned i=0;igetBoundingBox(); origX[i]=bbs[i]->getCentreX(); origY[i]=bbs[i]->getCentreY(); } removeoverlaps(bbs); for(unsigned i=0;imoveRectangles( bbs[i]->getCentreX()-origX[i], bbs[i]->getCentreY()-origY[i]); delete bbs[i]; } } }