COIN-OR::LEMON - Graph Library

source: glemon-0.x/graph_displayer_canvas.cc

fastopen tip
Last change on this file was 204:8fec6a6472fe, checked in by Hegyi Péter, 17 years ago

The much faster way.

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