home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / intrvews / xgrab.lha / xgrab / ui / clip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-03-07  |  4.3 KB  |  170 lines

  1. /**
  2.    GRAB Graph Layout and Browser System
  3.  
  4.    Copyright (c) 1986, 1988 Regents of the University of California
  5.    Copyright (c) 1989, Tera Computer Company
  6.  **/
  7.  
  8. /** 
  9.    clip.c - routines to do edge clipping. 
  10.  
  11.    The clipping routine is pretty naive, merely clipping against a box
  12.    with the width and height of the node the edge is heading towards,
  13.    even if the node happens to be, oh, say, an ellipse.
  14.  
  15.    Tricky points:  circles don't necessarily have the same width as
  16.    height, so the width is changed to match the height.  The height could
  17.    be changed to match the width, but when you do that, nodes with long
  18.    names become really big.  When you do it this way, long names tumble outside
  19.    the node, but that doesn't look half bad.
  20.  
  21.    With multiple edges possible between two nodes, it is undesirable to
  22.    have them all go to the same place.  So, edges are shifted right or left
  23.    a bit according to their ordinality.  This works fine for large slopes,
  24.    but gets worse and worse as the slope decreases.  Horizontal lines
  25.    must be handled by a special case.  In any event, the layout routines
  26.    prohibit horizontal edges, and tend to increase the slope of edges
  27.    by putting adjacent nodes as close to vertical as possible.  Edges
  28.    added by the user might look bad, but they should be a small percentage.
  29.  **/
  30.  
  31. #include "attribute.h"
  32. #include "digraph.h"
  33. #include "screen.h"
  34. #include "clip.h"
  35.  
  36. Clip(node, tonode, ord, from_x, from_y, to_x, to_y, screen)
  37. NODE *node, *tonode;
  38. int ord;
  39. double *from_x, *from_y;
  40. double *to_x, *to_y;
  41. SCREEN *screen;
  42.   /**
  43.      Clip the edge from node to tonode of ordinality ord and return 
  44.      the endpoints in to/from_x/y.
  45.    **/
  46. {
  47.     double shift;
  48.  
  49.       /* shift multiple edges from the same node */
  50.     shift = (double) ORD_TO_SHIFT(ord);
  51.  
  52.     if (Y_position(node) == Y_position(tonode))    /* horizontal edge */
  53.     {
  54.         *from_x = (double) X_position(node);
  55.         *from_y = (double) Y_position(node) + shift;
  56.         *to_x = (double) X_position(tonode);
  57.         *to_y = (double) Y_position(tonode) + shift;
  58.     }
  59.     else                    /* not horizontal */
  60.     {
  61.         *from_x = (double) X_position(node) + shift;
  62.         *from_y = (double) Y_position(node);
  63.         *to_x = (double) X_position(tonode) + shift;
  64.         *to_y = (double) Y_position(tonode);
  65.     }
  66.     
  67.     OneWayClip(tonode, from_x, from_y, to_x, to_y, screen);
  68.     OneWayClip(node, to_x, to_y, from_x, from_y, screen);
  69. }
  70.  
  71. OneWayClip(tonode, from_x, from_y, to_x, to_y, screen)
  72. NODE *tonode;
  73. double *from_x, *from_y;
  74. double *to_x, *to_y;
  75. SCREEN *screen;
  76.    /**
  77.       Clip the line from (from_x, from_y,) to (to_x, to_y) according
  78.       to tonode
  79.     **/
  80. {
  81.     double xdist, ydist;
  82.     double xright, xleft, ytop, ybottom;
  83.  
  84.     xright = (double) X_right(tonode);
  85.     xleft = (double) X_left(tonode);
  86.     ytop = (double) Y_top(tonode);
  87.     ybottom = (double) Y_bottom(tonode);
  88.  
  89.     if (Shape(tonode) == CIRCLE)
  90.        /* adjust right and left values to make it a circle */
  91.     {
  92.     double hh;
  93.  
  94.     hh = Half_height(tonode) / screen->zoom.yzoom * screen->zoom.xzoom;
  95.     xright = (double) X_position(tonode) + hh;
  96.     xleft = (double) X_position(tonode) - hh;
  97.     }
  98.     else if (Is_dummy(tonode))
  99.       /**
  100.      dummy nodes have width and height to insure they get enough
  101.      space when layed out, but for clipping purposes they are just
  102.      points
  103.        **/
  104.     {
  105.     xright = *to_x;
  106.     xleft = *to_x;
  107.     }
  108.  
  109.       /* if y's are = need only find which side to draw to */
  110.     if ((ydist = *from_y - *to_y) == 0) 
  111.     {
  112.     if (*from_x > *to_x) 
  113.     {
  114.         *to_x = xright;
  115.     }
  116.     else 
  117.     {
  118.         *to_x = xleft;
  119.     }
  120.     }
  121.       /* If y's <>, see if X's are = */
  122.     else if ((xdist = *from_x - *to_x) == 0) 
  123.     {
  124.         /* see what side to draw to */
  125.     if (*from_y > *to_y) 
  126.     {
  127.         *to_y = ytop;
  128.     }
  129.     else 
  130.     {
  131.         *to_y = ybottom;
  132.     }
  133.     }
  134.     else 
  135.     {
  136.       /**
  137.          otherwise if x's and y's are <>, aim for the top or bottom
  138.          of the node
  139.        **/
  140.     if (*from_y > *to_y) 
  141.     {
  142.         *to_y = ytop;
  143.     }
  144.     else 
  145.     {
  146.         *to_y = ybottom;
  147.     }
  148.  
  149.     *to_x = (xdist / ydist) * (*to_y - *from_y) + *from_x;
  150.  
  151.         /**
  152.          if to_x is too small or too large, the line will hit the
  153.          side of the node instead
  154.        **/
  155.     if ((*to_x < xleft) || (*to_x > xright)) 
  156.     {
  157.         if (*to_x < xleft) 
  158.         {
  159.         *to_x = xleft;
  160.         }
  161.         else 
  162.         {
  163.         *to_x = xright;
  164.         }
  165.  
  166.         *to_y = (ydist / xdist) * (*to_x - *from_x) + *from_y;
  167.     }
  168.     }
  169. }
  170.