graph_displayer_canvas.cc
author Alpar Juttner <alpar@cs.elte.hu>
Fri, 10 Oct 2008 13:36:20 +0100
changeset 7 f227a74db59d
permissions -rw-r--r--
Update to compile with the latest LEMON (version 1.0 or [5e12d7734036])
     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