14 * express or implied, and with no claim as to its suitability for any |
14 * express or implied, and with no claim as to its suitability for any |
15 * purpose. |
15 * purpose. |
16 * |
16 * |
17 */ |
17 */ |
18 |
18 |
19 #include "graph_displayer_canvas.h" |
19 #include <mapstorage.h> |
|
20 #include <nbtab.h> |
|
21 #include <graph_displayer_canvas.h> |
20 #include <lemon/random.h> |
22 #include <lemon/random.h> |
21 #include <cmath> |
23 #include <cmath> |
22 |
24 |
23 GraphDisplayerCanvas::GraphDisplayerCanvas(NoteBookTab & mainw) : |
25 GraphDisplayerCanvas::GraphDisplayerCanvas(NoteBookTab & mainw) : |
24 nodesmap(mainw.mapstorage.graph), edgesmap(mainw.mapstorage.graph), edgetextmap(mainw.mapstorage.graph), |
26 nodesmap(mainw.mapstorage->graph), edgesmap(mainw.mapstorage->graph), edgetextmap(mainw.mapstorage->graph), |
25 nodetextmap(mainw.mapstorage.graph), displayed_graph(*(root()), 0, 0), |
27 nodetextmap(mainw.mapstorage->graph), displayed_graph(*(root()), 0, 0), |
26 isbutton(0), active_item(NULL), target_item(NULL), nodemap_to_edit(""), |
28 isbutton(0), active_item(NULL), target_item(NULL), nodemap_to_edit(""), |
27 edgemap_to_edit(""), autoscale(true), zoomtrack(false), radius_size(20), edge_width(10), |
29 edgemap_to_edit(""), autoscale(true), zoomtrack(false), radius_size(20), edge_width(10), |
28 was_redesigned(false), is_drawn(false), mytab(mainw), |
30 was_redesigned(false), is_drawn(false), mytab(mainw), |
29 background_set(false) |
31 background_set(false) |
30 { |
32 { |
205 |
207 |
206 void GraphDisplayerCanvas::drawGraph() |
208 void GraphDisplayerCanvas::drawGraph() |
207 { |
209 { |
208 //first edges are drawn, to hide joining with nodes later |
210 //first edges are drawn, to hide joining with nodes later |
209 |
211 |
210 for (EdgeIt i((mytab.mapstorage).graph); i!=INVALID; ++i) |
212 for (EdgeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i) |
211 { |
213 { |
212 if (mytab.mapstorage.graph.source(i) == mytab.mapstorage.graph.target(i)) |
214 if (mytab.mapstorage->graph.source(i) == mytab.mapstorage->graph.target(i)) |
213 { |
215 { |
214 edgesmap[i]=new LoopEdge(displayed_graph, i, *this); |
216 edgesmap[i]=new LoopEdge(displayed_graph, i, *this); |
215 } |
217 } |
216 else |
218 else |
217 { |
219 { |
218 edgesmap[i]=new BrokenEdge(displayed_graph, i, *this); |
220 edgesmap[i]=new BrokenEdge(displayed_graph, i, *this); |
219 } |
221 } |
220 //initializing edge-text as well, to empty string |
222 //initializing edge-text as well, to empty string |
221 |
223 |
222 XY text_pos=mytab.mapstorage.arrow_pos[i]; |
224 XY text_pos=mytab.mapstorage->arrow_pos[i]; |
223 text_pos+=(XY(10,10)); |
225 text_pos+=(XY(10,10)); |
224 |
226 |
225 edgetextmap[i]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, ""); |
227 edgetextmap[i]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, ""); |
226 edgetextmap[i]->property_fill_color().set_value("darkgreen"); |
228 edgetextmap[i]->property_fill_color().set_value("darkgreen"); |
227 edgetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false); |
229 edgetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false); |
228 edgetextmap[i]->raise_to_top(); |
230 edgetextmap[i]->raise_to_top(); |
229 } |
231 } |
230 |
232 |
231 //afterwards nodes come to be drawn |
233 //afterwards nodes come to be drawn |
232 |
234 |
233 for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i) |
235 for (NodeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i) |
234 { |
236 { |
235 //drawing bule nodes, with black line around them |
237 //drawing bule nodes, with black line around them |
236 |
238 |
237 nodesmap[i]=new Gnome::Canvas::Ellipse( |
239 nodesmap[i]=new Gnome::Canvas::Ellipse( |
238 displayed_graph, |
240 displayed_graph, |
239 (mytab.mapstorage).coords[i].x-20, |
241 (mytab.mapstorage)->coords[i].x-20, |
240 (mytab.mapstorage).coords[i].y-20, |
242 (mytab.mapstorage)->coords[i].y-20, |
241 (mytab.mapstorage).coords[i].x+20, |
243 (mytab.mapstorage)->coords[i].x+20, |
242 (mytab.mapstorage).coords[i].y+20); |
244 (mytab.mapstorage)->coords[i].y+20); |
243 *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue"); |
245 *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue"); |
244 *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black"); |
246 *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black"); |
245 nodesmap[i]->raise_to_top(); |
247 nodesmap[i]->raise_to_top(); |
246 |
248 |
247 //initializing edge-text as well, to empty string |
249 //initializing edge-text as well, to empty string |
248 |
250 |
249 XY text_pos( |
251 XY text_pos( |
250 ((mytab.mapstorage).coords[i].x+node_property_defaults[N_RADIUS]+5), |
252 ((mytab.mapstorage)->coords[i].x+node_property_defaults[N_RADIUS]+5), |
251 ((mytab.mapstorage).coords[i].y+node_property_defaults[N_RADIUS]+5)); |
253 ((mytab.mapstorage)->coords[i].y+node_property_defaults[N_RADIUS]+5)); |
252 |
254 |
253 nodetextmap[i]=new Gnome::Canvas::Text(displayed_graph, |
255 nodetextmap[i]=new Gnome::Canvas::Text(displayed_graph, |
254 text_pos.x, text_pos.y, ""); |
256 text_pos.x, text_pos.y, ""); |
255 nodetextmap[i]->property_fill_color().set_value("darkblue"); |
257 nodetextmap[i]->property_fill_color().set_value("darkblue"); |
256 nodetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false); |
258 nodetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false); |
321 radius_p=radius_size; |
323 radius_p=radius_size; |
322 } |
324 } |
323 |
325 |
324 void GraphDisplayerCanvas::reDesignGraph() |
326 void GraphDisplayerCanvas::reDesignGraph() |
325 { |
327 { |
326 NodeIt firstnode((mytab.mapstorage).graph); |
328 NodeIt firstnode((mytab.mapstorage)->graph); |
327 //is it not an empty graph? |
329 //is it not an empty graph? |
328 if(firstnode!=INVALID) |
330 if(firstnode!=INVALID) |
329 { |
331 { |
330 double max_coord=50000; |
332 double max_coord=50000; |
331 double min_dist=20; |
333 double min_dist=20; |
332 double init_vector_length=25; |
334 double init_vector_length=25; |
333 |
335 |
334 if(!was_redesigned) |
336 if(!was_redesigned) |
335 { |
337 { |
336 NodeIt i((mytab.mapstorage).graph); |
338 NodeIt i((mytab.mapstorage)->graph); |
337 |
339 |
338 dim2::Point<double> init(init_vector_length*rnd(), |
340 dim2::Point<double> init(init_vector_length*rnd(), |
339 init_vector_length*rnd()); |
341 init_vector_length*rnd()); |
340 moveNode(init.x, init.y, nodesmap[i], i); |
342 moveNode(init.x, init.y, nodesmap[i], i); |
341 was_redesigned=true; |
343 was_redesigned=true; |
343 |
345 |
344 double attraction; |
346 double attraction; |
345 double propulsation; |
347 double propulsation; |
346 int iterations; |
348 int iterations; |
347 |
349 |
348 (mytab.mapstorage).get_design_data(attraction, propulsation, iterations); |
350 (mytab.mapstorage)->get_design_data(attraction, propulsation, iterations); |
349 |
351 |
350 //iteration counter |
352 //iteration counter |
351 for(int l=0;l<iterations;l++) |
353 for(int l=0;l<iterations;l++) |
352 { |
354 { |
353 Graph::NodeMap<double> x(mytab.mapstorage.graph); |
355 Graph::NodeMap<double> x(mytab.mapstorage->graph); |
354 Graph::NodeMap<double> y(mytab.mapstorage.graph); |
356 Graph::NodeMap<double> y(mytab.mapstorage->graph); |
355 XYMap<Graph::NodeMap<double> > actual_forces; |
357 XYMap<Graph::NodeMap<double> > actual_forces; |
356 actual_forces.setXMap(x); |
358 actual_forces.setXMap(x); |
357 actual_forces.setYMap(y); |
359 actual_forces.setYMap(y); |
358 |
360 |
359 //count actual force for each nodes |
361 //count actual force for each nodes |
360 for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i) |
362 for (NodeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i) |
361 { |
363 { |
362 //propulsation of nodes |
364 //propulsation of nodes |
363 for (NodeIt j((mytab.mapstorage).graph); j!=INVALID; ++j) |
365 for (NodeIt j((mytab.mapstorage)->graph); j!=INVALID; ++j) |
364 { |
366 { |
365 if(i!=j) |
367 if(i!=j) |
366 { |
368 { |
367 lemon::dim2::Point<double> delta = |
369 lemon::dim2::Point<double> delta = |
368 ((mytab.mapstorage).coords[i]- |
370 ((mytab.mapstorage)->coords[i]- |
369 (mytab.mapstorage).coords[j]); |
371 (mytab.mapstorage)->coords[j]); |
370 |
372 |
371 const double length_sqr=std::max(delta.normSquare(),min_dist); |
373 const double length_sqr=std::max(delta.normSquare(),min_dist); |
372 |
374 |
373 //normalize vector |
375 //normalize vector |
374 delta/=sqrt(length_sqr); |
376 delta/=sqrt(length_sqr); |
379 |
381 |
380 actual_forces.set(i,(actual_forces[i]+delta)); |
382 actual_forces.set(i,(actual_forces[i]+delta)); |
381 } |
383 } |
382 } |
384 } |
383 //attraction of nodes, to which actual node is bound |
385 //attraction of nodes, to which actual node is bound |
384 for(OutEdgeIt ei((mytab.mapstorage).graph,i);ei!=INVALID;++ei) |
386 for(OutEdgeIt ei((mytab.mapstorage)->graph,i);ei!=INVALID;++ei) |
385 { |
387 { |
386 lemon::dim2::Point<double> delta = |
388 lemon::dim2::Point<double> delta = |
387 ((mytab.mapstorage).coords[i]- |
389 ((mytab.mapstorage)->coords[i]- |
388 (mytab.mapstorage).coords[mytab.mapstorage. |
390 (mytab.mapstorage)->coords[mytab.mapstorage-> |
389 graph.target(ei)]); |
391 graph.target(ei)]); |
390 |
392 |
391 //calculating attraction strength |
393 //calculating attraction strength |
392 //greater distance means greater strength |
394 //greater distance means greater strength |
393 delta*=attraction; |
395 delta*=attraction; |
394 |
396 |
395 actual_forces.set(i,actual_forces[i]-delta); |
397 actual_forces.set(i,actual_forces[i]-delta); |
396 } |
398 } |
397 for(InEdgeIt ei((mytab.mapstorage).graph,i);ei!=INVALID;++ei) |
399 for(InEdgeIt ei((mytab.mapstorage)->graph,i);ei!=INVALID;++ei) |
398 { |
400 { |
399 lemon::dim2::Point<double> delta = |
401 lemon::dim2::Point<double> delta = |
400 ((mytab.mapstorage).coords[i]- |
402 ((mytab.mapstorage)->coords[i]- |
401 (mytab.mapstorage).coords[mytab.mapstorage. |
403 (mytab.mapstorage)->coords[mytab.mapstorage-> |
402 graph.source(ei)]); |
404 graph.source(ei)]); |
403 |
405 |
404 //calculating attraction strength |
406 //calculating attraction strength |
405 //greater distance means greater strength |
407 //greater distance means greater strength |
406 delta*=attraction; |
408 delta*=attraction; |
407 |
409 |
408 actual_forces.set(i,actual_forces[i]-delta); |
410 actual_forces.set(i,actual_forces[i]-delta); |
409 } |
411 } |
410 } |
412 } |
411 for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i) |
413 for (NodeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i) |
412 { |
414 { |
413 if(((mytab.mapstorage).coords[i].x)+actual_forces[i].x>max_coord) |
415 if(((mytab.mapstorage)->coords[i].x)+actual_forces[i].x>max_coord) |
414 { |
416 { |
415 actual_forces[i].x=max_coord-((mytab.mapstorage).coords[i].x); |
417 actual_forces[i].x=max_coord-((mytab.mapstorage)->coords[i].x); |
416 std::cout << "Correction! " << (((mytab.mapstorage).coords[i].x)+actual_forces[i].x) << std::endl; |
418 std::cout << "Correction! " << (((mytab.mapstorage)->coords[i].x)+actual_forces[i].x) << std::endl; |
417 } |
419 } |
418 else if(((mytab.mapstorage).coords[i].x)+actual_forces[i].x<(0-max_coord)) |
420 else if(((mytab.mapstorage)->coords[i].x)+actual_forces[i].x<(0-max_coord)) |
419 { |
421 { |
420 actual_forces[i].x=0-max_coord-((mytab.mapstorage).coords[i].x); |
422 actual_forces[i].x=0-max_coord-((mytab.mapstorage)->coords[i].x); |
421 std::cout << "Correction! " << (((mytab.mapstorage).coords[i].x)+actual_forces[i].x) << std::endl; |
423 std::cout << "Correction! " << (((mytab.mapstorage)->coords[i].x)+actual_forces[i].x) << std::endl; |
422 } |
424 } |
423 if(((mytab.mapstorage).coords[i].y)+actual_forces[i].y>max_coord) |
425 if(((mytab.mapstorage)->coords[i].y)+actual_forces[i].y>max_coord) |
424 { |
426 { |
425 actual_forces[i].y=max_coord-((mytab.mapstorage).coords[i].y); |
427 actual_forces[i].y=max_coord-((mytab.mapstorage)->coords[i].y); |
426 std::cout << "Correction! " << (((mytab.mapstorage).coords[i].y)+actual_forces[i].y) << std::endl; |
428 std::cout << "Correction! " << (((mytab.mapstorage)->coords[i].y)+actual_forces[i].y) << std::endl; |
427 } |
429 } |
428 else if(((mytab.mapstorage).coords[i].y)+actual_forces[i].y<(0-max_coord)) |
430 else if(((mytab.mapstorage)->coords[i].y)+actual_forces[i].y<(0-max_coord)) |
429 { |
431 { |
430 actual_forces[i].y=0-max_coord-((mytab.mapstorage).coords[i].y); |
432 actual_forces[i].y=0-max_coord-((mytab.mapstorage)->coords[i].y); |
431 std::cout << "Correction! " << (((mytab.mapstorage).coords[i].y)+actual_forces[i].y) << std::endl; |
433 std::cout << "Correction! " << (((mytab.mapstorage)->coords[i].y)+actual_forces[i].y) << std::endl; |
432 } |
434 } |
433 moveNode(actual_forces[i].x, actual_forces[i].y, nodesmap[i], i); |
435 moveNode(actual_forces[i].x, actual_forces[i].y, nodesmap[i], i); |
434 } |
436 } |
435 } |
437 } |
436 } |
438 } |