graph_displayer_canvas.cc
author hegyi
Wed, 25 Oct 2006 13:21:24 +0000
changeset 172 fc1e478697d3
parent 168 a5f82cbbc1e4
child 174 95872af46fc4
permissions -rwxr-xr-x
Currently visualized map can be saved and loaded from file.
ladanyi@53
     1
#include "graph_displayer_canvas.h"
hegyi@167
     2
#include <lemon/random.h>
alpar@59
     3
#include <cmath>
ladanyi@6
     4
hegyi@96
     5
GraphDisplayerCanvas::GraphDisplayerCanvas(NoteBookTab & mainw) :
hegyi@94
     6
  nodesmap(mainw.mapstorage.graph), edgesmap(mainw.mapstorage.graph), edgetextmap(mainw.mapstorage.graph),
hegyi@94
     7
  nodetextmap(mainw.mapstorage.graph), displayed_graph(*(root()), 0, 0),
ladanyi@66
     8
  isbutton(0), active_item(NULL), target_item(NULL), nodemap_to_edit(""),
hegyi@160
     9
  edgemap_to_edit(""), autoscale(true), zoomtrack(false), radius_size(20), edge_width(10),
hegyi@172
    10
  iterations(20), attraction(0.05), propulsation(40000), was_redesigned(false), is_drawn(false), mytab(mainw)
ladanyi@6
    11
{
ladanyi@53
    12
  //base event handler is move tool
ladanyi@53
    13
  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::moveEventHandler), false);
ladanyi@53
    14
  actual_tool=MOVE;
hegyi@34
    15
ladanyi@53
    16
  active_node=INVALID;
ladanyi@53
    17
  active_edge=INVALID;
ladanyi@53
    18
  forming_edge=INVALID;
ladanyi@53
    19
}
hegyi@9
    20
ladanyi@53
    21
GraphDisplayerCanvas::~GraphDisplayerCanvas()
ladanyi@53
    22
{
hegyi@96
    23
  for (NodeIt n((mytab.mapstorage).graph); n != INVALID; ++n)
hegyi@94
    24
    {
hegyi@94
    25
      delete nodesmap[n];
hegyi@94
    26
      delete nodetextmap[n];
hegyi@94
    27
    }
hegyi@94
    28
  
hegyi@96
    29
  for (EdgeIt e((mytab.mapstorage).graph); e != INVALID; ++e)
hegyi@94
    30
    {
hegyi@94
    31
      delete edgesmap[e];
hegyi@94
    32
      delete edgetextmap[e];
hegyi@94
    33
    }
hegyi@94
    34
}
ladanyi@6
    35
hegyi@94
    36
void GraphDisplayerCanvas::propertyChange(bool itisedge, int prop)
hegyi@94
    37
{
hegyi@94
    38
  if(itisedge)
hegyi@94
    39
    {
hegyi@94
    40
      propertyUpdate(Edge(INVALID), prop);
hegyi@94
    41
    }
hegyi@94
    42
  else
hegyi@94
    43
    {
hegyi@94
    44
      propertyUpdate(Node(INVALID), prop);
hegyi@94
    45
    }
hegyi@94
    46
}
hegyi@94
    47
hegyi@94
    48
void GraphDisplayerCanvas::propertyUpdate(Edge edge)
hegyi@94
    49
{
hegyi@94
    50
  for(int i=0;i<EDGE_PROPERTY_NUM;i++)
hegyi@94
    51
    {
hegyi@94
    52
      propertyUpdate(edge, i);
hegyi@94
    53
    }
hegyi@94
    54
}
hegyi@94
    55
hegyi@94
    56
void GraphDisplayerCanvas::propertyUpdate(Node node)
hegyi@94
    57
{
hegyi@94
    58
  for(int i=0;i<NODE_PROPERTY_NUM;i++)
hegyi@94
    59
    {
hegyi@94
    60
      propertyUpdate(node, i);
hegyi@94
    61
    }
hegyi@94
    62
}
hegyi@94
    63
hegyi@118
    64
void GraphDisplayerCanvas::propertyUpdate(Node node, int prop)
hegyi@94
    65
{
hegyi@96
    66
  std::string mapname=mytab.getActiveNodeMap(prop);
hegyi@94
    67
hegyi@172
    68
  if(is_drawn)
hegyi@94
    69
    {
hegyi@172
    70
      if(mapname!="")
hegyi@94
    71
	{
hegyi@172
    72
	  if( ( ((mytab.mapstorage).nodemap_storage).find(mapname) != ((mytab.mapstorage).nodemap_storage).end() ) )
hegyi@172
    73
	    {
hegyi@172
    74
	      switch(prop)
hegyi@172
    75
		{
hegyi@172
    76
		case N_RADIUS:
hegyi@172
    77
		  changeNodeRadius(mapname, node);
hegyi@172
    78
		  break;
hegyi@172
    79
		case N_COLOR:
hegyi@172
    80
		  changeNodeColor(mapname, node);
hegyi@172
    81
		  break;
hegyi@172
    82
		case N_TEXT:
hegyi@172
    83
		  changeNodeText(mapname, node);
hegyi@172
    84
		  break;
hegyi@172
    85
		default:
hegyi@172
    86
		  std::cerr<<"Error\n";
hegyi@172
    87
		}
hegyi@172
    88
	    }
hegyi@172
    89
	}
hegyi@172
    90
      else //mapname==""
hegyi@172
    91
	{
hegyi@172
    92
	  Node node=INVALID;	
hegyi@94
    93
	  switch(prop)
hegyi@94
    94
	    {
hegyi@94
    95
	    case N_RADIUS:
hegyi@172
    96
	      resetNodeRadius(node);
hegyi@94
    97
	      break;
hegyi@94
    98
	    case N_COLOR:
hegyi@172
    99
	      resetNodeColor(node);
hegyi@94
   100
	      break;
hegyi@94
   101
	    case N_TEXT:
hegyi@172
   102
	      resetNodeText(node);
hegyi@94
   103
	      break;
hegyi@94
   104
	    default:
hegyi@94
   105
	      std::cerr<<"Error\n";
hegyi@94
   106
	    }
hegyi@94
   107
	}
hegyi@94
   108
    }
hegyi@94
   109
}
hegyi@94
   110
hegyi@118
   111
void GraphDisplayerCanvas::propertyUpdate(Edge edge, int prop)
hegyi@94
   112
{
hegyi@96
   113
  std::string mapname=mytab.getActiveEdgeMap(prop);
hegyi@94
   114
hegyi@172
   115
  if(is_drawn)
hegyi@94
   116
    {
hegyi@172
   117
      if(mapname!="")
hegyi@172
   118
	{
hegyi@172
   119
	  if( ( ((mytab.mapstorage).edgemap_storage).find(mapname) != ((mytab.mapstorage).edgemap_storage).end() ) )
hegyi@172
   120
	    {
hegyi@172
   121
	      switch(prop)
hegyi@172
   122
		{
hegyi@172
   123
		case E_WIDTH:
hegyi@172
   124
		  changeEdgeWidth(mapname, edge);
hegyi@172
   125
		  break;
hegyi@172
   126
		case E_COLOR:
hegyi@172
   127
		  changeEdgeColor(mapname, edge);
hegyi@172
   128
		  break;
hegyi@172
   129
		case E_TEXT:
hegyi@172
   130
		  changeEdgeText(mapname, edge);
hegyi@172
   131
		  break;
hegyi@172
   132
		default:
hegyi@172
   133
		  std::cerr<<"Error\n";
hegyi@172
   134
		}
hegyi@172
   135
	    }
hegyi@172
   136
	}
hegyi@172
   137
      else //mapname==""
hegyi@94
   138
	{
hegyi@94
   139
	  switch(prop)
hegyi@94
   140
	    {
hegyi@94
   141
	    case E_WIDTH:
hegyi@172
   142
	      resetEdgeWidth(edge);
hegyi@94
   143
	      break;
hegyi@94
   144
	    case E_COLOR:
hegyi@172
   145
	      resetEdgeColor(edge);
hegyi@94
   146
	      break;
hegyi@94
   147
	    case E_TEXT:
hegyi@172
   148
	      resetEdgeText(edge);
hegyi@94
   149
	      break;
hegyi@94
   150
	    default:
hegyi@94
   151
	      std::cerr<<"Error\n";
hegyi@94
   152
	    }
hegyi@94
   153
	}
hegyi@94
   154
    }
ladanyi@53
   155
}
ladanyi@53
   156
ladanyi@53
   157
void GraphDisplayerCanvas::drawGraph()
ladanyi@53
   158
{
ladanyi@6
   159
  //first edges are drawn, to hide joining with nodes later
ladanyi@6
   160
hegyi@96
   161
  for (EdgeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
ladanyi@6
   162
  {
ladanyi@151
   163
    if (mytab.mapstorage.graph.source(i) == mytab.mapstorage.graph.target(i))
ladanyi@151
   164
    {
ladanyi@151
   165
      edgesmap[i]=new LoopEdge(displayed_graph, i, *this);
ladanyi@151
   166
    }
ladanyi@151
   167
    else
ladanyi@151
   168
    {
ladanyi@151
   169
      edgesmap[i]=new BrokenEdge(displayed_graph, i, *this);
ladanyi@151
   170
    }
ladanyi@6
   171
    //initializing edge-text as well, to empty string
ladanyi@6
   172
ladanyi@98
   173
    XY text_pos=mytab.mapstorage.arrow_pos[i];
ladanyi@98
   174
    text_pos+=(XY(10,10));
hegyi@25
   175
hegyi@25
   176
    edgetextmap[i]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
hegyi@28
   177
    edgetextmap[i]->property_fill_color().set_value("darkgreen");
hegyi@149
   178
    edgetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false);
ladanyi@63
   179
    edgetextmap[i]->raise_to_top();
ladanyi@6
   180
  }
ladanyi@6
   181
ladanyi@6
   182
  //afterwards nodes come to be drawn
ladanyi@6
   183
hegyi@96
   184
  for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
ladanyi@6
   185
  {
ladanyi@6
   186
    //drawing bule nodes, with black line around them
ladanyi@6
   187
ladanyi@53
   188
    nodesmap[i]=new Gnome::Canvas::Ellipse(
ladanyi@53
   189
        displayed_graph,
hegyi@96
   190
        (mytab.mapstorage).coords[i].x-20,
hegyi@96
   191
        (mytab.mapstorage).coords[i].y-20,
hegyi@96
   192
        (mytab.mapstorage).coords[i].x+20,
hegyi@96
   193
        (mytab.mapstorage).coords[i].y+20);
ladanyi@6
   194
    *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue");
ladanyi@6
   195
    *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black");
ladanyi@63
   196
    nodesmap[i]->raise_to_top();
hegyi@28
   197
hegyi@28
   198
    //initializing edge-text as well, to empty string
hegyi@28
   199
hegyi@150
   200
    XY text_pos(
hegyi@96
   201
        ((mytab.mapstorage).coords[i].x+node_property_defaults[N_RADIUS]+5),
hegyi@96
   202
        ((mytab.mapstorage).coords[i].y+node_property_defaults[N_RADIUS]+5));
hegyi@28
   203
ladanyi@53
   204
    nodetextmap[i]=new Gnome::Canvas::Text(displayed_graph,
ladanyi@53
   205
        text_pos.x, text_pos.y, "");
hegyi@28
   206
    nodetextmap[i]->property_fill_color().set_value("darkblue");
hegyi@149
   207
    nodetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false);
ladanyi@63
   208
    nodetextmap[i]->raise_to_top();
ladanyi@6
   209
  }
ladanyi@6
   210
hegyi@172
   211
  is_drawn=true;
hegyi@172
   212
hegyi@172
   213
  //upon drawing graph
hegyi@172
   214
  //properties have to
hegyi@172
   215
  //be set in as well
hegyi@172
   216
  for(int i=0;i<NODE_PROPERTY_NUM;i++)
hegyi@172
   217
    {
hegyi@172
   218
      propertyUpdate(Node(INVALID), i);
hegyi@172
   219
    }
hegyi@172
   220
hegyi@172
   221
  for(int i=0;i<EDGE_PROPERTY_NUM;i++)
hegyi@172
   222
    {
hegyi@172
   223
      propertyUpdate(Edge(INVALID), i);
hegyi@172
   224
    }
hegyi@172
   225
ladanyi@6
   226
  updateScrollRegion();
ladanyi@6
   227
}
ladanyi@6
   228
ladanyi@53
   229
void GraphDisplayerCanvas::clear()
ladanyi@6
   230
{
ladanyi@53
   231
  active_node=INVALID;
ladanyi@53
   232
  active_edge=INVALID;
ladanyi@53
   233
  forming_edge=INVALID;
ladanyi@6
   234
hegyi@96
   235
  for (NodeIt n((mytab.mapstorage).graph); n != INVALID; ++n)
ladanyi@6
   236
  {
ladanyi@53
   237
    delete nodesmap[n];
ladanyi@53
   238
    delete nodetextmap[n];
ladanyi@6
   239
  }
ladanyi@6
   240
hegyi@96
   241
  for (EdgeIt e((mytab.mapstorage).graph); e != INVALID; ++e)
ladanyi@53
   242
  {
ladanyi@53
   243
    delete edgesmap[e];
ladanyi@53
   244
    delete edgetextmap[e];
ladanyi@53
   245
  }
hegyi@172
   246
hegyi@172
   247
  is_drawn=false;
ladanyi@6
   248
}
hegyi@154
   249
hegyi@157
   250
void GraphDisplayerCanvas::setView(bool autoscale_p, bool zoomtrack_p, double width_p, double radius_p)
hegyi@154
   251
{
hegyi@154
   252
  autoscale=autoscale_p;
hegyi@157
   253
  edge_width=width_p;
hegyi@157
   254
  radius_size=radius_p;
hegyi@156
   255
hegyi@156
   256
  if((!zoomtrack) && zoomtrack_p)
hegyi@156
   257
    {
hegyi@156
   258
      fixed_zoom_factor=get_pixels_per_unit();
hegyi@156
   259
    }
hegyi@156
   260
hegyi@156
   261
  zoomtrack=zoomtrack_p;
hegyi@156
   262
hegyi@154
   263
  propertyChange(false, N_RADIUS);
hegyi@157
   264
  propertyChange(true, E_WIDTH);
hegyi@154
   265
}
hegyi@154
   266
hegyi@157
   267
void GraphDisplayerCanvas::getView(bool & autoscale_p, bool & zoomtrack_p, double& width_p, double& radius_p)
hegyi@154
   268
{
hegyi@154
   269
  autoscale_p=autoscale;
hegyi@156
   270
  zoomtrack_p=zoomtrack;
hegyi@157
   271
  width_p=edge_width;
hegyi@157
   272
  radius_p=radius_size;
hegyi@154
   273
}
hegyi@160
   274
hegyi@160
   275
void GraphDisplayerCanvas::reDesignGraph()
hegyi@160
   276
{
hegyi@166
   277
  double min_dist=20;
hegyi@166
   278
  double init_vector_length=25;
hegyi@166
   279
hegyi@166
   280
  if(!was_redesigned)
hegyi@166
   281
    {
hegyi@166
   282
      NodeIt i((mytab.mapstorage).graph);
hegyi@167
   283
alpar@168
   284
      dim2::Point<double> init(init_vector_length*rnd(),
alpar@168
   285
			       init_vector_length*rnd());
hegyi@166
   286
      moveNode(init.x, init.y, nodesmap[i], i);
hegyi@166
   287
      was_redesigned=true;
hegyi@166
   288
    }
hegyi@166
   289
  
hegyi@160
   290
hegyi@160
   291
  //iteration counter
hegyi@160
   292
  for(int l=0;l<iterations;l++)
hegyi@160
   293
    {
hegyi@160
   294
      Graph::NodeMap<double> x(mytab.mapstorage.graph);
hegyi@160
   295
      Graph::NodeMap<double> y(mytab.mapstorage.graph);
hegyi@160
   296
      XYMap<Graph::NodeMap<double> > actual_forces;
hegyi@160
   297
      actual_forces.setXMap(x);
hegyi@160
   298
      actual_forces.setYMap(y);
hegyi@160
   299
hegyi@160
   300
      lemon::dim2::Point<double> delta;
hegyi@160
   301
hegyi@160
   302
      //count actual force for each nodes
hegyi@160
   303
      for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
hegyi@160
   304
	{
hegyi@160
   305
	  //propulsation of nodes
hegyi@160
   306
	  for (NodeIt j((mytab.mapstorage).graph); j!=INVALID; ++j)
hegyi@160
   307
	    {
hegyi@160
   308
	      if(i!=j)
hegyi@160
   309
		{
hegyi@160
   310
		  delta=((mytab.mapstorage).coords[i]-(mytab.mapstorage).coords[j]);
hegyi@160
   311
hegyi@160
   312
		  double length_sqr=delta.normSquare();
hegyi@160
   313
		  double length=sqrt(length_sqr);
hegyi@160
   314
		  if(length_sqr<min_dist)
hegyi@160
   315
		    {
hegyi@160
   316
		      length_sqr=min_dist;
hegyi@160
   317
		    }
hegyi@160
   318
hegyi@160
   319
		  //normalize vector
hegyi@160
   320
		  delta/=length;
hegyi@160
   321
hegyi@160
   322
		  //calculating propulsation strength
hegyi@160
   323
		  //greater distance menas smaller propulsation strength
hegyi@160
   324
		  delta*=propulsation/length_sqr;
hegyi@160
   325
		    
hegyi@160
   326
		  actual_forces.set(i,(actual_forces[i]+delta));
hegyi@160
   327
		}
hegyi@160
   328
	    }
hegyi@160
   329
	  //attraction of nodes, to which actual node is bound
hegyi@160
   330
	  for(OutEdgeIt ei((mytab.mapstorage).graph,i);ei!=INVALID;++ei)
hegyi@160
   331
	    {
hegyi@160
   332
	      delta=((mytab.mapstorage).coords[i]-(mytab.mapstorage).coords[mytab.mapstorage.graph.target(ei)]);
hegyi@160
   333
hegyi@160
   334
	      double length_sqr=delta.normSquare();
hegyi@160
   335
	      double length=sqrt(length_sqr);
hegyi@160
   336
	      if(length_sqr<min_dist)
hegyi@160
   337
		{
hegyi@160
   338
		  length_sqr=min_dist;
hegyi@160
   339
		}
hegyi@160
   340
hegyi@160
   341
	      //normalize vector
hegyi@160
   342
	      delta/=length;
hegyi@160
   343
hegyi@160
   344
	      //calculating attraction strength
hegyi@160
   345
	      //greater distance means greater strength
hegyi@160
   346
	      delta*=attraction*length;
hegyi@160
   347
hegyi@160
   348
	      actual_forces.set(i,actual_forces[i]-delta);
hegyi@160
   349
	    }
hegyi@160
   350
	  for(InEdgeIt ei((mytab.mapstorage).graph,i);ei!=INVALID;++ei)
hegyi@160
   351
	    {
hegyi@160
   352
	      delta=((mytab.mapstorage).coords[i]-(mytab.mapstorage).coords[mytab.mapstorage.graph.source(ei)]);
hegyi@160
   353
hegyi@160
   354
	      double length_sqr=delta.normSquare();
hegyi@160
   355
	      double length=sqrt(length_sqr);
hegyi@160
   356
	      if(length_sqr<min_dist)
hegyi@160
   357
		{
hegyi@160
   358
		  length_sqr=min_dist;
hegyi@160
   359
		}
hegyi@160
   360
hegyi@160
   361
	      //normalize vector
hegyi@160
   362
	      delta/=length;
hegyi@160
   363
hegyi@160
   364
	      //calculating attraction strength
hegyi@160
   365
	      //greater distance means greater strength
hegyi@160
   366
	      delta*=attraction*length;
hegyi@160
   367
hegyi@160
   368
	      actual_forces.set(i,actual_forces[i]-delta);
hegyi@160
   369
	    }
hegyi@160
   370
	}
hegyi@160
   371
      for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
hegyi@160
   372
	{
hegyi@160
   373
	  moveNode(actual_forces[i].x, actual_forces[i].y, nodesmap[i], i);
hegyi@160
   374
	}
hegyi@160
   375
    }
hegyi@160
   376
}
hegyi@160
   377
hegyi@160
   378
void GraphDisplayerCanvas::get_design_data(double & attraction_p, double & propulsation_p, int & iterations_p)
hegyi@160
   379
{
hegyi@160
   380
  attraction_p=attraction;
hegyi@160
   381
  propulsation_p=propulsation;
hegyi@160
   382
  iterations_p=iterations;
hegyi@160
   383
}
hegyi@160
   384
hegyi@160
   385
void GraphDisplayerCanvas::set_attraction(double attraction_p)
hegyi@160
   386
{
hegyi@160
   387
  attraction=attraction_p;
hegyi@160
   388
}
hegyi@160
   389
hegyi@160
   390
void GraphDisplayerCanvas::set_propulsation(double propulsation_p)
hegyi@160
   391
{
hegyi@160
   392
  propulsation=propulsation_p;
hegyi@160
   393
}
hegyi@160
   394
hegyi@160
   395
void GraphDisplayerCanvas::set_iteration(int iterations_p)
hegyi@160
   396
{
hegyi@160
   397
  iterations=iterations_p;
hegyi@160
   398
}
hegyi@160
   399