source: tags/initial/fig2dev/latex_line.c

Last change on this file was 2, checked in by oldcode, 24 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.4 KB
Line 
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 */
47double rad2deg = 57.295779513082320877;
48
49int  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
59int  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
70int  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 
83struct angle_table {
84    int    x, y;
85    double angle;
86};
87
88#define N_LINE 25
89
90struct 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
120struct 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
136get_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
177latex_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}
Note: See TracBrowser for help on using the repository browser.