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.)
     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), 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   //dummy=dummy;
    67 
    68   std::string mapname=mytab.getActiveNodeMap(prop);
    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   //dummy=dummy;
   114 
   115   std::string mapname=mytab.getActiveEdgeMap(prop);
   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 void GraphDisplayerCanvas::drawGraph()
   157 {
   158   //first edges are drawn, to hide joining with nodes later
   159 
   160   for (EdgeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
   161   {
   162     if (mytab.mapstorage.graph.source(i) == mytab.mapstorage.graph.target(i))
   163     {
   164       edgesmap[i]=new LoopEdge(displayed_graph, i, *this);
   165     }
   166     else
   167     {
   168       edgesmap[i]=new BrokenEdge(displayed_graph, i, *this);
   169     }
   170     //initializing edge-text as well, to empty string
   171 
   172     XY text_pos=mytab.mapstorage.arrow_pos[i];
   173     text_pos+=(XY(10,10));
   174 
   175     edgetextmap[i]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
   176     edgetextmap[i]->property_fill_color().set_value("darkgreen");
   177     edgetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false);
   178     edgetextmap[i]->raise_to_top();
   179   }
   180 
   181   //afterwards nodes come to be drawn
   182 
   183   for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
   184   {
   185     //drawing bule nodes, with black line around them
   186 
   187     nodesmap[i]=new Gnome::Canvas::Ellipse(
   188         displayed_graph,
   189         (mytab.mapstorage).coords[i].x-20,
   190         (mytab.mapstorage).coords[i].y-20,
   191         (mytab.mapstorage).coords[i].x+20,
   192         (mytab.mapstorage).coords[i].y+20);
   193     *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue");
   194     *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black");
   195     nodesmap[i]->raise_to_top();
   196 
   197     //initializing edge-text as well, to empty string
   198 
   199     XY text_pos(
   200         ((mytab.mapstorage).coords[i].x+node_property_defaults[N_RADIUS]+5),
   201         ((mytab.mapstorage).coords[i].y+node_property_defaults[N_RADIUS]+5));
   202 
   203     nodetextmap[i]=new Gnome::Canvas::Text(displayed_graph,
   204         text_pos.x, text_pos.y, "");
   205     nodetextmap[i]->property_fill_color().set_value("darkblue");
   206     nodetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false);
   207     nodetextmap[i]->raise_to_top();
   208   }
   209 
   210   updateScrollRegion();
   211 }
   212 
   213 void GraphDisplayerCanvas::clear()
   214 {
   215   active_node=INVALID;
   216   active_edge=INVALID;
   217   forming_edge=INVALID;
   218 
   219   for (NodeIt n((mytab.mapstorage).graph); n != INVALID; ++n)
   220   {
   221     delete nodesmap[n];
   222     delete nodetextmap[n];
   223   }
   224 
   225   for (EdgeIt e((mytab.mapstorage).graph); e != INVALID; ++e)
   226   {
   227     delete edgesmap[e];
   228     delete edgetextmap[e];
   229   }
   230 }
   231 
   232 void GraphDisplayerCanvas::setView(bool autoscale_p, bool zoomtrack_p, double width_p, double radius_p)
   233 {
   234   autoscale=autoscale_p;
   235   edge_width=width_p;
   236   radius_size=radius_p;
   237 
   238   if((!zoomtrack) && zoomtrack_p)
   239     {
   240       fixed_zoom_factor=get_pixels_per_unit();
   241     }
   242 
   243   zoomtrack=zoomtrack_p;
   244 
   245   propertyChange(false, N_RADIUS);
   246   propertyChange(true, E_WIDTH);
   247 }
   248 
   249 void GraphDisplayerCanvas::getView(bool & autoscale_p, bool & zoomtrack_p, double& width_p, double& radius_p)
   250 {
   251   autoscale_p=autoscale;
   252   zoomtrack_p=zoomtrack;
   253   width_p=edge_width;
   254   radius_p=radius_size;
   255 }
   256 
   257 void GraphDisplayerCanvas::reDesignGraph()
   258 {
   259   double min_dist=20;
   260   double init_vector_length=25;
   261 
   262   if(!was_redesigned)
   263     {
   264       NodeIt i((mytab.mapstorage).graph);
   265 
   266       dim2::Point<double> init(init_vector_length*rnd(),
   267 			       init_vector_length*rnd());
   268       moveNode(init.x, init.y, nodesmap[i], i);
   269       was_redesigned=true;
   270     }
   271   
   272 
   273   //iteration counter
   274   for(int l=0;l<iterations;l++)
   275     {
   276       Graph::NodeMap<double> x(mytab.mapstorage.graph);
   277       Graph::NodeMap<double> y(mytab.mapstorage.graph);
   278       XYMap<Graph::NodeMap<double> > actual_forces;
   279       actual_forces.setXMap(x);
   280       actual_forces.setYMap(y);
   281 
   282       lemon::dim2::Point<double> delta;
   283 
   284       //count actual force for each nodes
   285       for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
   286 	{
   287 	  //propulsation of nodes
   288 	  for (NodeIt j((mytab.mapstorage).graph); j!=INVALID; ++j)
   289 	    {
   290 	      if(i!=j)
   291 		{
   292 		  delta=((mytab.mapstorage).coords[i]-(mytab.mapstorage).coords[j]);
   293 
   294 		  double length_sqr=delta.normSquare();
   295 		  double length=sqrt(length_sqr);
   296 		  if(length_sqr<min_dist)
   297 		    {
   298 		      length_sqr=min_dist;
   299 		    }
   300 
   301 		  //normalize vector
   302 		  delta/=length;
   303 
   304 		  //calculating propulsation strength
   305 		  //greater distance menas smaller propulsation strength
   306 		  delta*=propulsation/length_sqr;
   307 		    
   308 		  actual_forces.set(i,(actual_forces[i]+delta));
   309 		}
   310 	    }
   311 	  //attraction of nodes, to which actual node is bound
   312 	  for(OutEdgeIt ei((mytab.mapstorage).graph,i);ei!=INVALID;++ei)
   313 	    {
   314 	      delta=((mytab.mapstorage).coords[i]-(mytab.mapstorage).coords[mytab.mapstorage.graph.target(ei)]);
   315 
   316 	      double length_sqr=delta.normSquare();
   317 	      double length=sqrt(length_sqr);
   318 	      if(length_sqr<min_dist)
   319 		{
   320 		  length_sqr=min_dist;
   321 		}
   322 
   323 	      //normalize vector
   324 	      delta/=length;
   325 
   326 	      //calculating attraction strength
   327 	      //greater distance means greater strength
   328 	      delta*=attraction*length;
   329 
   330 	      actual_forces.set(i,actual_forces[i]-delta);
   331 	    }
   332 	  for(InEdgeIt ei((mytab.mapstorage).graph,i);ei!=INVALID;++ei)
   333 	    {
   334 	      delta=((mytab.mapstorage).coords[i]-(mytab.mapstorage).coords[mytab.mapstorage.graph.source(ei)]);
   335 
   336 	      double length_sqr=delta.normSquare();
   337 	      double length=sqrt(length_sqr);
   338 	      if(length_sqr<min_dist)
   339 		{
   340 		  length_sqr=min_dist;
   341 		}
   342 
   343 	      //normalize vector
   344 	      delta/=length;
   345 
   346 	      //calculating attraction strength
   347 	      //greater distance means greater strength
   348 	      delta*=attraction*length;
   349 
   350 	      actual_forces.set(i,actual_forces[i]-delta);
   351 	    }
   352 	}
   353       for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
   354 	{
   355 	  moveNode(actual_forces[i].x, actual_forces[i].y, nodesmap[i], i);
   356 	}
   357     }
   358 }
   359 
   360 void GraphDisplayerCanvas::get_design_data(double & attraction_p, double & propulsation_p, int & iterations_p)
   361 {
   362   attraction_p=attraction;
   363   propulsation_p=propulsation;
   364   iterations_p=iterations;
   365 }
   366 
   367 void GraphDisplayerCanvas::set_attraction(double attraction_p)
   368 {
   369   attraction=attraction_p;
   370 }
   371 
   372 void GraphDisplayerCanvas::set_propulsation(double propulsation_p)
   373 {
   374   propulsation=propulsation_p;
   375 }
   376 
   377 void GraphDisplayerCanvas::set_iteration(int iterations_p)
   378 {
   379   iterations=iterations_p;
   380 }
   381