COIN-OR::LEMON - Graph Library

source: glemon-0.x/graph_displayer_canvas.cc @ 174:95872af46fc4

Last change on this file since 174:95872af46fc4 was 174:95872af46fc4, checked in by Alpar Juttner, 15 years ago

Add copyright headers

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