COIN-OR::LEMON - Graph Library

source: glemon/graph_displayer_canvas.cc @ 3:2cc5ed6e6255

Last change on this file since 3:2cc5ed6e6255 was 1:67188bd752db, checked in by Peter Hegyi <hegyi@…>, 16 years ago

SVN revision 3500 made compilable with Lemon 1.0.

File size: 12.0 KB
Line 
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
25DigraphDisplayerCanvas::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
48void 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
72DigraphDisplayerCanvas::~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
87void 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
99void DigraphDisplayerCanvas::propertyUpdate(Arc arc)
100{
101  for(int i=0;i<EDGE_PROPERTY_NUM;i++)
102    {
103      propertyUpdate(arc, i);
104    }
105}
106
107void DigraphDisplayerCanvas::propertyUpdate(Node node)
108{
109  for(int i=0;i<NODE_PROPERTY_NUM;i++)
110    {
111      propertyUpdate(node, i);
112    }
113}
114
115void 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
173void 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
230void 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
302void 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
323void 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
340void 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
348void 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
Note: See TracBrowser for help on using the repository browser.