/* -*- C++ -*- * * This file is a part of LEMON, a generic C++ optimization library * * Copyright (C) 2003-2006 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ #include "graph_displayer_canvas.h" #include #include GraphDisplayerCanvas::GraphDisplayerCanvas(NoteBookTab & mainw) : nodesmap(mainw.mapstorage.graph), edgesmap(mainw.mapstorage.graph), edgetextmap(mainw.mapstorage.graph), nodetextmap(mainw.mapstorage.graph), displayed_graph(*(root()), 0, 0), isbutton(0), active_item(NULL), target_item(NULL), nodemap_to_edit(""), edgemap_to_edit(""), autoscale(true), zoomtrack(false), radius_size(20), edge_width(10), was_redesigned(false), is_drawn(false), mytab(mainw), background_set(false) { //base event handler is move tool actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::moveEventHandler), false); actual_tool=MOVE; active_node=INVALID; active_edge=INVALID; forming_edge=INVALID; setBackground(); } void GraphDisplayerCanvas::setBackground() { if (background_set) { delete background; } if (mytab.mapstorage.isBackgroundSet()) { background_set = true; refBackground = Gdk::Pixbuf::create_from_file( mytab.mapstorage.getBackgroundFilename()); background = new Gnome::Canvas::Pixbuf( *(root()), 0.0 - refBackground->get_width() / 2.0, 0.0 - refBackground->get_height() / 2.0, refBackground); background->lower_to_bottom(); } else { background_set = false; } } GraphDisplayerCanvas::~GraphDisplayerCanvas() { for (NodeIt n((mytab.mapstorage).graph); n != INVALID; ++n) { delete nodesmap[n]; delete nodetextmap[n]; } for (EdgeIt e((mytab.mapstorage).graph); e != INVALID; ++e) { delete edgesmap[e]; delete edgetextmap[e]; } } void GraphDisplayerCanvas::propertyChange(bool itisedge, int prop) { if(itisedge) { propertyUpdate(Edge(INVALID), prop); } else { propertyUpdate(Node(INVALID), prop); } } void GraphDisplayerCanvas::propertyUpdate(Edge edge) { for(int i=0;iproperty_fill_color().set_value("darkgreen"); edgetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false); edgetextmap[i]->raise_to_top(); } //afterwards nodes come to be drawn for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i) { //drawing bule nodes, with black line around them nodesmap[i]=new Gnome::Canvas::Ellipse( displayed_graph, (mytab.mapstorage).coords[i].x-20, (mytab.mapstorage).coords[i].y-20, (mytab.mapstorage).coords[i].x+20, (mytab.mapstorage).coords[i].y+20); *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue"); *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black"); nodesmap[i]->raise_to_top(); //initializing edge-text as well, to empty string XY text_pos( ((mytab.mapstorage).coords[i].x+node_property_defaults[N_RADIUS]+5), ((mytab.mapstorage).coords[i].y+node_property_defaults[N_RADIUS]+5)); nodetextmap[i]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, ""); nodetextmap[i]->property_fill_color().set_value("darkblue"); nodetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false); nodetextmap[i]->raise_to_top(); } is_drawn=true; //upon drawing graph //properties have to //be set in as well for(int i=0;i init(init_vector_length*rnd(), init_vector_length*rnd()); moveNode(init.x, init.y, nodesmap[i], i); was_redesigned=true; } double attraction; double propulsation; int iterations; (mytab.mapstorage).get_design_data(attraction, propulsation, iterations); //iteration counter for(int l=0;l x(mytab.mapstorage.graph); Graph::NodeMap y(mytab.mapstorage.graph); XYMap > actual_forces; actual_forces.setXMap(x); actual_forces.setYMap(y); //count actual force for each nodes for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i) { //propulsation of nodes for (NodeIt j((mytab.mapstorage).graph); j!=INVALID; ++j) { if(i!=j) { lemon::dim2::Point delta = ((mytab.mapstorage).coords[i]- (mytab.mapstorage).coords[j]); const double length_sqr=std::max(delta.normSquare(),min_dist); //normalize vector delta/=sqrt(length_sqr); //calculating propulsation strength //greater distance menas smaller propulsation strength delta*=propulsation/length_sqr; actual_forces.set(i,(actual_forces[i]+delta)); } } //attraction of nodes, to which actual node is bound for(OutEdgeIt ei((mytab.mapstorage).graph,i);ei!=INVALID;++ei) { lemon::dim2::Point delta = ((mytab.mapstorage).coords[i]- (mytab.mapstorage).coords[mytab.mapstorage. graph.target(ei)]); //calculating attraction strength //greater distance means greater strength delta*=attraction; actual_forces.set(i,actual_forces[i]-delta); } for(InEdgeIt ei((mytab.mapstorage).graph,i);ei!=INVALID;++ei) { lemon::dim2::Point delta = ((mytab.mapstorage).coords[i]- (mytab.mapstorage).coords[mytab.mapstorage. graph.source(ei)]); //calculating attraction strength //greater distance means greater strength delta*=attraction; actual_forces.set(i,actual_forces[i]-delta); } } for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i) { moveNode(actual_forces[i].x, actual_forces[i].y, nodesmap[i], i); } } }