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