COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/work/peter/graph-displayer.cc @ 1289:142633fc5014

Last change on this file since 1289:142633fc5014 was 1289:142633fc5014, checked in by Hegyi Péter, 20 years ago

Graph displayer is now displaying nodes. Edges remain still undisplayed yet.

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