1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/graph_displayer_canvas.cc Mon Jul 07 08:10:39 2008 -0500
1.3 @@ -0,0 +1,461 @@
1.4 +/* -*- C++ -*-
1.5 + *
1.6 + * This file is a part of LEMON, a generic C++ optimization library
1.7 + *
1.8 + * Copyright (C) 2003-2006
1.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
1.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
1.11 + *
1.12 + * Permission to use, modify and distribute this software is granted
1.13 + * provided that this copyright notice appears in all copies. For
1.14 + * precise terms see the accompanying LICENSE file.
1.15 + *
1.16 + * This software is provided "AS IS" with no warranty of any kind,
1.17 + * express or implied, and with no claim as to its suitability for any
1.18 + * purpose.
1.19 + *
1.20 + */
1.21 +
1.22 +#include <mapstorage.h>
1.23 +#include <nbtab.h>
1.24 +#include <graph_displayer_canvas.h>
1.25 +#include <lemon/random.h>
1.26 +#include <cmath>
1.27 +
1.28 +DigraphDisplayerCanvas::DigraphDisplayerCanvas(NoteBookTab & mainw) :
1.29 + nodesmap(mainw.mapstorage->digraph), arcsmap(mainw.mapstorage->digraph), arctextmap(mainw.mapstorage->digraph),
1.30 + nodetextmap(mainw.mapstorage->digraph), displayed_graph(*(root()), 0, 0),
1.31 + isbutton(0), active_item(NULL), target_item(NULL), nodemap_to_edit(""),
1.32 + arcmap_to_edit(""), autoscale(true), zoomtrack(false), radius_size(20), arc_width(10),
1.33 + was_redesigned(false), is_drawn(false), mytab(mainw),
1.34 + background_set(false)
1.35 +{
1.36 + //add mouse scroll event handler - it won't be changed, it handles zoom
1.37 + signal_event().connect(sigc::mem_fun(*this, &DigraphDisplayerCanvas::scrollEventHandler), false);
1.38 +
1.39 + //base event handler is move tool
1.40 + actual_handler=signal_event().connect(sigc::mem_fun(*this, &DigraphDisplayerCanvas::moveEventHandler), false);
1.41 + actual_tool=MOVE;
1.42 +
1.43 +
1.44 + active_node=INVALID;
1.45 + active_arc=INVALID;
1.46 + forming_arc=INVALID;
1.47 +
1.48 + setBackground();
1.49 +}
1.50 +
1.51 +void DigraphDisplayerCanvas::setBackground()
1.52 +{
1.53 + if (background_set)
1.54 + {
1.55 + delete background;
1.56 + }
1.57 + if (mytab.mapstorage->isBackgroundSet())
1.58 + {
1.59 + background_set = true;
1.60 + refBackground = Gdk::Pixbuf::create_from_file(
1.61 + mytab.mapstorage->getBackgroundFilename());
1.62 + background = new Gnome::Canvas::Pixbuf(
1.63 + *(root()),
1.64 + 0.0 - refBackground->get_width() / 2.0,
1.65 + 0.0 - refBackground->get_height() / 2.0,
1.66 + refBackground);
1.67 + background->lower_to_bottom();
1.68 + }
1.69 + else
1.70 + {
1.71 + background_set = false;
1.72 + }
1.73 +}
1.74 +
1.75 +DigraphDisplayerCanvas::~DigraphDisplayerCanvas()
1.76 +{
1.77 + for (NodeIt n((mytab.mapstorage)->digraph); n != INVALID; ++n)
1.78 + {
1.79 + delete nodesmap[n];
1.80 + delete nodetextmap[n];
1.81 + }
1.82 +
1.83 + for (ArcIt e((mytab.mapstorage)->digraph); e != INVALID; ++e)
1.84 + {
1.85 + delete arcsmap[e];
1.86 + delete arctextmap[e];
1.87 + }
1.88 +}
1.89 +
1.90 +void DigraphDisplayerCanvas::propertyChange(bool itisarc, int prop)
1.91 +{
1.92 + if(itisarc)
1.93 + {
1.94 + propertyUpdate(Arc(INVALID), prop);
1.95 + }
1.96 + else
1.97 + {
1.98 + propertyUpdate(Node(INVALID), prop);
1.99 + }
1.100 +}
1.101 +
1.102 +void DigraphDisplayerCanvas::propertyUpdate(Arc arc)
1.103 +{
1.104 + for(int i=0;i<EDGE_PROPERTY_NUM;i++)
1.105 + {
1.106 + propertyUpdate(arc, i);
1.107 + }
1.108 +}
1.109 +
1.110 +void DigraphDisplayerCanvas::propertyUpdate(Node node)
1.111 +{
1.112 + for(int i=0;i<NODE_PROPERTY_NUM;i++)
1.113 + {
1.114 + propertyUpdate(node, i);
1.115 + }
1.116 +}
1.117 +
1.118 +void DigraphDisplayerCanvas::propertyUpdate(Node node, int prop)
1.119 +{
1.120 + std::string mapname=mytab.getActiveNodeMap(prop);
1.121 +
1.122 + if(is_drawn)
1.123 + {
1.124 + if(mapname!="")
1.125 + {
1.126 + std::vector<std::string> nodemaps = mytab.mapstorage->getNodeMapList();
1.127 + bool found = false;
1.128 + for (std::vector<std::string>::const_iterator it = nodemaps.begin();
1.129 + it != nodemaps.end(); ++it)
1.130 + {
1.131 + if (*it == mapname)
1.132 + {
1.133 + found = true;
1.134 + break;
1.135 + }
1.136 + }
1.137 + if (found)
1.138 + {
1.139 + switch(prop)
1.140 + {
1.141 + case N_RADIUS:
1.142 + changeNodeRadius(mapname, node);
1.143 + break;
1.144 + case N_COLOR:
1.145 + changeNodeColor(mapname, node);
1.146 + break;
1.147 + case N_TEXT:
1.148 + changeNodeText(mapname, node);
1.149 + break;
1.150 + default:
1.151 + std::cerr<<"Error\n";
1.152 + }
1.153 + }
1.154 + }
1.155 + else //mapname==""
1.156 + {
1.157 + Node node=INVALID;
1.158 + switch(prop)
1.159 + {
1.160 + case N_RADIUS:
1.161 + resetNodeRadius(node);
1.162 + break;
1.163 + case N_COLOR:
1.164 + resetNodeColor(node);
1.165 + break;
1.166 + case N_TEXT:
1.167 + resetNodeText(node);
1.168 + break;
1.169 + default:
1.170 + std::cerr<<"Error\n";
1.171 + }
1.172 + }
1.173 + }
1.174 +}
1.175 +
1.176 +void DigraphDisplayerCanvas::propertyUpdate(Arc arc, int prop)
1.177 +{
1.178 + std::string mapname=mytab.getActiveArcMap(prop);
1.179 +
1.180 + if(is_drawn)
1.181 + {
1.182 + if(mapname!="")
1.183 + {
1.184 + std::vector<std::string> arcmaps = mytab.mapstorage->getArcMapList();
1.185 + bool found = false;
1.186 + for (std::vector<std::string>::const_iterator it = arcmaps.begin();
1.187 + it != arcmaps.end(); ++it)
1.188 + {
1.189 + if (*it == mapname)
1.190 + {
1.191 + found = true;
1.192 + break;
1.193 + }
1.194 + }
1.195 + if (found)
1.196 + {
1.197 + switch(prop)
1.198 + {
1.199 + case E_WIDTH:
1.200 + changeArcWidth(mapname, arc);
1.201 + break;
1.202 + case E_COLOR:
1.203 + changeArcColor(mapname, arc);
1.204 + break;
1.205 + case E_TEXT:
1.206 + changeArcText(mapname, arc);
1.207 + break;
1.208 + default:
1.209 + std::cerr<<"Error\n";
1.210 + }
1.211 + }
1.212 + }
1.213 + else //mapname==""
1.214 + {
1.215 + switch(prop)
1.216 + {
1.217 + case E_WIDTH:
1.218 + resetArcWidth(arc);
1.219 + break;
1.220 + case E_COLOR:
1.221 + resetArcColor(arc);
1.222 + break;
1.223 + case E_TEXT:
1.224 + resetArcText(arc);
1.225 + break;
1.226 + default:
1.227 + std::cerr<<"Error\n";
1.228 + }
1.229 + }
1.230 + }
1.231 +}
1.232 +
1.233 +void DigraphDisplayerCanvas::drawDigraph()
1.234 +{
1.235 + //first arcs are drawn, to hide joining with nodes later
1.236 +
1.237 + for (ArcIt i((mytab.mapstorage)->digraph); i!=INVALID; ++i)
1.238 + {
1.239 + if (mytab.mapstorage->digraph.source(i) == mytab.mapstorage->digraph.target(i))
1.240 + {
1.241 + arcsmap[i]=new LoopArc(displayed_graph, i, *this);
1.242 + }
1.243 + else
1.244 + {
1.245 + arcsmap[i]=new BrokenArc(displayed_graph, i, *this);
1.246 + }
1.247 + //initializing arc-text as well, to empty string
1.248 +
1.249 + XY text_pos=mytab.mapstorage->getArrowCoords(i);
1.250 + text_pos+=(XY(10,10));
1.251 +
1.252 + arctextmap[i]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
1.253 + arctextmap[i]->property_fill_color().set_value("darkgreen");
1.254 + arctextmap[i]->signal_event().connect(sigc::mem_fun(*this, &DigraphDisplayerCanvas::mapEditEventHandler), false);
1.255 + arctextmap[i]->raise_to_top();
1.256 + }
1.257 +
1.258 + //afterwards nodes come to be drawn
1.259 +
1.260 + for (NodeIt i((mytab.mapstorage)->digraph); i!=INVALID; ++i)
1.261 + {
1.262 + //drawing bule nodes, with black line around them
1.263 +
1.264 + nodesmap[i]=new Gnome::Canvas::Ellipse(
1.265 + displayed_graph,
1.266 + mytab.mapstorage->getNodeCoords(i).x-20,
1.267 + mytab.mapstorage->getNodeCoords(i).y-20,
1.268 + mytab.mapstorage->getNodeCoords(i).x+20,
1.269 + mytab.mapstorage->getNodeCoords(i).y+20);
1.270 + *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue");
1.271 + *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black");
1.272 + nodesmap[i]->raise_to_top();
1.273 +
1.274 + //initializing arc-text as well, to empty string
1.275 +
1.276 + XY text_pos(
1.277 + (mytab.mapstorage->getNodeCoords(i).x+node_property_defaults[N_RADIUS]+5),
1.278 + (mytab.mapstorage->getNodeCoords(i).y+node_property_defaults[N_RADIUS]+5));
1.279 +
1.280 + nodetextmap[i]=new Gnome::Canvas::Text(displayed_graph,
1.281 + text_pos.x, text_pos.y, "");
1.282 + nodetextmap[i]->property_fill_color().set_value("darkblue");
1.283 + nodetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &DigraphDisplayerCanvas::mapEditEventHandler), false);
1.284 + nodetextmap[i]->raise_to_top();
1.285 + }
1.286 +
1.287 + is_drawn=true;
1.288 +
1.289 + //upon drawing digraph
1.290 + //properties have to
1.291 + //be set in as well
1.292 + for(int i=0;i<NODE_PROPERTY_NUM;i++)
1.293 + {
1.294 + propertyUpdate(Node(INVALID), i);
1.295 + }
1.296 +
1.297 + for(int i=0;i<EDGE_PROPERTY_NUM;i++)
1.298 + {
1.299 + propertyUpdate(Arc(INVALID), i);
1.300 + }
1.301 +
1.302 + updateScrollRegion();
1.303 +}
1.304 +
1.305 +void DigraphDisplayerCanvas::clear()
1.306 +{
1.307 + active_node=INVALID;
1.308 + active_arc=INVALID;
1.309 + forming_arc=INVALID;
1.310 +
1.311 + for (NodeIt n((mytab.mapstorage)->digraph); n != INVALID; ++n)
1.312 + {
1.313 + delete nodesmap[n];
1.314 + delete nodetextmap[n];
1.315 + }
1.316 +
1.317 + for (ArcIt e((mytab.mapstorage)->digraph); e != INVALID; ++e)
1.318 + {
1.319 + delete arcsmap[e];
1.320 + delete arctextmap[e];
1.321 + }
1.322 +
1.323 + is_drawn=false;
1.324 +}
1.325 +
1.326 +void DigraphDisplayerCanvas::setView(bool autoscale_p, bool zoomtrack_p, double width_p, double radius_p)
1.327 +{
1.328 + autoscale=autoscale_p;
1.329 + arc_width=width_p;
1.330 + radius_size=radius_p;
1.331 +
1.332 + if((!zoomtrack) && zoomtrack_p)
1.333 + {
1.334 + fixed_zoom_factor=get_pixels_per_unit();
1.335 + }
1.336 +
1.337 + zoomtrack=zoomtrack_p;
1.338 +
1.339 + propertyChange(false, N_RADIUS);
1.340 + propertyChange(true, E_WIDTH);
1.341 +}
1.342 +
1.343 +void DigraphDisplayerCanvas::getView(bool & autoscale_p, bool & zoomtrack_p, double& width_p, double& radius_p)
1.344 +{
1.345 + autoscale_p=autoscale;
1.346 + zoomtrack_p=zoomtrack;
1.347 + width_p=arc_width;
1.348 + radius_p=radius_size;
1.349 +}
1.350 +
1.351 +void DigraphDisplayerCanvas::reDesignDigraph()
1.352 +{
1.353 + MapStorage& ms = *mytab.mapstorage;
1.354 + NodeIt firstnode(ms.digraph);
1.355 + //is it not an empty digraph?
1.356 + if(firstnode!=INVALID)
1.357 + {
1.358 + double max_coord=50000;
1.359 + double min_dist=20;
1.360 + double init_vector_length=25;
1.361 +
1.362 + if(!was_redesigned)
1.363 + {
1.364 + NodeIt i(ms.digraph);
1.365 +
1.366 + dim2::Point<double> init(init_vector_length*rnd(),
1.367 + init_vector_length*rnd());
1.368 + moveNode(init.x, init.y, nodesmap[i], i);
1.369 + was_redesigned=true;
1.370 + }
1.371 +
1.372 + double attraction;
1.373 + double propulsation;
1.374 + int iterations;
1.375 +
1.376 + ms.get_design_data(attraction, propulsation, iterations);
1.377 +
1.378 + //iteration counter
1.379 + for(int l=0;l<iterations;l++)
1.380 + {
1.381 + Digraph::NodeMap<double> x(ms.digraph);
1.382 + Digraph::NodeMap<double> y(ms.digraph);
1.383 + XYMap<Digraph::NodeMap<double> > actual_forces;
1.384 + actual_forces.setXMap(x);
1.385 + actual_forces.setYMap(y);
1.386 +
1.387 + //count actual force for each nodes
1.388 + for (NodeIt i(ms.digraph); i!=INVALID; ++i)
1.389 + {
1.390 + //propulsation of nodes
1.391 + for (NodeIt j(ms.digraph); j!=INVALID; ++j)
1.392 + {
1.393 + if(i!=j)
1.394 + {
1.395 + lemon::dim2::Point<double> delta =
1.396 + (ms.getNodeCoords(i)-
1.397 + ms.getNodeCoords(j));
1.398 +
1.399 + const double length_sqr=std::max(delta.normSquare(),min_dist);
1.400 +
1.401 + //normalize vector
1.402 + delta/=sqrt(length_sqr);
1.403 +
1.404 + //calculating propulsation strength
1.405 + //greater distance menas smaller propulsation strength
1.406 + delta*=propulsation/length_sqr;
1.407 +
1.408 + actual_forces.set(i,(actual_forces[i]+delta));
1.409 + }
1.410 + }
1.411 + //attraction of nodes, to which actual node is bound
1.412 + for(OutArcIt ei(ms.digraph,i);ei!=INVALID;++ei)
1.413 + {
1.414 + lemon::dim2::Point<double> delta =
1.415 + (ms.getNodeCoords(i)-
1.416 + ms.getNodeCoords(ms.digraph.target(ei)));
1.417 +
1.418 + //calculating attraction strength
1.419 + //greater distance means greater strength
1.420 + delta*=attraction;
1.421 +
1.422 + actual_forces.set(i,actual_forces[i]-delta);
1.423 + }
1.424 + for(InArcIt ei(ms.digraph,i);ei!=INVALID;++ei)
1.425 + {
1.426 + lemon::dim2::Point<double> delta =
1.427 + (ms.getNodeCoords(i)-
1.428 + ms.getNodeCoords(ms.digraph.source(ei)));
1.429 +
1.430 + //calculating attraction strength
1.431 + //greater distance means greater strength
1.432 + delta*=attraction;
1.433 +
1.434 + actual_forces.set(i,actual_forces[i]-delta);
1.435 + }
1.436 + }
1.437 + for (NodeIt i(ms.digraph); i!=INVALID; ++i)
1.438 + {
1.439 + if((ms.getNodeCoords(i).x)+actual_forces[i].x>max_coord)
1.440 + {
1.441 + actual_forces[i].x=max_coord-(ms.getNodeCoords(i).x);
1.442 + std::cout << "Correction! " << ((ms.getNodeCoords(i).x)+actual_forces[i].x) << std::endl;
1.443 + }
1.444 + else if((ms.getNodeCoords(i).x)+actual_forces[i].x<(0-max_coord))
1.445 + {
1.446 + actual_forces[i].x=0-max_coord-(ms.getNodeCoords(i).x);
1.447 + std::cout << "Correction! " << ((ms.getNodeCoords(i).x)+actual_forces[i].x) << std::endl;
1.448 + }
1.449 + if((ms.getNodeCoords(i).y)+actual_forces[i].y>max_coord)
1.450 + {
1.451 + actual_forces[i].y=max_coord-(ms.getNodeCoords(i).y);
1.452 + std::cout << "Correction! " << ((ms.getNodeCoords(i).y)+actual_forces[i].y) << std::endl;
1.453 + }
1.454 + else if((ms.getNodeCoords(i).y)+actual_forces[i].y<(0-max_coord))
1.455 + {
1.456 + actual_forces[i].y=0-max_coord-(ms.getNodeCoords(i).y);
1.457 + std::cout << "Correction! " << ((ms.getNodeCoords(i).y)+actual_forces[i].y) << std::endl;
1.458 + }
1.459 + moveNode(actual_forces[i].x, actual_forces[i].y, nodesmap[i], i);
1.460 + }
1.461 + }
1.462 + }
1.463 +}
1.464 +