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