gdc-broken_edge.cc
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
branchgui
changeset 90 e9f8f44f12a3
parent 80 231191361de5
child 93 56eb90299693
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
     1 #include "graph_displayer_canvas.h"
     2 #include <cmath>
     3 
     4 GraphDisplayerCanvas::BrokenEdge::BrokenEdge(Gnome::Canvas::Group & g, Gnome::Canvas::Points p, GraphDisplayerCanvas & gc) : Line(g), gdc(gc), isbutton(false)
     5 {
     6   my_points=new Gnome::Art::Point[3];
     7 
     8   arrow=new Gnome::Canvas::Polygon(g);
     9   *arrow << Gnome::Canvas::Properties::fill_color("red");
    10   arrow->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::BrokenEdge::edgeFormerEventHandler));
    11   arrow->lower_to_bottom();
    12   setPoints(p);
    13 }
    14 
    15 GraphDisplayerCanvas::BrokenEdge::~BrokenEdge()
    16 {
    17   if(arrow)delete(arrow);
    18 }
    19 
    20 void GraphDisplayerCanvas::BrokenEdge::setPoints(Gnome::Canvas::Points p, bool move)
    21 {
    22   bool set_arrow=false;
    23   //red arrow losts its position-right button
    24   if(!move)
    25     {
    26       if(p.size()==2)
    27 	{
    28 	  set_arrow=true;
    29 	  Gnome::Canvas::Points points_with_center;
    30 	  points_with_center.push_back(my_points[0]=p[0]);
    31 	  points_with_center.push_back(my_points[1]=Gnome::Art::Point( (p[0].get_x()+p[1].get_x())/2+0 , (p[0].get_y()+p[1].get_y())/2 )+0 );
    32 	  points_with_center.push_back(my_points[2]=p[1]);
    33 	  property_points().set_value(points_with_center);
    34 	}  
    35       if(p.size()==3)
    36 	{
    37 	  set_arrow=true;
    38 	  property_points().set_value(p);
    39 	  for(int i=0;i<3;i++)
    40 	    {
    41 	      my_points[i]=p[i];
    42 	    }
    43 	}
    44     }
    45   else
    46     {
    47       //arrow keeps its position-left button
    48 
    49 //       if(p.size()==2)
    50 //       	{
    51 //       	  Gnome::Canvas::Points points;
    52 //       	  my_points[0]=p[0];
    53 //       	  my_points[2]=p[1];
    54 //       	  for(int i=0;i<3;i++)
    55 //       	    {
    56 //       	      points.push_back(my_points[i]);
    57 //       	    }
    58 //       	  property_points().set_value(points);
    59 //       	}
    60       set_arrow=true;
    61 
    62       //////////////////////////////////////////////////////////////////////////////////////////////////////
    63       /////////// keeps shape-with scalar multiplication - version 2.
    64       //////////////////////////////////////////////////////////////////////////////////////////////////////
    65 
    66       if(p.size()==2)
    67       	{
    68 	  //old vector from one to the other node - a
    69 	  xy<double> a_v(my_points[2].get_x()-my_points[0].get_x(),my_points[2].get_y()-my_points[0].get_y());
    70 	  //new vector from one to the other node - b
    71 	  xy<double> b_v(p[1].get_x()-p[0].get_x(),p[1].get_y()-p[0].get_y());
    72 
    73 	  double absa=sqrt(a_v.normSquare());
    74 	  double absb=sqrt(b_v.normSquare());
    75 
    76 	  //old vector from one node to the breakpoint - c
    77 	  xy<double> c_v(my_points[1].get_x()-my_points[0].get_x(),my_points[1].get_y()-my_points[0].get_y());
    78 
    79 	  //unit vector with the same direction to a_v
    80 	  xy<double> a_v_u(a_v.x/absa,a_v.y/absa);
    81 
    82 	  //normal vector of unit vector with the same direction to a_v
    83 	  xy<double> a_v_u_n(((-1)*a_v_u.y),a_v_u.x);
    84 
    85 	  //unit vector with the same direction to b_v
    86 	  xy<double> b_v_u(b_v.x/absb,b_v.y/absb);
    87 
    88 	  //normal vector of unit vector with the same direction to b_v
    89 	  xy<double> b_v_u_n(((-1)*b_v_u.y),b_v_u.x);
    90 
    91 	  //vector c in a_v_u and a_v_u_n co-ordinate system
    92 	  xy<double> c_a(c_v*a_v_u,c_v*a_v_u_n);
    93 
    94 	  //new vector from one node to the breakpoint - d - we have to calculate this one
    95 	  xy<double> d_v=absb/absa*(c_a.x*b_v_u+c_a.y*b_v_u_n);
    96 
    97 	  my_points[1]=Gnome::Art::Point(d_v.x+p[0].get_x(),d_v.y+p[0].get_y());
    98 
    99       	  my_points[0]=p[0];
   100       	  my_points[2]=p[1];
   101 
   102 	  Gnome::Canvas::Points points;
   103 	  for(int i=0;i<3;i++)
   104 	    {
   105 	      points.push_back(my_points[i]);
   106 	    }
   107 	  property_points().set_value(points);
   108 	}
   109     }
   110   if(set_arrow)
   111     {
   112       //calculating coordinates of the direction indicator arrow
   113 
   114       xy<gdouble> target( my_points[2].get_x(), my_points[2].get_y() );
   115       xy<gdouble> center( my_points[1].get_x(), my_points[1].get_y() );
   116 
   117       xy<gdouble> unit_vector_in_dir(target-center);
   118       //       std::cout << target << " - " << center << " = " << unit_vector_in_dir << "    / " <<unit_vector_in_dir.normSquare() ;
   119       unit_vector_in_dir/=sqrt( unit_vector_in_dir.normSquare() );
   120       //       std::cout << " = " << unit_vector_in_dir << std::endl;
   121 
   122       xy<gdouble> unit_norm_vector(0-unit_vector_in_dir.y, unit_vector_in_dir.x);
   123       //       std::cout << unit_norm_vector << std::endl;
   124 
   125       {      
   126 	//       /\       // top
   127 	//      /  \      //
   128 	//      -  -      // c(enter)l(eft), ccl, ccr, cr
   129 	//       ||       //
   130 	//       ||       // b(ottom)l, br
   131       }
   132 
   133       double size=3;
   134 
   135       xy<gdouble> bl (center - unit_vector_in_dir * 3 * size + unit_norm_vector * size );
   136       xy<gdouble> br (center - unit_vector_in_dir * 3 * size - unit_norm_vector * size );
   137       xy<gdouble> ccl(center + unit_vector_in_dir *  size + unit_norm_vector * size );
   138       xy<gdouble> ccr(center + unit_vector_in_dir *  size - unit_norm_vector * size );
   139       xy<gdouble> cl (center + unit_vector_in_dir *  size + unit_norm_vector * 2 * size );
   140       xy<gdouble> cr (center + unit_vector_in_dir *  size - unit_norm_vector * 2 * size );
   141       xy<gdouble> top(center + unit_vector_in_dir * 3 * size);
   142 	 
   143       //       std::cout << bl << " " << br << " " << ccl << " "  << ccr << " " << cl << " " << cr << " " << top << std::endl;
   144 
   145       Gnome::Canvas::Points arrow_points;
   146       arrow_points.push_back(Gnome::Art::Point( bl.x , bl.y  ) );
   147       arrow_points.push_back(Gnome::Art::Point( br.x , br.y  ) );
   148       arrow_points.push_back(Gnome::Art::Point( ccr.x, ccr.y ) );
   149       arrow_points.push_back(Gnome::Art::Point( cr.x , cr.y  ) );
   150       arrow_points.push_back(Gnome::Art::Point( top.x, top.y ) );
   151       arrow_points.push_back(Gnome::Art::Point( cl.x , cl.y  ) );
   152       arrow_points.push_back(Gnome::Art::Point( ccl.x, ccl.y ) );
   153 
   154       arrow->property_points().set_value(arrow_points);
   155     }
   156 }
   157 
   158 bool GraphDisplayerCanvas::BrokenEdge::edgeFormerEventHandler(GdkEvent* e)
   159 {
   160   switch(e->type)
   161     {
   162     case GDK_BUTTON_PRESS:
   163       //we mark the location of the event to be able to calculate parameters of dragging
   164       if(gdc.getActualTool()!=CREATE_NODE)
   165 	{
   166 	  gdc.toggleEdgeActivity(this, true);
   167 	  clicked_x=e->button.x;
   168 	  clicked_y=e->button.y;
   169 	  isbutton=true;
   170 	}
   171       break;
   172     case GDK_BUTTON_RELEASE:
   173       if(gdc.getActualTool()!=CREATE_NODE)
   174 	{
   175 	  gdc.toggleEdgeActivity(this, false);
   176 	  isbutton=false;
   177 	}
   178       break;
   179     case GDK_MOTION_NOTIFY:
   180       //we only have to do sg. if the mouse button is pressed
   181       if(isbutton)
   182 	{
   183 	  //new coordinates will be the old values,
   184 	  //because the item will be moved to the
   185 	  //new coordinate therefore the new movement
   186 	  //has to be calculated from here
   187 
   188 	  double dx=e->motion.x-clicked_x;
   189 	  double dy=e->motion.y-clicked_y;
   190 
   191 	  Gnome::Canvas::Points points_new;
   192 
   193 	  points_new.push_back(my_points[0]);
   194 	  points_new.push_back(my_points[1]=Gnome::Art::Point(my_points[1].get_x()+dx,my_points[1].get_y()+dy));
   195 	  points_new.push_back(my_points[2]);
   196 
   197 	  setPoints(points_new);
   198 	  gdc.textReposition(xy<double>(my_points[1].get_x(),my_points[1].get_y()));
   199 
   200 	  clicked_x=e->motion.x;
   201 	  clicked_y=e->motion.y;
   202 
   203 	}
   204     default: break;
   205     }
   206 
   207   return true;
   208 }
   209 
   210 xy<double> GraphDisplayerCanvas::BrokenEdge::getArrowPos()
   211 {
   212   xy<double> ret_val(my_points[1].get_x(),my_points[1].get_y());
   213   return ret_val;
   214 }