Home || Architecture || Video Search || Visual Search || Scripts || Applications || Important Messages || OGL || Src

BoostedGraph.h

Go to the documentation of this file.
00001 #include "OglGui/Graph.h"
00002 
00003 #include <string>
00004 #include <map>
00005 #include <vector>
00006 #include <utility>                   // for std::pair
00007 #include <algorithm>                 // for std::for_each
00008 
00009 #include <boost/graph/graph_traits.hpp>
00010 #include <boost/graph/adjacency_list.hpp>
00011 #include <boost/graph/simple_point.hpp>
00012 #include <boost/graph/circle_layout.hpp>
00013 #include <boost/graph/fruchterman_reingold.hpp>
00014 
00015 #include "Tag.h"
00016 
00017 using namespace OglGui;
00018 using namespace std;
00019 using namespace boost;
00020 
00021 class BoostedGraph : public OglGui::Graph, public OglGui::WindowListener {
00022 public:
00023         typedef adjacency_list<vecS, vecS, undirectedS, property<vertex_name_t, string> > Graph;
00024         typedef graph_traits<Graph>::vertex_descriptor Vertex;
00025 
00026         BoostedGraph(Window* parent, int w, int h, int drawShape=0, strconst txt="") : OglGui::Graph(parent, w, h, drawShape, txt) {
00027                 layoutDone = false;
00028         }
00029 
00030         ~BoostedGraph() {
00031                 ILOG_DEBUG("Destructing BoostedGraph");
00032                 initialLayoutDone = false;
00033                 layoutDone = false;
00034         }
00035 
00036         void addNodes(map<string, vector<string> > labels) {
00037                 map<string, vector<string> >::iterator iter;
00038                 for(iter = labels.begin(); iter != labels.end(); iter++) {
00039                         string label = iter->first;
00040                         if(nodes.count(label) == 0) addNode(label);
00041                         for(uint i = 0; i < iter->second.size(); i++) {
00042                                 string related = iter->second[i];
00043                                 if(nodes.count(related) == 0) addNode(related);
00044                                 ConnectNode(label, related);
00045                         }
00046                 }
00047 
00048                 if(labels.begin()->first.compare("obama") == 0) {
00049                         ConnectNode("election", "president"); ConnectNode("barack", "barackobama");
00050                         ConnectNode("vote", "election"); ConnectNode("president", "politics");
00051                         ConnectNode("vote", "president"); ConnectNode("president", "obama");
00052                         ConnectNode("change", "hope"); ConnectNode("campaign", "election");
00053                 }
00054         }
00055 
00056         virtual void DisplayFunc() {
00057                 //ILOG_DEBUG("DisplayFunc");
00058                 if(!layoutDone) layoutDone = doLayout();
00059                 OglGui::Graph::DisplayFunc();
00060         }
00061 
00062     virtual void OnLayoutChange()
00063     {
00064                 layoutDone = false;
00065                 OglGui::Graph::OnLayoutChange();
00066     }
00067 
00068     virtual void WindowMouseEvent(OglGui::Window *src, int msg, int but, int state, int x, int y, void *userData )
00069     {
00070         if (but==oglLeftButton && msg == oglMouseMove) dragging = true;
00071 
00072         if (dragging && but==oglLeftButton && msg == oglMouseUp) {
00073                 OglGui::Graph* g = (OglGui::Graph*) userData;
00074                 // update BoostGraph with move of node
00075                 // TODO: This updating should be more elegant
00076                 graph_traits<Graph>::vertex_iterator vi, vi_end;
00077                 for (tie(vi, vi_end) = vertices(graph); vi != vi_end; ++vi) {
00078                         string name = get(vertex_name, graph, *vi);
00079                         if(name.compare(g->GetText()) != 0) continue;
00080                         int x, y, w, h;
00081                         g->GetDimensions(x, y, w, h);
00082                 ILOG_DEBUG(g->GetText() + " moved");// to (" + MakeString(x) + "," + MakeString(y) + ")");
00083                         position[*vi].x = x-center.x;
00084                         position[*vi].y = y-center.y;
00085                 layoutDone = false;
00086                 break;
00087                 }
00088                 dragging = false;
00089         }
00090     }
00091 
00092 private:
00093         void addNode(string label) {
00094                 int width, height;
00095                 this->GetDimensions(width, height);
00096                 int x  = ABSRND(width-20);
00097                 int y  = ABSRND(height-20);
00098 
00099                 nodes[label].first = add_vertex(label, graph);
00100                 nodes[label].second = new OglGui::Graph(this,x,y,75,20,1,label);
00101                 nodes[label].second->ShapeBg(ARGB2COLOR(208,255,24,0));
00102                 nodes[label].second->SetBorderType(0);
00103                 nodes[label].second->ActOnModifier(0);
00104                 nodes[label].second->SetAllowSizeDirections(AllDir, false);
00105         nodes[label].second->SetWindowListener(this, nodes[label].second);
00106 
00107                 this->AddNode(nodes[label].second);
00108         }
00109 
00110         void ConnectNode(string from, string to) {
00111                 add_edge(nodes[from].first, nodes[to].first, graph);
00112                 OglGui::Graph::ConnectNode(nodes[from].second, nodes[to].second);
00113         }
00114 
00115         void doInitialLayout() {
00116                 position_vec = PositionVec(num_vertices(graph));
00117                 position = PositionMap(position_vec.begin(), get(vertex_index, graph));
00118                 circle_graph_layout(graph, position, 10);
00119                 fruchterman_reingold_force_directed_layout(graph, position, 2*center.x-10, 2*center.y-10,
00120                                 force_pairs(all_force_pairs()));
00121                 initialLayoutDone = true;
00122         }
00123 
00124         bool doLayout() {
00125                 center.x = (W()-75)/2; center.y = (H()-20)/2;
00126                 if(!initialLayoutDone) doInitialLayout();
00127                 fruchterman_reingold_force_directed_layout(graph, position, 2*center.x-10, 2*center.y-10,
00128                                 force_pairs(all_force_pairs()).
00129                                 cooling(linear_cooling<double>(50)));
00130 
00131                 graph_traits<Graph>::vertex_iterator vi, vi_end;
00132                 for (tie(vi, vi_end) = vertices(graph); vi != vi_end; ++vi) {
00133                         string name = get(vertex_name, graph, *vi);
00134                         //ILOG_DEBUG(name + ": " + Impala::MakeString(position[*vi].x) + " " + Impala::MakeString(position[*vi].y));
00135                         int x, y, w, h;
00136                         nodes[name].second->GetDimensions(x, y, w, h);
00137                         nodes[name].second->SetDimensions(center.x+position[*vi].x, center.y+position[*vi].y, w, h);
00138                         nodes[name].second->ShapeBg(ARGB2COLOR(208,255,24,0));
00139                 }
00140                 return true;
00141         }
00142 
00143         typedef vector<simple_point<double> > PositionVec;
00144         typedef iterator_property_map<PositionVec::iterator, property_map<Graph, vertex_index_t>::type> PositionMap;
00145 
00146         PositionVec position_vec;
00147         PositionMap position;
00148 
00149         simple_point<double> center;
00150 
00151     map<string, pair<Vertex, OglGui::Graph*> > nodes;
00152     Graph graph;
00153 
00154         bool initialLayoutDone;
00155     bool layoutDone;
00156     bool dragging;
00157 
00158     ILOG_VAR_DEC;
00159 };
00160 
00161 ILOG_VAR_INIT(BoostedGraph, Impala.Application.TagsLife);

Generated on Fri Mar 19 09:30:39 2010 for ImpalaSrc by  doxygen 1.5.1