graph_displayer_canvas.cc
changeset 4 244d8c60b997
equal deleted inserted replaced
-1:000000000000 0:e50c7f77e162
       
     1 /* -*- C++ -*-
       
     2  *
       
     3  * This file is a part of LEMON, a generic C++ optimization library
       
     4  *
       
     5  * Copyright (C) 2003-2006
       
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
       
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
       
     8  *
       
     9  * Permission to use, modify and distribute this software is granted
       
    10  * provided that this copyright notice appears in all copies. For
       
    11  * precise terms see the accompanying LICENSE file.
       
    12  *
       
    13  * This software is provided "AS IS" with no warranty of any kind,
       
    14  * express or implied, and with no claim as to its suitability for any
       
    15  * purpose.
       
    16  *
       
    17  */
       
    18 
       
    19 #include <mapstorage.h>
       
    20 #include <nbtab.h>
       
    21 #include <graph_displayer_canvas.h>
       
    22 #include <lemon/random.h>
       
    23 #include <cmath>
       
    24 
       
    25 DigraphDisplayerCanvas::DigraphDisplayerCanvas(NoteBookTab & mainw) :
       
    26   nodesmap(mainw.mapstorage->digraph), arcsmap(mainw.mapstorage->digraph), arctextmap(mainw.mapstorage->digraph),
       
    27   nodetextmap(mainw.mapstorage->digraph), displayed_graph(*(root()), 0, 0),
       
    28   isbutton(0), active_item(NULL), target_item(NULL), nodemap_to_edit(""),
       
    29   arcmap_to_edit(""), autoscale(true), zoomtrack(false), radius_size(20), arc_width(10),
       
    30   was_redesigned(false), is_drawn(false), mytab(mainw),
       
    31   background_set(false)
       
    32 {
       
    33   //add mouse scroll event handler - it won't be changed, it handles zoom
       
    34   signal_event().connect(sigc::mem_fun(*this, &DigraphDisplayerCanvas::scrollEventHandler), false);
       
    35 
       
    36   //base event handler is move tool
       
    37   actual_handler=signal_event().connect(sigc::mem_fun(*this, &DigraphDisplayerCanvas::moveEventHandler), false);
       
    38   actual_tool=MOVE;
       
    39 
       
    40 
       
    41   active_node=INVALID;
       
    42   active_arc=INVALID;
       
    43   forming_arc=INVALID;
       
    44 
       
    45   setBackground();
       
    46 }
       
    47 
       
    48 void DigraphDisplayerCanvas::setBackground()
       
    49 {
       
    50   if (background_set)
       
    51   {
       
    52     delete background;
       
    53   }
       
    54   if (mytab.mapstorage->isBackgroundSet())
       
    55   {
       
    56     background_set = true;
       
    57     refBackground = Gdk::Pixbuf::create_from_file(
       
    58       mytab.mapstorage->getBackgroundFilename());
       
    59     background = new Gnome::Canvas::Pixbuf(
       
    60         *(root()),
       
    61         0.0 - refBackground->get_width() / 2.0,
       
    62         0.0 - refBackground->get_height() / 2.0,
       
    63         refBackground);
       
    64     background->lower_to_bottom();
       
    65   }
       
    66   else
       
    67   {
       
    68     background_set = false;
       
    69   }
       
    70 }
       
    71 
       
    72 DigraphDisplayerCanvas::~DigraphDisplayerCanvas()
       
    73 {
       
    74   for (NodeIt n((mytab.mapstorage)->digraph); n != INVALID; ++n)
       
    75     {
       
    76       delete nodesmap[n];
       
    77       delete nodetextmap[n];
       
    78     }
       
    79   
       
    80   for (ArcIt e((mytab.mapstorage)->digraph); e != INVALID; ++e)
       
    81     {
       
    82       delete arcsmap[e];
       
    83       delete arctextmap[e];
       
    84     }
       
    85 }
       
    86 
       
    87 void DigraphDisplayerCanvas::propertyChange(bool itisarc, int prop)
       
    88 {
       
    89   if(itisarc)
       
    90     {
       
    91       propertyUpdate(Arc(INVALID), prop);
       
    92     }
       
    93   else
       
    94     {
       
    95       propertyUpdate(Node(INVALID), prop);
       
    96     }
       
    97 }
       
    98 
       
    99 void DigraphDisplayerCanvas::propertyUpdate(Arc arc)
       
   100 {
       
   101   for(int i=0;i<EDGE_PROPERTY_NUM;i++)
       
   102     {
       
   103       propertyUpdate(arc, i);
       
   104     }
       
   105 }
       
   106 
       
   107 void DigraphDisplayerCanvas::propertyUpdate(Node node)
       
   108 {
       
   109   for(int i=0;i<NODE_PROPERTY_NUM;i++)
       
   110     {
       
   111       propertyUpdate(node, i);
       
   112     }
       
   113 }
       
   114 
       
   115 void DigraphDisplayerCanvas::propertyUpdate(Node node, int prop)
       
   116 {
       
   117   std::string mapname=mytab.getActiveNodeMap(prop);
       
   118 
       
   119   if(is_drawn)
       
   120   {
       
   121     if(mapname!="")
       
   122     {
       
   123       std::vector<std::string> nodemaps = mytab.mapstorage->getNodeMapList();
       
   124       bool found = false;
       
   125       for (std::vector<std::string>::const_iterator it = nodemaps.begin();
       
   126           it != nodemaps.end(); ++it)
       
   127       {
       
   128         if (*it == mapname)
       
   129         {
       
   130           found = true;
       
   131           break;
       
   132         }
       
   133       }
       
   134       if (found)
       
   135       {
       
   136         switch(prop)
       
   137         {
       
   138           case N_RADIUS:
       
   139             changeNodeRadius(mapname, node);
       
   140             break;
       
   141           case N_COLOR:
       
   142             changeNodeColor(mapname, node);
       
   143             break;
       
   144           case N_TEXT:
       
   145             changeNodeText(mapname, node);
       
   146             break;
       
   147           default:
       
   148             std::cerr<<"Error\n";
       
   149         }
       
   150       }
       
   151     }
       
   152     else //mapname==""
       
   153     {
       
   154       Node node=INVALID;
       
   155       switch(prop)
       
   156       {
       
   157         case N_RADIUS:
       
   158           resetNodeRadius(node);
       
   159           break;
       
   160         case N_COLOR:
       
   161           resetNodeColor(node);
       
   162           break;
       
   163         case N_TEXT:
       
   164           resetNodeText(node);
       
   165           break;
       
   166         default:
       
   167           std::cerr<<"Error\n";
       
   168       }
       
   169     }
       
   170   }
       
   171 }
       
   172 
       
   173 void DigraphDisplayerCanvas::propertyUpdate(Arc arc, int prop)
       
   174 {
       
   175   std::string mapname=mytab.getActiveArcMap(prop);
       
   176 
       
   177   if(is_drawn)
       
   178   {
       
   179     if(mapname!="")
       
   180     {
       
   181       std::vector<std::string> arcmaps = mytab.mapstorage->getArcMapList();
       
   182       bool found = false;
       
   183       for (std::vector<std::string>::const_iterator it = arcmaps.begin();
       
   184           it != arcmaps.end(); ++it)
       
   185       {
       
   186         if (*it == mapname)
       
   187         {
       
   188           found = true;
       
   189           break;
       
   190         }
       
   191       }
       
   192       if (found)
       
   193       {
       
   194         switch(prop)
       
   195         {
       
   196           case E_WIDTH:
       
   197             changeArcWidth(mapname, arc);
       
   198             break;
       
   199           case E_COLOR:
       
   200             changeArcColor(mapname, arc);
       
   201             break;
       
   202           case E_TEXT:
       
   203             changeArcText(mapname, arc);
       
   204             break;
       
   205           default:
       
   206             std::cerr<<"Error\n";
       
   207         }
       
   208       }
       
   209     }
       
   210     else //mapname==""
       
   211     {
       
   212       switch(prop)
       
   213       {
       
   214         case E_WIDTH:
       
   215           resetArcWidth(arc);
       
   216           break;
       
   217         case E_COLOR:
       
   218           resetArcColor(arc);
       
   219           break;
       
   220         case E_TEXT:
       
   221           resetArcText(arc);
       
   222           break;
       
   223         default:
       
   224           std::cerr<<"Error\n";
       
   225       }
       
   226     }
       
   227   }
       
   228 }
       
   229 
       
   230 void DigraphDisplayerCanvas::drawDigraph()
       
   231 {
       
   232   //first arcs are drawn, to hide joining with nodes later
       
   233 
       
   234   for (ArcIt i((mytab.mapstorage)->digraph); i!=INVALID; ++i)
       
   235   {
       
   236     if (mytab.mapstorage->digraph.source(i) == mytab.mapstorage->digraph.target(i))
       
   237     {
       
   238       arcsmap[i]=new LoopArc(displayed_graph, i, *this);
       
   239     }
       
   240     else
       
   241     {
       
   242       arcsmap[i]=new BrokenArc(displayed_graph, i, *this);
       
   243     }
       
   244     //initializing arc-text as well, to empty string
       
   245 
       
   246     XY text_pos=mytab.mapstorage->getArrowCoords(i);
       
   247     text_pos+=(XY(10,10));
       
   248 
       
   249     arctextmap[i]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
       
   250     arctextmap[i]->property_fill_color().set_value("darkgreen");
       
   251     arctextmap[i]->signal_event().connect(sigc::mem_fun(*this, &DigraphDisplayerCanvas::mapEditEventHandler), false);
       
   252     arctextmap[i]->raise_to_top();
       
   253   }
       
   254 
       
   255   //afterwards nodes come to be drawn
       
   256 
       
   257   for (NodeIt i((mytab.mapstorage)->digraph); i!=INVALID; ++i)
       
   258   {
       
   259     //drawing bule nodes, with black line around them
       
   260 
       
   261     nodesmap[i]=new Gnome::Canvas::Ellipse(
       
   262         displayed_graph,
       
   263         mytab.mapstorage->getNodeCoords(i).x-20,
       
   264         mytab.mapstorage->getNodeCoords(i).y-20,
       
   265         mytab.mapstorage->getNodeCoords(i).x+20,
       
   266         mytab.mapstorage->getNodeCoords(i).y+20);
       
   267     *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue");
       
   268     *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black");
       
   269     nodesmap[i]->raise_to_top();
       
   270 
       
   271     //initializing arc-text as well, to empty string
       
   272 
       
   273     XY text_pos(
       
   274         (mytab.mapstorage->getNodeCoords(i).x+node_property_defaults[N_RADIUS]+5),
       
   275         (mytab.mapstorage->getNodeCoords(i).y+node_property_defaults[N_RADIUS]+5));
       
   276 
       
   277     nodetextmap[i]=new Gnome::Canvas::Text(displayed_graph,
       
   278         text_pos.x, text_pos.y, "");
       
   279     nodetextmap[i]->property_fill_color().set_value("darkblue");
       
   280     nodetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &DigraphDisplayerCanvas::mapEditEventHandler), false);
       
   281     nodetextmap[i]->raise_to_top();
       
   282   }
       
   283 
       
   284   is_drawn=true;
       
   285 
       
   286   //upon drawing digraph
       
   287   //properties have to
       
   288   //be set in as well
       
   289   for(int i=0;i<NODE_PROPERTY_NUM;i++)
       
   290     {
       
   291       propertyUpdate(Node(INVALID), i);
       
   292     }
       
   293 
       
   294   for(int i=0;i<EDGE_PROPERTY_NUM;i++)
       
   295     {
       
   296       propertyUpdate(Arc(INVALID), i);
       
   297     }
       
   298 
       
   299   updateScrollRegion();
       
   300 }
       
   301 
       
   302 void DigraphDisplayerCanvas::clear()
       
   303 {
       
   304   active_node=INVALID;
       
   305   active_arc=INVALID;
       
   306   forming_arc=INVALID;
       
   307 
       
   308   for (NodeIt n((mytab.mapstorage)->digraph); n != INVALID; ++n)
       
   309   {
       
   310     delete nodesmap[n];
       
   311     delete nodetextmap[n];
       
   312   }
       
   313 
       
   314   for (ArcIt e((mytab.mapstorage)->digraph); e != INVALID; ++e)
       
   315   {
       
   316     delete arcsmap[e];
       
   317     delete arctextmap[e];
       
   318   }
       
   319 
       
   320   is_drawn=false;
       
   321 }
       
   322 
       
   323 void DigraphDisplayerCanvas::setView(bool autoscale_p, bool zoomtrack_p, double width_p, double radius_p)
       
   324 {
       
   325   autoscale=autoscale_p;
       
   326   arc_width=width_p;
       
   327   radius_size=radius_p;
       
   328 
       
   329   if((!zoomtrack) && zoomtrack_p)
       
   330     {
       
   331       fixed_zoom_factor=get_pixels_per_unit();
       
   332     }
       
   333 
       
   334   zoomtrack=zoomtrack_p;
       
   335 
       
   336   propertyChange(false, N_RADIUS);
       
   337   propertyChange(true, E_WIDTH);
       
   338 }
       
   339 
       
   340 void DigraphDisplayerCanvas::getView(bool & autoscale_p, bool & zoomtrack_p, double& width_p, double& radius_p)
       
   341 {
       
   342   autoscale_p=autoscale;
       
   343   zoomtrack_p=zoomtrack;
       
   344   width_p=arc_width;
       
   345   radius_p=radius_size;
       
   346 }
       
   347 
       
   348 void DigraphDisplayerCanvas::reDesignDigraph()
       
   349 {
       
   350   MapStorage& ms = *mytab.mapstorage;
       
   351   NodeIt firstnode(ms.digraph);
       
   352   //is it not an empty digraph?
       
   353   if(firstnode!=INVALID)
       
   354     {
       
   355       double max_coord=50000;
       
   356       double min_dist=20;
       
   357       double init_vector_length=25;
       
   358 
       
   359       if(!was_redesigned)
       
   360 	{
       
   361 	  NodeIt i(ms.digraph);
       
   362 
       
   363 	  dim2::Point<double> init(init_vector_length*rnd(),
       
   364 				   init_vector_length*rnd());
       
   365 	  moveNode(init.x, init.y, nodesmap[i], i);
       
   366 	  was_redesigned=true;
       
   367 	}
       
   368 
       
   369       double attraction;
       
   370       double propulsation;
       
   371       int iterations;
       
   372 
       
   373       ms.get_design_data(attraction, propulsation, iterations);
       
   374 
       
   375       //iteration counter
       
   376       for(int l=0;l<iterations;l++)
       
   377 	{
       
   378 	  Digraph::NodeMap<double> x(ms.digraph);
       
   379 	  Digraph::NodeMap<double> y(ms.digraph);
       
   380 	  XYMap<Digraph::NodeMap<double> > actual_forces;
       
   381 	  actual_forces.setXMap(x);
       
   382 	  actual_forces.setYMap(y);
       
   383 
       
   384 	  //count actual force for each nodes
       
   385 	  for (NodeIt i(ms.digraph); i!=INVALID; ++i)
       
   386 	    {
       
   387 	      //propulsation of nodes
       
   388 	      for (NodeIt j(ms.digraph); j!=INVALID; ++j)
       
   389 		{
       
   390 		  if(i!=j)
       
   391 		    {
       
   392 		      lemon::dim2::Point<double> delta =
       
   393 			(ms.getNodeCoords(i)-
       
   394 			 ms.getNodeCoords(j));
       
   395 
       
   396 		      const double length_sqr=std::max(delta.normSquare(),min_dist);
       
   397 
       
   398 		      //normalize vector
       
   399 		      delta/=sqrt(length_sqr);
       
   400 
       
   401 		      //calculating propulsation strength
       
   402 		      //greater distance menas smaller propulsation strength
       
   403 		      delta*=propulsation/length_sqr;
       
   404 		    
       
   405 		      actual_forces.set(i,(actual_forces[i]+delta));
       
   406 		    }
       
   407 		}
       
   408             //attraction of nodes, to which actual node is bound
       
   409             for(OutArcIt ei(ms.digraph,i);ei!=INVALID;++ei)
       
   410               {
       
   411                 lemon::dim2::Point<double> delta =
       
   412                   (ms.getNodeCoords(i)-
       
   413                    ms.getNodeCoords(ms.digraph.target(ei)));
       
   414 
       
   415                 //calculating attraction strength
       
   416                 //greater distance means greater strength
       
   417                 delta*=attraction;
       
   418 
       
   419                 actual_forces.set(i,actual_forces[i]-delta);
       
   420               }
       
   421                     for(InArcIt ei(ms.digraph,i);ei!=INVALID;++ei)
       
   422               {
       
   423                 lemon::dim2::Point<double> delta =
       
   424                   (ms.getNodeCoords(i)-
       
   425                    ms.getNodeCoords(ms.digraph.source(ei)));
       
   426 
       
   427                 //calculating attraction strength
       
   428                 //greater distance means greater strength
       
   429                 delta*=attraction;
       
   430 
       
   431                 actual_forces.set(i,actual_forces[i]-delta);
       
   432               }
       
   433 	    }
       
   434 	  for (NodeIt i(ms.digraph); i!=INVALID; ++i)
       
   435 	    {
       
   436 	      if((ms.getNodeCoords(i).x)+actual_forces[i].x>max_coord)
       
   437 		{
       
   438 		  actual_forces[i].x=max_coord-(ms.getNodeCoords(i).x);
       
   439 		  std::cout << "Correction! " << ((ms.getNodeCoords(i).x)+actual_forces[i].x) << std::endl;
       
   440 		}
       
   441 	      else if((ms.getNodeCoords(i).x)+actual_forces[i].x<(0-max_coord))
       
   442 		{
       
   443 		  actual_forces[i].x=0-max_coord-(ms.getNodeCoords(i).x);
       
   444 		  std::cout << "Correction! " << ((ms.getNodeCoords(i).x)+actual_forces[i].x) << std::endl;
       
   445 		}
       
   446 	      if((ms.getNodeCoords(i).y)+actual_forces[i].y>max_coord)
       
   447 		{
       
   448 		  actual_forces[i].y=max_coord-(ms.getNodeCoords(i).y);
       
   449 		  std::cout << "Correction! " << ((ms.getNodeCoords(i).y)+actual_forces[i].y) << std::endl;
       
   450 		}
       
   451 	      else if((ms.getNodeCoords(i).y)+actual_forces[i].y<(0-max_coord))
       
   452 		{
       
   453 		  actual_forces[i].y=0-max_coord-(ms.getNodeCoords(i).y);
       
   454 		  std::cout << "Correction! " << ((ms.getNodeCoords(i).y)+actual_forces[i].y) << std::endl;
       
   455 		}
       
   456 	      moveNode(actual_forces[i].x, actual_forces[i].y, nodesmap[i], i);
       
   457 	    }
       
   458 	}
       
   459     }
       
   460 }
       
   461