graph_displayer_canvas.cc
author alpar
Sun, 22 Oct 2006 09:24:15 +0000
changeset 168 a5f82cbbc1e4
parent 167 30a7be486475
child 172 fc1e478697d3
permissions -rwxr-xr-x
Fix usage of Random. (Random's doc should possibly be improved.)
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@166
    10
  iterations(20), attraction(0.05), propulsation(40000), was_redesigned(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@118
    66
  //dummy=dummy;
hegyi@94
    67
hegyi@96
    68
  std::string mapname=mytab.getActiveNodeMap(prop);
hegyi@94
    69
hegyi@94
    70
  if(mapname!="")
hegyi@94
    71
    {
hegyi@96
    72
      if( ( ((mytab.mapstorage).nodemap_storage).find(mapname) != ((mytab.mapstorage).nodemap_storage).end() ) )
hegyi@94
    73
	{
hegyi@94
    74
	  switch(prop)
hegyi@94
    75
	    {
hegyi@94
    76
	    case N_RADIUS:
hegyi@94
    77
	      changeNodeRadius(mapname, node);
hegyi@94
    78
	      break;
hegyi@94
    79
	    case N_COLOR:
hegyi@94
    80
	      changeNodeColor(mapname, node);
hegyi@94
    81
	      break;
hegyi@94
    82
	    case N_TEXT:
hegyi@94
    83
	      changeNodeText(mapname, node);
hegyi@94
    84
	      break;
hegyi@94
    85
	    default:
hegyi@94
    86
	      std::cerr<<"Error\n";
hegyi@94
    87
	    }
hegyi@94
    88
	}
hegyi@94
    89
    }
hegyi@94
    90
  else //mapname==""
hegyi@94
    91
    {
hegyi@94
    92
      Node node=INVALID;	
hegyi@94
    93
      switch(prop)
hegyi@94
    94
	{
hegyi@94
    95
	case N_RADIUS:
hegyi@94
    96
	  resetNodeRadius(node);
hegyi@94
    97
	  break;
hegyi@94
    98
	case N_COLOR:
hegyi@94
    99
	  resetNodeColor(node);
hegyi@94
   100
	  break;
hegyi@94
   101
	case N_TEXT:
hegyi@94
   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@118
   113
  //dummy=dummy;
hegyi@94
   114
hegyi@96
   115
  std::string mapname=mytab.getActiveEdgeMap(prop);
hegyi@94
   116
hegyi@94
   117
  if(mapname!="")
hegyi@94
   118
    {
hegyi@96
   119
      if( ( ((mytab.mapstorage).edgemap_storage).find(mapname) != ((mytab.mapstorage).edgemap_storage).end() ) )
hegyi@94
   120
	{
hegyi@94
   121
	  switch(prop)
hegyi@94
   122
	    {
hegyi@94
   123
	    case E_WIDTH:
hegyi@94
   124
	      changeEdgeWidth(mapname, edge);
hegyi@94
   125
	      break;
hegyi@94
   126
	    case E_COLOR:
hegyi@94
   127
	      changeEdgeColor(mapname, edge);
hegyi@94
   128
	      break;
hegyi@94
   129
	    case E_TEXT:
hegyi@94
   130
	      changeEdgeText(mapname, edge);
hegyi@94
   131
	      break;
hegyi@94
   132
	    default:
hegyi@94
   133
	      std::cerr<<"Error\n";
hegyi@94
   134
	    }
hegyi@94
   135
	}
hegyi@94
   136
    }
hegyi@94
   137
  else //mapname==""
hegyi@94
   138
    {
hegyi@94
   139
      switch(prop)
hegyi@94
   140
	{
hegyi@94
   141
	case E_WIDTH:
hegyi@94
   142
	  resetEdgeWidth(edge);
hegyi@94
   143
	  break;
hegyi@94
   144
	case E_COLOR:
hegyi@94
   145
	  resetEdgeColor(edge);
hegyi@94
   146
	  break;
hegyi@94
   147
	case E_TEXT:
hegyi@94
   148
	  resetEdgeText(edge);
hegyi@94
   149
	  break;
hegyi@94
   150
	default:
hegyi@94
   151
	  std::cerr<<"Error\n";
hegyi@94
   152
	}
hegyi@94
   153
    }
ladanyi@53
   154
}
ladanyi@53
   155
ladanyi@53
   156
void GraphDisplayerCanvas::drawGraph()
ladanyi@53
   157
{
ladanyi@6
   158
  //first edges are drawn, to hide joining with nodes later
ladanyi@6
   159
hegyi@96
   160
  for (EdgeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
ladanyi@6
   161
  {
ladanyi@151
   162
    if (mytab.mapstorage.graph.source(i) == mytab.mapstorage.graph.target(i))
ladanyi@151
   163
    {
ladanyi@151
   164
      edgesmap[i]=new LoopEdge(displayed_graph, i, *this);
ladanyi@151
   165
    }
ladanyi@151
   166
    else
ladanyi@151
   167
    {
ladanyi@151
   168
      edgesmap[i]=new BrokenEdge(displayed_graph, i, *this);
ladanyi@151
   169
    }
ladanyi@6
   170
    //initializing edge-text as well, to empty string
ladanyi@6
   171
ladanyi@98
   172
    XY text_pos=mytab.mapstorage.arrow_pos[i];
ladanyi@98
   173
    text_pos+=(XY(10,10));
hegyi@25
   174
hegyi@25
   175
    edgetextmap[i]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
hegyi@28
   176
    edgetextmap[i]->property_fill_color().set_value("darkgreen");
hegyi@149
   177
    edgetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false);
ladanyi@63
   178
    edgetextmap[i]->raise_to_top();
ladanyi@6
   179
  }
ladanyi@6
   180
ladanyi@6
   181
  //afterwards nodes come to be drawn
ladanyi@6
   182
hegyi@96
   183
  for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
ladanyi@6
   184
  {
ladanyi@6
   185
    //drawing bule nodes, with black line around them
ladanyi@6
   186
ladanyi@53
   187
    nodesmap[i]=new Gnome::Canvas::Ellipse(
ladanyi@53
   188
        displayed_graph,
hegyi@96
   189
        (mytab.mapstorage).coords[i].x-20,
hegyi@96
   190
        (mytab.mapstorage).coords[i].y-20,
hegyi@96
   191
        (mytab.mapstorage).coords[i].x+20,
hegyi@96
   192
        (mytab.mapstorage).coords[i].y+20);
ladanyi@6
   193
    *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue");
ladanyi@6
   194
    *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black");
ladanyi@63
   195
    nodesmap[i]->raise_to_top();
hegyi@28
   196
hegyi@28
   197
    //initializing edge-text as well, to empty string
hegyi@28
   198
hegyi@150
   199
    XY text_pos(
hegyi@96
   200
        ((mytab.mapstorage).coords[i].x+node_property_defaults[N_RADIUS]+5),
hegyi@96
   201
        ((mytab.mapstorage).coords[i].y+node_property_defaults[N_RADIUS]+5));
hegyi@28
   202
ladanyi@53
   203
    nodetextmap[i]=new Gnome::Canvas::Text(displayed_graph,
ladanyi@53
   204
        text_pos.x, text_pos.y, "");
hegyi@28
   205
    nodetextmap[i]->property_fill_color().set_value("darkblue");
hegyi@149
   206
    nodetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false);
ladanyi@63
   207
    nodetextmap[i]->raise_to_top();
ladanyi@6
   208
  }
ladanyi@6
   209
ladanyi@6
   210
  updateScrollRegion();
ladanyi@6
   211
}
ladanyi@6
   212
ladanyi@53
   213
void GraphDisplayerCanvas::clear()
ladanyi@6
   214
{
ladanyi@53
   215
  active_node=INVALID;
ladanyi@53
   216
  active_edge=INVALID;
ladanyi@53
   217
  forming_edge=INVALID;
ladanyi@6
   218
hegyi@96
   219
  for (NodeIt n((mytab.mapstorage).graph); n != INVALID; ++n)
ladanyi@6
   220
  {
ladanyi@53
   221
    delete nodesmap[n];
ladanyi@53
   222
    delete nodetextmap[n];
ladanyi@6
   223
  }
ladanyi@6
   224
hegyi@96
   225
  for (EdgeIt e((mytab.mapstorage).graph); e != INVALID; ++e)
ladanyi@53
   226
  {
ladanyi@53
   227
    delete edgesmap[e];
ladanyi@53
   228
    delete edgetextmap[e];
ladanyi@53
   229
  }
ladanyi@6
   230
}
hegyi@154
   231
hegyi@157
   232
void GraphDisplayerCanvas::setView(bool autoscale_p, bool zoomtrack_p, double width_p, double radius_p)
hegyi@154
   233
{
hegyi@154
   234
  autoscale=autoscale_p;
hegyi@157
   235
  edge_width=width_p;
hegyi@157
   236
  radius_size=radius_p;
hegyi@156
   237
hegyi@156
   238
  if((!zoomtrack) && zoomtrack_p)
hegyi@156
   239
    {
hegyi@156
   240
      fixed_zoom_factor=get_pixels_per_unit();
hegyi@156
   241
    }
hegyi@156
   242
hegyi@156
   243
  zoomtrack=zoomtrack_p;
hegyi@156
   244
hegyi@154
   245
  propertyChange(false, N_RADIUS);
hegyi@157
   246
  propertyChange(true, E_WIDTH);
hegyi@154
   247
}
hegyi@154
   248
hegyi@157
   249
void GraphDisplayerCanvas::getView(bool & autoscale_p, bool & zoomtrack_p, double& width_p, double& radius_p)
hegyi@154
   250
{
hegyi@154
   251
  autoscale_p=autoscale;
hegyi@156
   252
  zoomtrack_p=zoomtrack;
hegyi@157
   253
  width_p=edge_width;
hegyi@157
   254
  radius_p=radius_size;
hegyi@154
   255
}
hegyi@160
   256
hegyi@160
   257
void GraphDisplayerCanvas::reDesignGraph()
hegyi@160
   258
{
hegyi@166
   259
  double min_dist=20;
hegyi@166
   260
  double init_vector_length=25;
hegyi@166
   261
hegyi@166
   262
  if(!was_redesigned)
hegyi@166
   263
    {
hegyi@166
   264
      NodeIt i((mytab.mapstorage).graph);
hegyi@167
   265
alpar@168
   266
      dim2::Point<double> init(init_vector_length*rnd(),
alpar@168
   267
			       init_vector_length*rnd());
hegyi@166
   268
      moveNode(init.x, init.y, nodesmap[i], i);
hegyi@166
   269
      was_redesigned=true;
hegyi@166
   270
    }
hegyi@166
   271
  
hegyi@160
   272
hegyi@160
   273
  //iteration counter
hegyi@160
   274
  for(int l=0;l<iterations;l++)
hegyi@160
   275
    {
hegyi@160
   276
      Graph::NodeMap<double> x(mytab.mapstorage.graph);
hegyi@160
   277
      Graph::NodeMap<double> y(mytab.mapstorage.graph);
hegyi@160
   278
      XYMap<Graph::NodeMap<double> > actual_forces;
hegyi@160
   279
      actual_forces.setXMap(x);
hegyi@160
   280
      actual_forces.setYMap(y);
hegyi@160
   281
hegyi@160
   282
      lemon::dim2::Point<double> delta;
hegyi@160
   283
hegyi@160
   284
      //count actual force for each nodes
hegyi@160
   285
      for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
hegyi@160
   286
	{
hegyi@160
   287
	  //propulsation of nodes
hegyi@160
   288
	  for (NodeIt j((mytab.mapstorage).graph); j!=INVALID; ++j)
hegyi@160
   289
	    {
hegyi@160
   290
	      if(i!=j)
hegyi@160
   291
		{
hegyi@160
   292
		  delta=((mytab.mapstorage).coords[i]-(mytab.mapstorage).coords[j]);
hegyi@160
   293
hegyi@160
   294
		  double length_sqr=delta.normSquare();
hegyi@160
   295
		  double length=sqrt(length_sqr);
hegyi@160
   296
		  if(length_sqr<min_dist)
hegyi@160
   297
		    {
hegyi@160
   298
		      length_sqr=min_dist;
hegyi@160
   299
		    }
hegyi@160
   300
hegyi@160
   301
		  //normalize vector
hegyi@160
   302
		  delta/=length;
hegyi@160
   303
hegyi@160
   304
		  //calculating propulsation strength
hegyi@160
   305
		  //greater distance menas smaller propulsation strength
hegyi@160
   306
		  delta*=propulsation/length_sqr;
hegyi@160
   307
		    
hegyi@160
   308
		  actual_forces.set(i,(actual_forces[i]+delta));
hegyi@160
   309
		}
hegyi@160
   310
	    }
hegyi@160
   311
	  //attraction of nodes, to which actual node is bound
hegyi@160
   312
	  for(OutEdgeIt ei((mytab.mapstorage).graph,i);ei!=INVALID;++ei)
hegyi@160
   313
	    {
hegyi@160
   314
	      delta=((mytab.mapstorage).coords[i]-(mytab.mapstorage).coords[mytab.mapstorage.graph.target(ei)]);
hegyi@160
   315
hegyi@160
   316
	      double length_sqr=delta.normSquare();
hegyi@160
   317
	      double length=sqrt(length_sqr);
hegyi@160
   318
	      if(length_sqr<min_dist)
hegyi@160
   319
		{
hegyi@160
   320
		  length_sqr=min_dist;
hegyi@160
   321
		}
hegyi@160
   322
hegyi@160
   323
	      //normalize vector
hegyi@160
   324
	      delta/=length;
hegyi@160
   325
hegyi@160
   326
	      //calculating attraction strength
hegyi@160
   327
	      //greater distance means greater strength
hegyi@160
   328
	      delta*=attraction*length;
hegyi@160
   329
hegyi@160
   330
	      actual_forces.set(i,actual_forces[i]-delta);
hegyi@160
   331
	    }
hegyi@160
   332
	  for(InEdgeIt ei((mytab.mapstorage).graph,i);ei!=INVALID;++ei)
hegyi@160
   333
	    {
hegyi@160
   334
	      delta=((mytab.mapstorage).coords[i]-(mytab.mapstorage).coords[mytab.mapstorage.graph.source(ei)]);
hegyi@160
   335
hegyi@160
   336
	      double length_sqr=delta.normSquare();
hegyi@160
   337
	      double length=sqrt(length_sqr);
hegyi@160
   338
	      if(length_sqr<min_dist)
hegyi@160
   339
		{
hegyi@160
   340
		  length_sqr=min_dist;
hegyi@160
   341
		}
hegyi@160
   342
hegyi@160
   343
	      //normalize vector
hegyi@160
   344
	      delta/=length;
hegyi@160
   345
hegyi@160
   346
	      //calculating attraction strength
hegyi@160
   347
	      //greater distance means greater strength
hegyi@160
   348
	      delta*=attraction*length;
hegyi@160
   349
hegyi@160
   350
	      actual_forces.set(i,actual_forces[i]-delta);
hegyi@160
   351
	    }
hegyi@160
   352
	}
hegyi@160
   353
      for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
hegyi@160
   354
	{
hegyi@160
   355
	  moveNode(actual_forces[i].x, actual_forces[i].y, nodesmap[i], i);
hegyi@160
   356
	}
hegyi@160
   357
    }
hegyi@160
   358
}
hegyi@160
   359
hegyi@160
   360
void GraphDisplayerCanvas::get_design_data(double & attraction_p, double & propulsation_p, int & iterations_p)
hegyi@160
   361
{
hegyi@160
   362
  attraction_p=attraction;
hegyi@160
   363
  propulsation_p=propulsation;
hegyi@160
   364
  iterations_p=iterations;
hegyi@160
   365
}
hegyi@160
   366
hegyi@160
   367
void GraphDisplayerCanvas::set_attraction(double attraction_p)
hegyi@160
   368
{
hegyi@160
   369
  attraction=attraction_p;
hegyi@160
   370
}
hegyi@160
   371
hegyi@160
   372
void GraphDisplayerCanvas::set_propulsation(double propulsation_p)
hegyi@160
   373
{
hegyi@160
   374
  propulsation=propulsation_p;
hegyi@160
   375
}
hegyi@160
   376
hegyi@160
   377
void GraphDisplayerCanvas::set_iteration(int iterations_p)
hegyi@160
   378
{
hegyi@160
   379
  iterations=iterations_p;
hegyi@160
   380
}
hegyi@160
   381