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