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