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