COIN-OR::LEMON - Graph Library

source: glemon-0.x/graph_displayer_canvas.cc @ 172:fc1e478697d3

Last change on this file since 172:fc1e478697d3 was 172:fc1e478697d3, checked in by Hegyi Péter, 18 years ago

Currently visualized map can be saved and loaded from file.

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