3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
19 #include <mapstorage.h>
21 #include <graph_displayer_canvas.h>
22 #include <lemon/random.h>
25 DigraphDisplayerCanvas::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),
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);
36 //base event handler is move tool
37 actual_handler=signal_event().connect(sigc::mem_fun(*this, &DigraphDisplayerCanvas::moveEventHandler), false);
48 void DigraphDisplayerCanvas::setBackground()
54 if (mytab.mapstorage->isBackgroundSet())
56 background_set = true;
57 refBackground = Gdk::Pixbuf::create_from_file(
58 mytab.mapstorage->getBackgroundFilename());
59 background = new Gnome::Canvas::Pixbuf(
61 0.0 - refBackground->get_width() / 2.0,
62 0.0 - refBackground->get_height() / 2.0,
64 background->lower_to_bottom();
68 background_set = false;
72 DigraphDisplayerCanvas::~DigraphDisplayerCanvas()
74 for (NodeIt n((mytab.mapstorage)->digraph); n != INVALID; ++n)
77 delete nodetextmap[n];
80 for (ArcIt e((mytab.mapstorage)->digraph); e != INVALID; ++e)
87 void DigraphDisplayerCanvas::propertyChange(bool itisarc, int prop)
91 propertyUpdate(Arc(INVALID), prop);
95 propertyUpdate(Node(INVALID), prop);
99 void DigraphDisplayerCanvas::propertyUpdate(Arc arc)
101 for(int i=0;i<EDGE_PROPERTY_NUM;i++)
103 propertyUpdate(arc, i);
107 void DigraphDisplayerCanvas::propertyUpdate(Node node)
109 for(int i=0;i<NODE_PROPERTY_NUM;i++)
111 propertyUpdate(node, i);
115 void DigraphDisplayerCanvas::propertyUpdate(Node node, int prop)
117 std::string mapname=mytab.getActiveNodeMap(prop);
123 std::vector<std::string> nodemaps = mytab.mapstorage->getNodeMapList();
125 for (std::vector<std::string>::const_iterator it = nodemaps.begin();
126 it != nodemaps.end(); ++it)
139 changeNodeRadius(mapname, node);
142 changeNodeColor(mapname, node);
145 changeNodeText(mapname, node);
148 std::cerr<<"Error\n";
158 resetNodeRadius(node);
161 resetNodeColor(node);
167 std::cerr<<"Error\n";
173 void DigraphDisplayerCanvas::propertyUpdate(Arc arc, int prop)
175 std::string mapname=mytab.getActiveArcMap(prop);
181 std::vector<std::string> arcmaps = mytab.mapstorage->getArcMapList();
183 for (std::vector<std::string>::const_iterator it = arcmaps.begin();
184 it != arcmaps.end(); ++it)
197 changeArcWidth(mapname, arc);
200 changeArcColor(mapname, arc);
203 changeArcText(mapname, arc);
206 std::cerr<<"Error\n";
224 std::cerr<<"Error\n";
230 void DigraphDisplayerCanvas::drawDigraph()
232 //first arcs are drawn, to hide joining with nodes later
234 for (ArcIt i((mytab.mapstorage)->digraph); i!=INVALID; ++i)
236 if (mytab.mapstorage->digraph.source(i) == mytab.mapstorage->digraph.target(i))
238 arcsmap[i]=new LoopArc(displayed_graph, i, *this);
242 arcsmap[i]=new BrokenArc(displayed_graph, i, *this);
244 //initializing arc-text as well, to empty string
246 XY text_pos=mytab.mapstorage->getArrowCoords(i);
247 text_pos+=(XY(10,10));
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();
255 //afterwards nodes come to be drawn
257 for (NodeIt i((mytab.mapstorage)->digraph); i!=INVALID; ++i)
259 //drawing bule nodes, with black line around them
261 nodesmap[i]=new Gnome::Canvas::Ellipse(
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();
271 //initializing arc-text as well, to empty string
274 (mytab.mapstorage->getNodeCoords(i).x+node_property_defaults[N_RADIUS]+5),
275 (mytab.mapstorage->getNodeCoords(i).y+node_property_defaults[N_RADIUS]+5));
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();
286 //upon drawing digraph
289 for(int i=0;i<NODE_PROPERTY_NUM;i++)
291 propertyUpdate(Node(INVALID), i);
294 for(int i=0;i<EDGE_PROPERTY_NUM;i++)
296 propertyUpdate(Arc(INVALID), i);
299 updateScrollRegion();
302 void DigraphDisplayerCanvas::clear()
308 for (NodeIt n((mytab.mapstorage)->digraph); n != INVALID; ++n)
311 delete nodetextmap[n];
314 for (ArcIt e((mytab.mapstorage)->digraph); e != INVALID; ++e)
317 delete arctextmap[e];
323 void DigraphDisplayerCanvas::setView(bool autoscale_p, bool zoomtrack_p, double width_p, double radius_p)
325 autoscale=autoscale_p;
327 radius_size=radius_p;
329 if((!zoomtrack) && zoomtrack_p)
331 fixed_zoom_factor=get_pixels_per_unit();
334 zoomtrack=zoomtrack_p;
336 propertyChange(false, N_RADIUS);
337 propertyChange(true, E_WIDTH);
340 void DigraphDisplayerCanvas::getView(bool & autoscale_p, bool & zoomtrack_p, double& width_p, double& radius_p)
342 autoscale_p=autoscale;
343 zoomtrack_p=zoomtrack;
345 radius_p=radius_size;
348 void DigraphDisplayerCanvas::reDesignDigraph()
350 MapStorage& ms = *mytab.mapstorage;
351 NodeIt firstnode(ms.digraph);
352 //is it not an empty digraph?
353 if(firstnode!=INVALID)
355 double max_coord=50000;
357 double init_vector_length=25;
361 NodeIt i(ms.digraph);
363 dim2::Point<double> init(init_vector_length*rnd(),
364 init_vector_length*rnd());
365 moveNode(init.x, init.y, nodesmap[i], i);
373 ms.get_design_data(attraction, propulsation, iterations);
376 for(int l=0;l<iterations;l++)
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);
384 //count actual force for each nodes
385 for (NodeIt i(ms.digraph); i!=INVALID; ++i)
387 //propulsation of nodes
388 for (NodeIt j(ms.digraph); j!=INVALID; ++j)
392 lemon::dim2::Point<double> delta =
393 (ms.getNodeCoords(i)-
394 ms.getNodeCoords(j));
396 const double length_sqr=std::max(delta.normSquare(),min_dist);
399 delta/=sqrt(length_sqr);
401 //calculating propulsation strength
402 //greater distance menas smaller propulsation strength
403 delta*=propulsation/length_sqr;
405 actual_forces.set(i,(actual_forces[i]+delta));
408 //attraction of nodes, to which actual node is bound
409 for(OutArcIt ei(ms.digraph,i);ei!=INVALID;++ei)
411 lemon::dim2::Point<double> delta =
412 (ms.getNodeCoords(i)-
413 ms.getNodeCoords(ms.digraph.target(ei)));
415 //calculating attraction strength
416 //greater distance means greater strength
419 actual_forces.set(i,actual_forces[i]-delta);
421 for(InArcIt ei(ms.digraph,i);ei!=INVALID;++ei)
423 lemon::dim2::Point<double> delta =
424 (ms.getNodeCoords(i)-
425 ms.getNodeCoords(ms.digraph.source(ei)));
427 //calculating attraction strength
428 //greater distance means greater strength
431 actual_forces.set(i,actual_forces[i]-delta);
434 for (NodeIt i(ms.digraph); i!=INVALID; ++i)
436 if((ms.getNodeCoords(i).x)+actual_forces[i].x>max_coord)
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;
441 else if((ms.getNodeCoords(i).x)+actual_forces[i].x<(0-max_coord))
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;
446 if((ms.getNodeCoords(i).y)+actual_forces[i].y>max_coord)
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;
451 else if((ms.getNodeCoords(i).y)+actual_forces[i].y<(0-max_coord))
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;
456 moveNode(actual_forces[i].x, actual_forces[i].y, nodesmap[i], i);