home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / XAP / XFIG / TRANSFIG.2 / TRANSFIG / transfig / fig2dev / latex_line.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-14  |  5.4 KB  |  207 lines

  1. /*
  2.  * TransFig: Facility for Translating Fig code
  3.  * Copyright (c) 1985 Supoj Sutantavibul
  4.  * Copyright (c) 1991 Micah Beck
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation. The authors make no representations about the suitability 
  11.  * of this software for any purpose.  It is provided "as is" without express 
  12.  * or implied warranty.
  13.  *
  14.  * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16.  * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  *
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <math.h>
  26. /* 
  27.  *    latex_line.c: 
  28.  *        Subroutines for drawing and translating lines for the LaTeX
  29.  *        picture environment.
  30.  *    Written by Frank Schmuck (schmuck@svax.cs.cornell.edu)
  31.  *    June 1988
  32.  *
  33.  *    The LaTeX picture environment allows generating pictures in standard
  34.  *    LaTeX.  However, some restrictions apply:  lines and vectors (a vector
  35.  *    is a line with an arrow at the end) can only be drawn with a finite
  36.  *    number of slopes.  The available slopes are given by dy/dx where
  37.  *    dx and dy must be integers <= 6 for lines and <= 4 for vectors.
  38.  *
  39.  *    The subroutines in this file are used in fig2latex to approximate
  40.  *    an arbitrary line or vector by a LaTeX line/vector, and in fig to 
  41.  *    restrict line drawing to slopes supported by LaTeX.
  42.  */
  43.  
  44. /*
  45.  * Constant for converting from radian to degrees
  46.  */
  47. double rad2deg = 57.295779513082320877;
  48.  
  49. int  pgcd(a,b)
  50.     int a, b;
  51. /*
  52.  *  compute greatest common divisor, assuming 0 < a <= b
  53.  */
  54. {
  55.     b = b % a;
  56.     return (b)? gcd(b, a): a;
  57. }
  58.  
  59. int  gcd(a, b)
  60.     int a, b;
  61. /*
  62.  *  compute greatest common divisor
  63.  */
  64. {
  65.     if (a < 0) a = -a;
  66.     if (b < 0) b = -b;
  67.     return (a <= b)? pgcd(a, b): pgcd(b, a);
  68. }
  69.  
  70. int  lcm(a, b)
  71.     int a, b;
  72. /*
  73.  *  Compute least common multiple
  74.  */
  75. {
  76.     return abs(a*b)/gcd(a,b);
  77. }
  78.  
  79. /*
  80.  *  Tables of line and vector slopes supported by LaTeX
  81.  */
  82.  
  83. struct angle_table {
  84.     int    x, y;
  85.     double angle;
  86. };
  87.  
  88. #define N_LINE 25
  89.  
  90. struct angle_table line_angles[N_LINE] =
  91.   { {0, 1, 90.0}, 
  92.     {1, 0,  0.0},
  93.     {1, 1, 45.0}, 
  94.     {1, 2, 63.434948822922010648},
  95.     {1, 3, 71.565051177077989351},
  96.     {1, 4, 75.963756532073521417},
  97.     {1, 5, 78.690067525979786913},
  98.     {1, 6, 80.537677791974382609},
  99.     {2, 1, 26.565051177077989351},
  100.     {2, 3, 56.309932474020213086},
  101.     {2, 5, 68.198590513648188229}, 
  102.     {3, 1, 18.434948822922010648},
  103.     {3, 2, 33.690067525979786913},
  104.     {3, 4, 53.130102354155978703},
  105.     {3, 5, 59.036243467926478582},
  106.     {4, 1, 14.036243467926478588},
  107.     {4, 3, 36.869897645844021297},
  108.     {4, 5, 51.340191745909909396},
  109.     {5, 1, 11.309932474020213086},
  110.     {5, 2, 21.801409486351811770},
  111.     {5, 3, 30.963756532073521417},
  112.     {5, 4, 38.659808254090090604},
  113.     {5, 6, 50.194428907734805993},
  114.     {6, 1, 9.4623222080256173906},
  115.     {6, 5, 39.805571092265194006}
  116.   };
  117.  
  118. #define N_ARROW 13
  119.  
  120. struct angle_table arrow_angles[N_ARROW] =
  121.   { {0, 1, 90.0}, 
  122.     {1, 0,  0.0},
  123.     {1, 1, 45.0}, 
  124.     {1, 2, 63.434948822922010648},
  125.     {1, 3, 71.565051177077989351},
  126.     {1, 4, 75.963756532073521417},
  127.     {2, 1, 26.565051177077989351},
  128.     {2, 3, 56.309932474020213086},
  129.     {3, 1, 18.434948822922010648},
  130.     {3, 2, 33.690067525979786913},
  131.     {3, 4, 53.130102354155978703},
  132.     {4, 1, 14.036243467926478588},
  133.     {4, 3, 36.869897645844021297},
  134.   };
  135.  
  136. get_slope(dx, dy, sxp, syp, arrow)
  137.     int  dx, dy, *sxp, *syp, arrow;
  138. /*
  139.  *  Find the LaTeX line slope that is closest to the one given by dx, dy.
  140.  *  Result is returned in *sxp, *syp.  If (arrow != 0) the closest LaTeX
  141.  *  vector slope is selected.
  142.  */
  143. {
  144.     double angle;
  145.     int    i, s, max;
  146.     double d, d1;
  147.     struct angle_table *st;
  148.  
  149.     if (dx == 0) {
  150.     *sxp = 0;
  151.     *syp = (dy < 0)? -1: 1;
  152.     return;
  153.     }
  154.     angle = atan((double)abs(dy) / (double)abs(dx)) * rad2deg;
  155.     if (arrow) {
  156.     st = arrow_angles;
  157.     max = N_ARROW;
  158.     } else {
  159.     st = line_angles;
  160.     max = N_LINE;
  161.     }
  162.     s = 0;
  163.     d = 9.9e9;
  164.     for (i = 0; i < max; i++) {
  165.     d1 = fabs(angle - st[i].angle);
  166.     if (d1 < d) {
  167.         s = i;
  168.         d = d1;
  169.     } 
  170.     }
  171.     *sxp = st[s].x;
  172.     if (dx < 0) *sxp = -*sxp;
  173.     *syp = st[s].y;
  174.     if (dy < 0) *syp = -*syp;
  175. }
  176.  
  177. latex_endpoint(x1, y1, x2, y2, xout, yout, arrow, magnet)
  178.     int  x1, y1, x2, y2;
  179.     int  *xout, *yout;
  180.     int  arrow, magnet;
  181. /*
  182.  *  Computes a point "close" to (x2,y2) that is reachable from (x1,y1)
  183.  *  by a LaTeX line (LaTeX vector if arrow != 0).  The result is returned
  184.  *  in *xout, *yout.  If (magnet > 1) the point returned is selected such that
  185.  *  (*xout - x1) and (*yout - y1) are both multiples of magnet.
  186.  */
  187. {
  188.     int    dx, dy, sx, sy, ds, dsx, dsy;
  189.  
  190.     dx = x2-x1;
  191.     dy = y2-y1;
  192.     get_slope(dx, dy, &sx, &sy, arrow);
  193.     if (abs(sx) >= abs(sy)) {
  194.     ds = lcm(sx, magnet*gcd(sx,magnet));
  195.     dsx = (2*abs(dx)/ds + 1)/2;
  196.     dsx = (dx >= 0)? dsx*ds: -dsx*ds;
  197.     *xout = x1 + dsx;
  198.     *yout = y1 + dsx*sy/sx;
  199.     } else {
  200.     ds = lcm(sy, magnet*gcd(sy,magnet));
  201.     dsy = (2*abs(dy)/ds + 1)/2;
  202.     dsy = (dy >= 0)? dsy*ds: -dsy*ds;
  203.     *yout = y1 + dsy;
  204.     *xout = x1 + dsy*sx/sy;
  205.     }
  206. }
  207.