COIN-OR::LEMON - Graph Library

source: glemon-0.x/gdc-broken_edge.cc @ 191:af2ed974ab68

Last change on this file since 191:af2ed974ab68 was 189:8b69c54d5bf0, checked in by Hegyi Péter, 17 years ago

No segmentation fault will be occured if two nodes are exactly overlap each other, AND they are connected.

File size: 7.3 KB
Line 
1/* -*- C++ -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library
4 *
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 *
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.
12 *
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
15 * purpose.
16 *
17 */
18
19#include "graph_displayer_canvas.h"
20#include <cmath>
21
22GraphDisplayerCanvas::EdgeBase::EdgeBase(Gnome::Canvas::Group& _group, Edge _edge, GraphDisplayerCanvas& _canvas) :
23  Gnome::Canvas::Group(_group), edge(_edge), canvas(_canvas), arrow(*this)
24{
25  arrow.property_fill_color().set_value("red");
26  arrow.lower_to_bottom();
27  lower_to_bottom();
28}
29
30GraphDisplayerCanvas::EdgeBase::~EdgeBase()
31{
32}
33
34void GraphDisplayerCanvas::EdgeBase::drawArrow(XY unit_vector_in_dir)
35{
36  MapStorage& ms = canvas.mytab.mapstorage;
37  XY center(ms.arrow_pos[edge]);
38  XY unit_norm_vector(0-unit_vector_in_dir.y, unit_vector_in_dir.x);
39
40  //       /\       // top
41  //      /  \      //
42  //      -  -      // c(enter)l(eft), ccl, ccr, cr
43  //       ||       //
44  //       ||       // b(ottom)l, br
45
46  double size=3;
47
48  XY bl (center - unit_vector_in_dir * 3 * size + unit_norm_vector * size );
49  XY br (center - unit_vector_in_dir * 3 * size - unit_norm_vector * size );
50  XY ccl(center + unit_vector_in_dir *  size + unit_norm_vector * size );
51  XY ccr(center + unit_vector_in_dir *  size - unit_norm_vector * size );
52  XY cl (center + unit_vector_in_dir *  size + unit_norm_vector * 2 * size );
53  XY cr (center + unit_vector_in_dir *  size - unit_norm_vector * 2 * size );
54  XY top(center + unit_vector_in_dir * 3 * size);
55
56  Gnome::Canvas::Points arrow_points;
57  arrow_points.push_back(Gnome::Art::Point( bl.x , bl.y  ) );
58  arrow_points.push_back(Gnome::Art::Point( br.x , br.y  ) );
59  arrow_points.push_back(Gnome::Art::Point( ccr.x, ccr.y ) );
60  arrow_points.push_back(Gnome::Art::Point( cr.x , cr.y  ) );
61  arrow_points.push_back(Gnome::Art::Point( top.x, top.y ) );
62  arrow_points.push_back(Gnome::Art::Point( cl.x , cl.y  ) );
63  arrow_points.push_back(Gnome::Art::Point( ccl.x, ccl.y ) );
64
65  arrow.property_points().set_value(arrow_points);
66}
67
68GraphDisplayerCanvas::BrokenEdge::BrokenEdge(Gnome::Canvas::Group & g,
69    Edge _edge, GraphDisplayerCanvas & gc) : EdgeBase(g, _edge, gc),
70  isbutton(false), line(*this)
71{
72  arrow.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::BrokenEdge::edgeFormerEventHandler));
73
74  line.property_fill_color().set_value("green");
75  line.property_width_units().set_value(10);   
76  line.lower_to_bottom();
77
78  draw();
79}
80
81GraphDisplayerCanvas::BrokenEdge::~BrokenEdge()
82{
83}
84
85void GraphDisplayerCanvas::BrokenEdge::draw()
86{
87  MapStorage& ms = canvas.mytab.mapstorage;
88
89  //calculating coordinates of the direction indicator arrow
90  XY head(ms.coords[ms.graph.target(edge)]);
91  XY center(ms.arrow_pos[edge]);
92
93  XY unit_vector_in_dir(head-center);
94  double length=sqrt( unit_vector_in_dir.normSquare() );
95
96  if(length!=0)
97    {
98      unit_vector_in_dir/=length;
99    }
100
101  // update the arrow
102  drawArrow(unit_vector_in_dir);
103
104  // update the edge
105  Gnome::Canvas::Points points;
106  Node source = ms.graph.source(edge);
107  Node target = ms.graph.target(edge);
108  points.push_back(Gnome::Art::Point(ms.coords[source].x,
109        ms.coords[source].y));
110  points.push_back(Gnome::Art::Point(ms.arrow_pos[edge].x,
111        ms.arrow_pos[edge].y));
112  points.push_back(Gnome::Art::Point(ms.coords[target].x,
113        ms.coords[target].y));
114  line.property_points().set_value(points);
115}
116
117bool GraphDisplayerCanvas::BrokenEdge::edgeFormerEventHandler(GdkEvent* e)
118{
119  switch(e->type)
120  {
121    case GDK_BUTTON_PRESS:
122      //we mark the location of the event to be able to calculate parameters
123      //of dragging
124      if(canvas.getActualTool()!=CREATE_NODE)
125      {
126        canvas.toggleEdgeActivity(this, true);
127        clicked_x=e->button.x;
128        clicked_y=e->button.y;
129        isbutton=true;
130      }
131      break;
132    case GDK_BUTTON_RELEASE:
133      if(canvas.getActualTool()!=CREATE_NODE)
134      {
135        canvas.toggleEdgeActivity(this, false);
136        isbutton=false;
137      }
138      break;
139    case GDK_MOTION_NOTIFY:
140      //we only have to do sg. if the mouse button is pressed
141      if(isbutton)
142      {
143        //new coordinates will be the old values,
144        //because the item will be moved to the
145        //new coordinate therefore the new movement
146        //has to be calculated from here
147
148        double dx=e->motion.x-clicked_x;
149        double dy=e->motion.y-clicked_y;
150
151        Gnome::Canvas::Points points_new;
152
153        canvas.mytab.mapstorage.arrow_pos.set(edge, canvas.mytab.mapstorage.arrow_pos[edge] + XY(dx, dy));
154
155        draw();
156        canvas.textReposition(canvas.mytab.mapstorage.arrow_pos[edge]);
157
158        clicked_x=e->motion.x;
159        clicked_y=e->motion.y;
160
161      }
162    default: break;
163  }
164
165  return true;
166}
167
168void GraphDisplayerCanvas::BrokenEdge::setLineWidth(int w)
169{
170  line.property_width_units().set_value(w);
171}
172
173void GraphDisplayerCanvas::BrokenEdge::setFillColor(Gdk::Color c)
174{
175  line.property_fill_color_gdk().set_value(c);
176}
177
178GraphDisplayerCanvas::LoopEdge::LoopEdge(Gnome::Canvas::Group& _group,
179    Edge _edge, GraphDisplayerCanvas& _canvas) :
180  EdgeBase(_group, _edge, _canvas), line(*this), isbutton(false)
181{
182  arrow.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::LoopEdge::edgeFormerEventHandler));
183
184  line.property_outline_color().set_value("green");
185  line.property_width_units().set_value(10);
186  line.lower_to_bottom();
187
188  draw();
189}
190
191GraphDisplayerCanvas::LoopEdge::~LoopEdge()
192{
193}
194
195void GraphDisplayerCanvas::LoopEdge::draw()
196{
197  MapStorage& ms = canvas.mytab.mapstorage;
198
199  Node node = ms.graph.source(edge);
200  XY center = (ms.coords[node] + ms.arrow_pos[edge]) / 2.0;
201
202  XY unit_vector_in_dir(rot90(center - ms.arrow_pos[edge]));
203  double length = sqrt(unit_vector_in_dir.normSquare());
204  unit_vector_in_dir /= length;
205
206  drawArrow(unit_vector_in_dir);
207
208  double radius =
209    sqrt((ms.arrow_pos[edge] - ms.coords[node]).normSquare()) / 2.0;
210
211  XY p1 = center + XY(-radius,  radius);
212  XY p2 = center + XY( radius, -radius);
213  line.property_x1().set_value(p1.x);
214  line.property_y1().set_value(p1.y);
215  line.property_x2().set_value(p2.x);
216  line.property_y2().set_value(p2.y);
217}
218
219void GraphDisplayerCanvas::LoopEdge::setLineWidth(int w)
220{
221  line.property_width_units().set_value(w);
222}
223
224void GraphDisplayerCanvas::LoopEdge::setFillColor(Gdk::Color c)
225{
226  line.property_outline_color_gdk().set_value(c);
227}
228
229bool GraphDisplayerCanvas::LoopEdge::edgeFormerEventHandler(GdkEvent* e)
230{
231  switch(e->type)
232  {
233    case GDK_BUTTON_PRESS:
234      if(canvas.getActualTool()!=CREATE_NODE)
235      {
236        canvas.toggleEdgeActivity(this, true);
237        isbutton=true;
238      }
239      break;
240    case GDK_BUTTON_RELEASE:
241      if(canvas.getActualTool()!=CREATE_NODE)
242      {
243        canvas.toggleEdgeActivity(this, false);
244        isbutton=false;
245      }
246      break;
247    case GDK_MOTION_NOTIFY:
248      if(isbutton)
249      {
250        canvas.mytab.mapstorage.arrow_pos.set(edge, XY(e->motion.x, e->motion.y));
251
252        draw();
253        canvas.textReposition(canvas.mytab.mapstorage.arrow_pos[edge]);
254      }
255    default: break;
256  }
257  return true;
258}
Note: See TracBrowser for help on using the repository browser.