COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/work/peter/graph-displayer.cc @ 1301:1f3baf3bd1f2

Last change on this file since 1301:1f3baf3bd1f2 was 1301:1f3baf3bd1f2, checked in by Hegyi Péter, 15 years ago

Graph displayer displays graphs now.

File size: 7.2 KB
Line 
1// This example was started by Guillaume Laurent.
2// It has become a place to dump code that tests parts of the
3// gnomemm canvas code. Little thought has been given to the
4// actual on-screen output.
5
6#include <libgnomecanvasmm.h>
7#include <libgnomecanvasmm/polygon.h>
8
9#include <fstream>
10#include <iostream>
11
12#include <lemon/list_graph.h>
13#include <lemon/graph_reader.h>
14#include <lemon/graph_writer.h>
15#include <lemon/graph_utils.h>
16#include <lemon/maps.h>
17#include <lemon/error.h>
18#include <lemon/xy.h>
19
20using namespace lemon;
21
22typedef xy<double> Coordinates;
23typedef ListGraph Graph;
24typedef Graph::NodeMap<Coordinates> CoordinatesMap;
25typedef Graph::Node Node;
26typedef Graph::EdgeIt EdgeIt;
27typedef Graph::NodeIt NodeIt;
28
29class GraphDisplayerCanvas : public Gnome::Canvas::CanvasAA
30{
31  typedef Gnome::Canvas::CanvasAA Parent;
32
33public:
34  GraphDisplayerCanvas(Graph &, CoordinatesMap &);
35  virtual ~GraphDisplayerCanvas();
36
37private:
38
39  ///Event handler function that handles dragging nodes of displayed_graph
40  bool event_handler(GdkEvent* e, Node n);
41
42        ///The graph, on which we work
43        Graph g;
44  ///Map of nodes of planefigure
45  Graph::NodeMap<Gnome::Canvas::Ellipse *> nodesmap; 
46  ///Map of edges of planefigure
47  Graph::EdgeMap<Gnome::Canvas::Line *> edgesmap; 
48  ///Group of graphical elements of displayed_graph
49  Gnome::Canvas::Group displayed_graph;
50
51  ///Indicates whether the button of mouse is pressed or not
52  bool isbutton;
53
54  ///At this location was the mousebutton pressed.
55  ///It helps to calculate the distance of dragging.
56  double clicked_x, clicked_y;
57
58  ///Remembers which Gnome::Canvas::Item was pressed.
59  ///this variable is needed, because
60  ///1. we cannot query the item at he cursor as fast as it could not cause a Segmentation Fault
61  ///2. we would like to handle only ony item per movement, therefore quering it is not a working solution
62  Gnome::Canvas::Item * active_item;
63
64
65};
66
67
68///This function moves only one node of displayed_graph,
69///but recalculate the location of weight point,
70///and also redraw the sides of the planefigure.
71bool GraphDisplayerCanvas::event_handler(GdkEvent* e, Node n)
72{
73  switch(e->type)
74  {
75    case GDK_BUTTON_PRESS:
76      clicked_x=e->button.x;
77      clicked_y=e->button.y;
78      active_item=(get_item_at(e->button.x, e->button.y));
79      isbutton=true;
80      break;
81    case GDK_BUTTON_RELEASE:
82      isbutton=false;
83      active_item=NULL;
84      break;
85    case GDK_MOTION_NOTIFY:
86      if(isbutton)
87      {
88        double dx=e->motion.x-clicked_x;
89        double dy=e->motion.y-clicked_y;
90        active_item->move(dx, dy);
91        clicked_x=e->motion.x;
92        clicked_y=e->motion.y;
93
94                                EdgeIt e;
95
96                                g.firstOut(e,n);
97                                for(;e!=INVALID;g.nextOut(e))
98                                {
99                                                Gnome::Canvas::Points coos;
100                                                double x1, x2, y1, y2;
101
102                                                nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
103                                                coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
104
105                                                nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
106                                                coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
107
108                                                edgesmap[e]->property_points().set_value(coos);
109                                }
110
111                                g.firstIn(e,n);
112                                for(;e!=INVALID;g.nextIn(e))
113                                {
114                                                Gnome::Canvas::Points coos;
115                                                double x1, x2, y1, y2;
116
117                                                nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
118                                                coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
119
120                                                nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
121                                                coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
122
123                                                edgesmap[e]->property_points().set_value(coos);
124                                }
125      }
126    default: break;
127  }
128  return true;
129}
130
131GraphDisplayerCanvas::GraphDisplayerCanvas(Graph & gr, CoordinatesMap & cm):g(gr),nodesmap(g),edgesmap(g),displayed_graph(*(root()), 0, 0),isbutton(false),active_item(NULL)
132{
133                for (EdgeIt i(g); i!=INVALID; ++i)
134    {
135                                Gnome::Canvas::Points coos;
136                                coos.push_back(Gnome::Art::Point(cm[g.source(i)].x,cm[g.source(i)].y));
137                                coos.push_back(Gnome::Art::Point(cm[g.target(i)].x,cm[g.target(i)].y));
138                                edgesmap[i]=new Gnome::Canvas::Line(displayed_graph, coos);
139                                *(edgesmap[i]) << Gnome::Canvas::Properties::fill_color("green");
140                                edgesmap[i]->property_width_pixels().set_value(10);
141    }
142    for (NodeIt i(g); i!=INVALID; ++i)
143    {
144                                nodesmap[i]=new Gnome::Canvas::Ellipse(displayed_graph, cm[i].x-20, cm[i].y-20, cm[i].x+20, cm[i].y+20);
145                                *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue");
146                                *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black");
147                                (nodesmap[i])->signal_event().connect(sigc::bind(sigc::mem_fun(*this, &GraphDisplayerCanvas::event_handler),i));
148    }
149
150}
151
152GraphDisplayerCanvas::~GraphDisplayerCanvas()
153{
154                Graph::NodeMap <int> id(g);
155                Graph::NodeMap <double> xc(g);
156                Graph::NodeMap <double> yc(g);
157
158                int j=1;
159
160    for (NodeIt i(g); i!=INVALID; ++i)
161    {
162                                double x1,y1,x2,y2;
163                                nodesmap[i]->get_bounds(x1, y1, x2, y2);
164
165                                id[i]=j++;
166                                xc[i]=(x1+x2)/2;
167                                yc[i]=(y1+y2)/2;
168                }
169
170                GraphWriter<Graph> writer(std::cout,g);
171
172                writer.addNodeMap("id", id);
173                writer.addNodeMap("coordinates_x", xc);
174                writer.addNodeMap("coordinates_y", yc);
175                writer.run();
176}
177
178
179//MainWin:
180class MainWin : public Gtk::Window
181{
182public:
183  MainWin(const std::string& title, Graph &, CoordinatesMap &);
184
185protected:
186  //Member widgets:
187  GraphDisplayerCanvas gd_canvas;
188};
189
190MainWin::MainWin(const std::string& title, Graph & graph, CoordinatesMap & cm):gd_canvas(graph, cm)
191{
192  set_title (title);
193  add(gd_canvas);
194  set_default_size(900,600);
195
196  show_all();
197}
198
199
200///This class is responsible for being able
201///to read xy datastructure from file. It is
202///based on BaseMap. The set method sets the
203///appropriate value in the final xy NodeMap
204///that was given to the constructor.
205class CoordReaderMap: public MapBase <Node, double>
206{
207    CoordinatesMap & cm;
208    char xoy;
209
210public:
211    CoordReaderMap(char xory, CoordinatesMap & coordmap);
212    void set(Node node, double coord);
213};
214
215///The constructor expects for an xy NodeMap,
216///and we have to tell it, for which  value
217///of the xy vector is responsible the actual
218///copy.
219CoordReaderMap::CoordReaderMap(char xory, CoordinatesMap & coordmap): cm(coordmap)
220{
221    switch(xory)
222    {
223        case 'x':
224        case 'y':
225            xoy=xory;
226            break;
227        default:
228            throw UninitializedParameter() ;
229    }
230}
231
232///set method sets the appropriate value in the
233///xy type NodeMap that is under construction
234void CoordReaderMap::set(Node node, double coord)
235{
236    switch(xoy)
237    {
238        case 'x':
239            cm[node].x=coord;
240            break;
241        case 'y':
242            cm[node].y=coord;
243            break;
244        default:
245            throw UninitializedParameter() ;
246    }
247}
248
249//main():
250
251int main(int argc, char *argv[])
252{
253  if(argc<2)
254  {
255      std::cerr << "USAGE: gd <input filename.lgf>" << endl;
256      return 0;
257  }
258
259  Coordinates coosvector;
260
261  Graph g;
262
263  CoordinatesMap cm(g);
264  Graph::EdgeMap<double> cap(g);
265
266  //we create one object to read x coordinates
267  //and one to read y coordinate of nodes and write them to cm NodeMap.
268  CoordReaderMap xreader('x',cm);
269  CoordReaderMap yreader('y',cm);
270
271  std::ifstream is(argv[1]);
272
273  GraphReader<Graph> reader(is, g);
274  reader.addNodeMap("coordinates_x", xreader);
275  reader.addNodeMap("coordinates_y", yreader);
276  reader.run();
277
278  Gnome::Canvas::init();
279  Gtk::Main app(argc, argv);
280
281  MainWin mainwin("Displayed Graph", g, cm);
282  app.run(mainwin);
283
284  return 0;
285}
Note: See TracBrowser for help on using the repository browser.