COIN-OR::LEMON - Graph Library

source: glemon-0.x/graph_displayer_canvas.cc @ 166:302d75b08b27

Last change on this file since 166:302d75b08b27 was 166:302d75b08b27, checked in by Hegyi Péter, 15 years ago

Graph redesign starts with an initial kick of the first node.

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