/* * 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. * * 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. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library in the file LICENSE; if not, * write to the Free Software Foundation, Inc., 59 Temple Place, * Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include "graphlayouttest.h" using namespace std; using namespace cola; typedef map NodeIdMap; typedef map > Partitions; Edge readEdge(ifstream &f) { string l; int indent=1; unsigned source, target; boost::regex sourceRE(".*source\\s+(\\d+).*"); boost::regex targetRE(".*target\\s+(\\d+).*"); boost::smatch matches; while(!getline(f,l).eof()) { if(boost::regex_match(l,matches,sourceRE)) { std::istringstream i(matches[1]); i>>source; } if(boost::regex_match(l,matches,targetRE)) { std::istringstream i(matches[1]); i>>target; } if(l.find("[")!=string::npos) { indent++; } if(l.find("]")!=string::npos) { indent--; if(indent==0) { return make_pair(source,target); } } } cerr << "Incomplete edge definition!" << endl; return make_pair(0,0); } unsigned readNode(ifstream &f, NodeIdMap &nodeIdMap, Partitions &partitions) { static unsigned nodeCtr=0; int indent=1; string l; boost::regex idRE("\\s*id\\s+(\\d+).*"); boost::regex fillRE(".*fill\\s+\"#(.+)\".*"); boost::smatch matches; unsigned id; while(!getline(f,l).eof()) { if(boost::regex_match(l,matches,idRE)) { std::istringstream i(matches[1]); i>>id; nodeIdMap[id]=nodeCtr++; } if(boost::regex_match(l,matches,fillRE)) { string partition(matches[1]); Partitions::iterator i=partitions.find(partition); partitions[partition].push_back(nodeIdMap[id]); } if(l.find("[")!=string::npos) { indent++; } if(l.find("]")!=string::npos) { indent--; if(indent==0) { return nodeCtr; } } } cerr << "Incomplete node definition!" << endl; return 0; } struct PostIteration : TestConvergence { PostIteration(vector &rs, vector > &ps, vector &bs, const double d,const unsigned i) : TestConvergence(d,i), rs(rs), ps(ps), bs(bs) {} bool operator()(const double new_stress, valarray & X, valarray & Y) { static int iterations=0; unsigned n=X.size(); double centreX=0,centreY=0; for(unsigned i=0;i::iterator v=ps[i].begin();v!=ps[i].end();v++) { double dx=X[*v]-centreX, dy=Y[*v]-centreY; double l=sqrt(dx*dx+dy*dy); if(i>0) { double r=bs[i-1]+10; if(lr) { double dx1=dx*(r/l), dy1=dy*(r/l); X[*v]=centreX+dx1; Y[*v]=centreY+dy1; } } } } for(unsigned i=0;imoveCentre(X[i],Y[i]); } cout << iterations++ << ":stress="< &rs; vector > &ps; vector &bs; }; int main() { //const char *fname="data/test.gml"; string fname("data/uetzNetworkGSC-all.gml"); ifstream f(fname.c_str()); if(!f.is_open()) { cout << "Error opening file: " << fname << endl; exit(1); } unsigned V = 0; double defaultEdgeLength=40; vector es; CompoundConstraints cx,cy; NodeIdMap nodeIdMap; Partitions partitions; string l; boost::regex nodeRE(".*node\\s+\\[.*"); boost::regex edgeRE(".*edge\\s+\\[.*"); while(!getline(f,l).eof()) { if(boost::regex_match(l,nodeRE)) { V=readNode(f,nodeIdMap,partitions); } if(boost::regex_match(l,edgeRE)) { pair e=readEdge(f); unsigned start=nodeIdMap[e.first]; unsigned end=nodeIdMap[e.second]; //printf("edge (%d,%d)\n",start,end); es.push_back(make_pair(start,end)); //cy.push_back( //new SeparationConstraint(start,end,defaultEdgeLength/3)); } } assert(V==nodeIdMap.size()); /* unsigned p1=V++; unsigned p2=V++; // red at the top list &p=partitions[string("FF3333")]; //double cgap=defaultEdgeLength/3; double cgap=0; for(list::iterator j=p.begin();j!=p.end();j++) { cy.push_back( new SeparationConstraint(*j,p1,cgap)); } // yellow in the middle p=partitions[string("FFFF00")]; for(list::iterator j=p.begin();j!=p.end();j++) { cy.push_back( new SeparationConstraint(p1,*j,cgap)); cy.push_back( new SeparationConstraint(*j,p2,cgap)); } // green at the bottom p=partitions[string("00FF00")]; for(list::iterator j=p.begin();j!=p.end();j++) { cy.push_back( new SeparationConstraint(p2,*j,cgap)); } */ cout << "V="< rs; cout << "|V|=" << V << endl; //srand(time(nullptr)); for(unsigned i=0;i > ps; ps.push_back(partitions[string("FF3333")]); ps.push_back(partitions[string("FFFF00")]); ps.push_back(partitions[string("00FF00")]); vector bs; bs.push_back(80); bs.push_back(120); PostIteration test(rs,ps,bs,0.0001,200); ConstrainedMajorizationLayout alg(rs,es,nullptr,defaultEdgeLength,nullptr,test); //ConstrainedFDLayout alg(rs,es,nullptr,defaultEdgeLength,nullptr,test); //alg.setConstrainedLayout(true); //alg.setScaling(true); //alg.setXConstraints(&cx); //alg.setYConstraints(&cy); alg.run(); /* vector colours(V); list &p=partitions[string("FF3333")]; for(list::iterator i=p.begin();i!=p.end();i++) { //colours[*i]=ColourRGBA(1.,0,0.3,1.); colours[*i]=ColourRGBA(0,0,0,1.); } p=partitions[string("FFFF00")]; for(list::iterator i=p.begin();i!=p.end();i++) { //colours[*i]=ColourRGBA((unsigned)255,162,99,255); colours[*i]=ColourRGBA(0,0,0,1.); } p=partitions[string("00FF00")]; for(list::iterator i=p.begin();i!=p.end();i++) { //colours[*i]=ColourRGBA((unsigned)24,157,0,255); colours[*i]=ColourRGBA(0,0,0,1.); } */ OutputFile of(rs,es,nullptr,"gml_graph-constrained.svg",false,true); //of.colours=&colours; of.generate(); for(unsigned i=0;i