COIN-OR::LEMON - Graph Library

source: glemon-0.x/graph_displayer_canvas.cc @ 168:a5f82cbbc1e4

Last change on this file since 168:a5f82cbbc1e4 was 168:a5f82cbbc1e4, checked in by Alpar Juttner, 18 years ago

Fix usage of Random. (Random's doc should possibly be improved.)

  • Property exe set to *
File size: 9.2 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), 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  //dummy=dummy;
67
68  std::string mapname=mytab.getActiveNodeMap(prop);
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  //dummy=dummy;
114
115  std::string mapname=mytab.getActiveEdgeMap(prop);
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
156void GraphDisplayerCanvas::drawGraph()
157{
158  //first edges are drawn, to hide joining with nodes later
159
160  for (EdgeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
161  {
162    if (mytab.mapstorage.graph.source(i) == mytab.mapstorage.graph.target(i))
163    {
164      edgesmap[i]=new LoopEdge(displayed_graph, i, *this);
165    }
166    else
167    {
168      edgesmap[i]=new BrokenEdge(displayed_graph, i, *this);
169    }
170    //initializing edge-text as well, to empty string
171
172    XY text_pos=mytab.mapstorage.arrow_pos[i];
173    text_pos+=(XY(10,10));
174
175    edgetextmap[i]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
176    edgetextmap[i]->property_fill_color().set_value("darkgreen");
177    edgetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false);
178    edgetextmap[i]->raise_to_top();
179  }
180
181  //afterwards nodes come to be drawn
182
183  for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
184  {
185    //drawing bule nodes, with black line around them
186
187    nodesmap[i]=new Gnome::Canvas::Ellipse(
188        displayed_graph,
189        (mytab.mapstorage).coords[i].x-20,
190        (mytab.mapstorage).coords[i].y-20,
191        (mytab.mapstorage).coords[i].x+20,
192        (mytab.mapstorage).coords[i].y+20);
193    *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue");
194    *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black");
195    nodesmap[i]->raise_to_top();
196
197    //initializing edge-text as well, to empty string
198
199    XY text_pos(
200        ((mytab.mapstorage).coords[i].x+node_property_defaults[N_RADIUS]+5),
201        ((mytab.mapstorage).coords[i].y+node_property_defaults[N_RADIUS]+5));
202
203    nodetextmap[i]=new Gnome::Canvas::Text(displayed_graph,
204        text_pos.x, text_pos.y, "");
205    nodetextmap[i]->property_fill_color().set_value("darkblue");
206    nodetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false);
207    nodetextmap[i]->raise_to_top();
208  }
209
210  updateScrollRegion();
211}
212
213void GraphDisplayerCanvas::clear()
214{
215  active_node=INVALID;
216  active_edge=INVALID;
217  forming_edge=INVALID;
218
219  for (NodeIt n((mytab.mapstorage).graph); n != INVALID; ++n)
220  {
221    delete nodesmap[n];
222    delete nodetextmap[n];
223  }
224
225  for (EdgeIt e((mytab.mapstorage).graph); e != INVALID; ++e)
226  {
227    delete edgesmap[e];
228    delete edgetextmap[e];
229  }
230}
231
232void GraphDisplayerCanvas::setView(bool autoscale_p, bool zoomtrack_p, double width_p, double radius_p)
233{
234  autoscale=autoscale_p;
235  edge_width=width_p;
236  radius_size=radius_p;
237
238  if((!zoomtrack) && zoomtrack_p)
239    {
240      fixed_zoom_factor=get_pixels_per_unit();
241    }
242
243  zoomtrack=zoomtrack_p;
244
245  propertyChange(false, N_RADIUS);
246  propertyChange(true, E_WIDTH);
247}
248
249void GraphDisplayerCanvas::getView(bool & autoscale_p, bool & zoomtrack_p, double& width_p, double& radius_p)
250{
251  autoscale_p=autoscale;
252  zoomtrack_p=zoomtrack;
253  width_p=edge_width;
254  radius_p=radius_size;
255}
256
257void GraphDisplayerCanvas::reDesignGraph()
258{
259  double min_dist=20;
260  double init_vector_length=25;
261
262  if(!was_redesigned)
263    {
264      NodeIt i((mytab.mapstorage).graph);
265
266      dim2::Point<double> init(init_vector_length*rnd(),
267                               init_vector_length*rnd());
268      moveNode(init.x, init.y, nodesmap[i], i);
269      was_redesigned=true;
270    }
271 
272
273  //iteration counter
274  for(int l=0;l<iterations;l++)
275    {
276      Graph::NodeMap<double> x(mytab.mapstorage.graph);
277      Graph::NodeMap<double> y(mytab.mapstorage.graph);
278      XYMap<Graph::NodeMap<double> > actual_forces;
279      actual_forces.setXMap(x);
280      actual_forces.setYMap(y);
281
282      lemon::dim2::Point<double> delta;
283
284      //count actual force for each nodes
285      for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
286        {
287          //propulsation of nodes
288          for (NodeIt j((mytab.mapstorage).graph); j!=INVALID; ++j)
289            {
290              if(i!=j)
291                {
292                  delta=((mytab.mapstorage).coords[i]-(mytab.mapstorage).coords[j]);
293
294                  double length_sqr=delta.normSquare();
295                  double length=sqrt(length_sqr);
296                  if(length_sqr<min_dist)
297                    {
298                      length_sqr=min_dist;
299                    }
300
301                  //normalize vector
302                  delta/=length;
303
304                  //calculating propulsation strength
305                  //greater distance menas smaller propulsation strength
306                  delta*=propulsation/length_sqr;
307                   
308                  actual_forces.set(i,(actual_forces[i]+delta));
309                }
310            }
311          //attraction of nodes, to which actual node is bound
312          for(OutEdgeIt ei((mytab.mapstorage).graph,i);ei!=INVALID;++ei)
313            {
314              delta=((mytab.mapstorage).coords[i]-(mytab.mapstorage).coords[mytab.mapstorage.graph.target(ei)]);
315
316              double length_sqr=delta.normSquare();
317              double length=sqrt(length_sqr);
318              if(length_sqr<min_dist)
319                {
320                  length_sqr=min_dist;
321                }
322
323              //normalize vector
324              delta/=length;
325
326              //calculating attraction strength
327              //greater distance means greater strength
328              delta*=attraction*length;
329
330              actual_forces.set(i,actual_forces[i]-delta);
331            }
332          for(InEdgeIt ei((mytab.mapstorage).graph,i);ei!=INVALID;++ei)
333            {
334              delta=((mytab.mapstorage).coords[i]-(mytab.mapstorage).coords[mytab.mapstorage.graph.source(ei)]);
335
336              double length_sqr=delta.normSquare();
337              double length=sqrt(length_sqr);
338              if(length_sqr<min_dist)
339                {
340                  length_sqr=min_dist;
341                }
342
343              //normalize vector
344              delta/=length;
345
346              //calculating attraction strength
347              //greater distance means greater strength
348              delta*=attraction*length;
349
350              actual_forces.set(i,actual_forces[i]-delta);
351            }
352        }
353      for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
354        {
355          moveNode(actual_forces[i].x, actual_forces[i].y, nodesmap[i], i);
356        }
357    }
358}
359
360void GraphDisplayerCanvas::get_design_data(double & attraction_p, double & propulsation_p, int & iterations_p)
361{
362  attraction_p=attraction;
363  propulsation_p=propulsation;
364  iterations_p=iterations;
365}
366
367void GraphDisplayerCanvas::set_attraction(double attraction_p)
368{
369  attraction=attraction_p;
370}
371
372void GraphDisplayerCanvas::set_propulsation(double propulsation_p)
373{
374  propulsation=propulsation_p;
375}
376
377void GraphDisplayerCanvas::set_iteration(int iterations_p)
378{
379  iterations=iterations_p;
380}
381
Note: See TracBrowser for help on using the repository browser.