|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T f
Length: 16638 (0x40fe)
Types: TextFile
Names: »fig2tex.c«
└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
└─⟦this⟧ »./tex82/TeXgraphics/transfig/fig2tex/fig2tex.c«
/*
* Fig2tex : The fig-to-PicTeX translator
*
* Modified from ftp, the fig-to-to-pic translator
*
* University of Texas at Austin,
*
*/
/*
* Modified 1987 for PicTeX output by Micah Beck (beck@svax.cs.cornell.edu)
*
*/
#include <stdio.h>
#include <math.h>
#include "object.h"
#include "choices.h"
#define round(x) ((int) (x + .5))
#define max(a,b) ((a > b) ? a : b)
#define min(a,b) ((a < b) ? a : b)
#define MINMAX(X,Y) { min_x = min(X, min_x); \
min_y = min(Y, min_y); \
max_x = max(X, max_x); \
max_y = max(Y, max_y); \
}
#define SWITCH(T,A,B) { register T t; \
t = A; \
A = B; \
B = t; \
}
#define EPSILON 0.02
#define CLOSE(A,B) (fabs(A-B) < EPSILON)
extern int getopt();
extern char *optarg;
extern int optind;
extern double sin(), cos(), acos(), fabs();
FILE *tfp;
float PIX_PER_INCH, mag;
int cur_style, cur_dashlength;
main(argc, argv)
int argc;
char *argv[];
{
char *textfont, *linethick, *plotsymbol;
char *from, *to, text[80], c;
FILE *ffp;
int arb, size, type, style, thickness, direction;
int n, num_obj, font, object;
int f_arrow, b_arrow, arrow_wid, arrow_ht;
float CANVAS_WIDTH, CANVAS_HEIGHT, ORIGIN;
float dummy, width, height, length, dash_length;
float a, b;
float x, y, x1, y1, x2, y2, xsav, ysav;
float cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
float min_x, min_y, max_x, max_y;
double dx1, dx2, dy1, dy2, r1, th1, r2, th2, theta, t;
mag = 1.0;
textfont = "\\twltt";
linethick = ".7pt";
plotsymbol = "\\sevrm .";
from = NULL;
to = NULL;
while ((c = getopt(argc, argv, "af:l:p:m:")) != EOF)
switch (c) {
case 'a': /* arbitrary text */
arb = 1;
case 'f': /* set text font */
textfont = optarg;
break;
case 'l': /* set line thickness */
linethick = optarg;
break;
case 'p': /* set plot symbol */
plotsymbol = optarg;
break;
case 'm':
mag = atof(optarg); /* set magnification */
break;
case '?':
exit(1);
break;
}
if (optind < argc) from = argv[optind++]; /* from file */
if (optind < argc) to = argv[optind]; /* to file */
if (from == NULL)
ffp = stdin;
else if ((ffp = fopen(from, "r")) == NULL) {
fprintf(stderr, "Couldn't open %s\n", from);
exit(1);
}
if (to == NULL)
tfp = stdout;
else if ((tfp = fopen(to, "w")) == NULL) {
fprintf(stderr, "Couldn't open %s\n", to);
exit(1);
}
cur_style = SOLID_LINE;
cur_dashlength = 0;
fscanf(ffp,"%f %f %f %f\n", &PIX_PER_INCH, &ORIGIN,
&CANVAS_WIDTH, &CANVAS_HEIGHT);
max_x = max_y = 0;
min_x = CANVAS_WIDTH;
min_y = CANVAS_HEIGHT;
fprintf(tfp, "\\mbox{\\beginpicture\n");
fprintf(tfp, "\\setcoordinatesystem units <%6.3fin,%6.3fin>\n",
mag, mag);
fprintf(tfp, "\\linethickness=%s\n", linethick);
fprintf(tfp, "\\setplotsymbol ({%s})\n", plotsymbol);
fprintf(tfp, "\\setlinear\n");
fprintf(tfp, "\\if \\picturemode \\nopics \\else\n");
fprintf(tfp, "\\if \\picturemode \\dottedpics \\setdots \\fi");
fprintf(tfp, "\\if \\picturemode \\optpics\n");
fprintf(tfp, "\\unitlength=%6.3fin\n", mag);
fprintf(tfp, "\\thicklines\n");
fprintf(tfp, "\\fi\n");
num_obj = 0;
while ((fscanf(ffp, "%d", &object)) != EOF) {
switch (object) {
case ARC :
num_obj++;
fprintf(tfp, "%%\n%% Fig ARC object (#%d)\n%%\n", num_obj);
n = fscanf(ffp, " %d %d %d %f %d %d %d %d %d %f %f %f %f %f %f %f %f\n",
&type, &style, &thickness,
&dash_length, &direction, &f_arrow, &b_arrow,
&arrow_ht, &arrow_wid, &x, &y,
&x1, &y1, &dummy, &dummy, &x2, &y2);
if (n != 17) {
fprintf(stderr, "Arc (object #%d) is incomplete\n",
num_obj);
fscanf(ffp, " %[^\n]", text); /* skip to next line */
break;
}
if (direction == 1) {
SWITCH(float, x1, x2);
SWITCH(float, y1, y2);
SWITCH(int, f_arrow, b_arrow);
}
dx1 = x1 - x;
dy1 = y1 - y;
dx2 = x2 - x;
dy2 = y2 - y;
rtop(dx1, dy1, &r1, &th1);
rtop(dx2, dy2, &r2, &th2);
theta = th1 - th2;
if (theta > 0) theta -= 360;
MINMAX(x1, y1);
MINMAX(x2, y2);
for (t = 0; t > theta * acos(0.0) / 90; t -= .1)
MINMAX(x + r1 * cos(th1+t), y + r1 * sin(th1+t));
x = x / PIX_PER_INCH; /* (x,y) is the center of the arc */
y = (CANVAS_HEIGHT - y) / PIX_PER_INCH;
x1 = x1 / PIX_PER_INCH;
y1 = (CANVAS_HEIGHT - y1) / PIX_PER_INCH;
x2 = x2 / PIX_PER_INCH;
y2 = (CANVAS_HEIGHT - y2) / PIX_PER_INCH;
if (b_arrow) setarrow(tfp,
((float)arrow_wid)/PIX_PER_INCH,
((float)arrow_ht)/PIX_PER_INCH,
x1+(y1-y), y1-(x1-x), x1, y1);
if (f_arrow) setarrow(tfp,
((float)arrow_wid)/PIX_PER_INCH,
((float)arrow_ht)/PIX_PER_INCH,
x2-(y2-y), y2+(x2-x), x2, y2);
setstyle(style, dash_length);
fprintf(tfp, "\\circulararc %6.3f degrees from %6.3f %6.3f center at %6.3f %6.3f\n",
theta, x1, y1, x, y);
break;
case POLYLINE :
num_obj++;
fprintf(tfp, "%%\n%% Fig POLYLINE object (#%d)\n%%\n",
num_obj);
n = fscanf(ffp, " %d %d %d %f %d %d %d %d",
&type, &style, &thickness,
&dash_length, &f_arrow, &b_arrow,
&arrow_ht, &arrow_wid);
if (n != 8) {
fprintf(stderr, "Line (object #%d) is incomplete\n",
num_obj);
fscanf(ffp, " %[^\n]", text); /* skip to next line */
break;
}
if (fscanf(ffp, " %f %f %f %f", &x1, &y1, &x2, &y2) != 4) {
fprintf(stderr, "Line (object #%d) is incomplete\n",
num_obj);
fscanf(ffp, " %[^\n]", text); /* skip to next line */
break;
};
MINMAX(x1, y1);
x1 = x1 / PIX_PER_INCH;
y1 = (CANVAS_HEIGHT - y1) / PIX_PER_INCH;
if (x2 == 9999 && y2 == 9999) { /* A single point line */
fprintf(tfp, "\\plot %6.3f %6.3f %6.3f %6.3f/\n",
x1, y1, x1, y1);
break;
}
MINMAX(x2, y2);
x2 = x2 / PIX_PER_INCH;
y2 = (CANVAS_HEIGHT - y2) / PIX_PER_INCH;
if (b_arrow) setarrow(tfp,
((float)arrow_wid)/PIX_PER_INCH,
((float)arrow_ht)/PIX_PER_INCH,
x2, y2, x1, y1);
setstyle(style, dash_length);
putline(x1, y1, x2, y2);
for (;;) {
if (fscanf(ffp, " %f %f", &x, &y) != 2) {
fprintf(stderr, "Line (object #%d) is incomplete\n",
num_obj);
fscanf(ffp, "%*[^\n]"); /* Flush the buffer */
break;
};
if (x == 9999) break;
MINMAX(x, y);
x = x / PIX_PER_INCH;
y = (CANVAS_HEIGHT - y) / PIX_PER_INCH;
putline(x2, y2, x, y);
x1 = x2;
y1 = y2;
x2 = x;
y2 = y;
}
if (f_arrow) setarrow(tfp,
((float)arrow_wid)/PIX_PER_INCH,
((float)arrow_ht) /PIX_PER_INCH,
x1, y1, x2, y2);
break;
case SPLINE :
num_obj++;
fprintf(tfp, "%%\n%% Fig SPLINE object (#%d)\n%%\n",
num_obj);
n = fscanf(ffp, " %d %d %d %f %d %d %d %d", &type, &style,
&thickness, &dash_length,
&f_arrow, &b_arrow, &arrow_ht, &arrow_wid);
if (n != 8) {
fprintf(stderr, "Spline (object #%d) is incomplete\n",
num_obj);
fscanf(ffp, " %[^\n]", text); /* skip to next line */
break;
}
if (fscanf(ffp, " %f %f %f %f", &x1, &y1, &x2, &y2) != 4) {
fprintf(stderr, "Spline (object #%d) is incomplete\n",
num_obj);
fscanf(ffp, " %[^\n]", text); /* skip to next line */
break;
};
MINMAX(x1, y1);
MINMAX(x2, y2);
y1 = (CANVAS_HEIGHT - y1);
y2 = (CANVAS_HEIGHT - y2);
if (b_arrow) setarrow(tfp,
((float)arrow_wid)/PIX_PER_INCH,
((float)arrow_ht)/PIX_PER_INCH,
x2/PIX_PER_INCH, y2/PIX_PER_INCH,
x1/PIX_PER_INCH, y1/PIX_PER_INCH);
setstyle(style, dash_length);
cx1 = (x1 + x2) / 2; cy1 = (y1 + y2) / 2;
cx2 = (x1 + 3 * x2) / 4; cy2 = (y1 + 3 * y2) / 4;
if (type == DRAW_SPLINE)
fprintf(tfp, "\\plot %6.3f %6.3f %6.3f %6.3f\n",
x1/PIX_PER_INCH, y1/PIX_PER_INCH,
cx1/PIX_PER_INCH, cy1/PIX_PER_INCH);
else
fprintf(tfp, "\\plot \n");
/* save closure point for close splines */
xsav = x2;
ysav = y2;
for (n=2;;n++) {
if (fscanf(ffp, " %f %f", &x, &y) != 2) {
fprintf(stderr, "Spline (object #%d) is incomplete\n",
num_obj);
fscanf(ffp, "%*[^\n]"); /* Flush the buffer */
break;
};
if (x == 9999) break;
MINMAX(x, y);
y = (CANVAS_HEIGHT - y);
x1 = x2; y1 = y2;
x2 = x; y2 = y;
cx3 = (3 * x1 + x2) / 4; cy3 = (3 * y1 + y2) / 4;
cx4 = (x1 + x2) / 2; cy4 = (y1 + y2) / 2;
chaikin_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
cx1 = cx4; cy1 = cy4;
cx2 = (x1 + 3 * x2) / 4; cy2 = (y1 + 3 * y2) / 4;
}
if (type == DRAW_SPLINE)
fprintf(tfp, "\t%6.3f %6.3f /\n",
(int)x2/PIX_PER_INCH, (int)y2/PIX_PER_INCH);
else {
fprintf(tfp, "\t/\n\\plot\n");
x1 = x2; y1 = y2;
x2 = xsav; y2 = ysav;
cx3 = (3 * x1 + x2) / 4; cy3 = (3 * y1 + y2) / 4;
cx4 = (x1 + x2) / 2; cy4 = (y1 + y2) / 2;
chaikin_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
fprintf(tfp, "\t/\n");
}
if (f_arrow) setarrow(tfp,
((float)arrow_wid)/PIX_PER_INCH,
((float)arrow_ht) /PIX_PER_INCH,
x1/PIX_PER_INCH, y1/PIX_PER_INCH,
x2/PIX_PER_INCH, y2/PIX_PER_INCH);
break;
case ELLIPSE :
num_obj++;
fprintf(tfp, "%%\n%% Fig ELLIPSE object (#%d)\n%%\n",
num_obj);
n = fscanf(ffp, " %d %d %d %f %d %f %f %f %f %f %f %f %f\n",
&type, &style, &thickness, &dash_length,
&direction, &x, &y, &a, &b,
&dummy, &dummy, &dummy, &dummy);
if (n != 13) {
fprintf(stderr, "Ellipse (object #%d) is incomplete\n",
num_obj);
fscanf(ffp, " %[^\n]", text); /* skip to next line */
break;
}
setstyle(style, dash_length);
MINMAX(x+a, y);
MINMAX(x-a, y);
MINMAX(x, y+b);
MINMAX(x, y-b);
x = x / PIX_PER_INCH;
y = (CANVAS_HEIGHT - y) / PIX_PER_INCH;
width = a / PIX_PER_INCH;
height = b / PIX_PER_INCH;
if (!latexcircle(width, height, x, y))
fprintf(tfp, "\\iffalse ");
fprintf(tfp, "\\else\n");
fprintf(tfp, "\\ellipticalarc axes ratio %6.3f:%-6.3f 360 degrees \n",
width, height);
fprintf(tfp, "\tfrom %6.3f %6.3f center at %6.3f %6.3f\n",
x+width, y, x, y);
fprintf(tfp, "\\fi\n");
break;
case TEXT :
num_obj++;
fprintf(tfp, "%%\n%% Fig TEXT object (#%d)\n%%\n",
num_obj);
n = fscanf(ffp, "%d %d %d %f %f %f %f %[^\n]",
&font, &size,
&style, &height, &length, &x, &y, text);
if (n != 8) {
fprintf(stderr, "Text (object #%d) is incomplete\n",
num_obj);
fscanf(ffp, " %[^\n]", text); /* skip to next line */
break;
}
MINMAX(x,y);
MINMAX(x+length, y-height)
x = x / PIX_PER_INCH;
y = (CANVAS_HEIGHT - y) / PIX_PER_INCH;
if (arb)
/* arbitrary tex needs no hbox */
fprintf(tfp, "\\put {%s %s} [lB] at %6.3f %6.3f\n",
textfont, text, x, y);
else
fprintf(tfp, "\\put {\\hbox to %6.3fin{%s %s}} [lB] at %6.3f %6.3f\n",
length/PIX_PER_INCH, textfont, text, x, y);
break;
case COMPOUND :
fscanf(ffp, " %[^\n]", text); /* ignore the rest */
default :
break;
}
}
fprintf(tfp, "\\fi\n");
fprintf(tfp, "\\linethickness=0pt\n");
fprintf(tfp, "\\putrectangle corners at %6.3f %6.3f and %6.3f %6.3f\n",
min_x/PIX_PER_INCH,(CANVAS_HEIGHT-max_y)/PIX_PER_INCH,
max_x/PIX_PER_INCH,(CANVAS_HEIGHT-min_y)/PIX_PER_INCH);
fprintf(tfp, "\\endpicture}\n");
}
/*
* putline - use rules if possible
*/
putline (start_x, start_y, end_x, end_y)
float start_x, start_y, end_x, end_y;
{
if (cur_style == SOLID_LINE &&
(CLOSE (start_x, end_x) || CLOSE (start_y, end_y)))
fprintf(tfp, "\\putrule from %6.3f %6.3f to %6.3f %6.3f\n",
start_x, start_y, end_x, end_y);
else {
if (!latexline(start_x, start_y, end_x, end_y))
fprintf(tfp, "\\iffalse\n");
fprintf(tfp, "\\else\n");
fprintf(tfp, "\\plot %6.3f %6.3f %6.3f %6.3f /\n",
start_x, start_y, end_x, end_y);
fprintf(tfp, "\\fi\n");
}
}
/*
* setstyle - issue style commands as appropriate
*/
setstyle(style, dash_length)
int style;
float dash_length;
{
switch (style) {
case SOLID_LINE:
if (cur_style == SOLID_LINE) break;
fprintf(tfp, "\\setsolid\n");
break;
case DASH_LINE:
if (cur_style == DASH_LINE && cur_dashlength == dash_length)
break;
fprintf(tfp, "\\setdashes <%7.4fin>\n",dash_length / PIX_PER_INCH);
break;
case DOTTED_LINE:
if (cur_style == DOTTED_LINE)
break;
fprintf(tfp, "\\setdots \n");
break;
}
cur_style = style;
cur_dashlength = dash_length;
}
/*
* setarrow - construct an arrow from a given direction
*/
setarrow(tfp, w, l, ex, ey, ax, ay)
FILE *tfp;
float w, l, ex, ey, ax, ay;
{
float L, beta, gamma;
L = hypot(ex - ax, ey - ay);
ex = (ax + .01*(ex - ax)/L);
ey = (ay + .01*(ey - ay)/L);
gamma = w/l;
beta = gamma/2;
setstyle(SOLID_LINE, 0.0);
fprintf(tfp, "\\arrow <%6.3fin> [%6.3f,%6.3f] from %6.3f %6.3f to %6.3f %6.3f\n",
l*mag, beta, gamma, ex, ey, ax, ay);
}
/*
* rtop - rectangular to polar conversion
*/
rtop(x, y, r, th)
double x, y, *r, *th;
{
*r = hypot(x,y);
*th = acos(x/(*r)) * 90 /acos(0.0);
if (y < 0) *th = 360 - *th;
}
/****************************************************************************
The following spline drawing routine is from
"An Algorithm for High-Speed Curve Generation"
by George Merrill Chaikin,
Computer Graphics and Image Processing, 3, Academic Press,
1974, 346-349.
and
"On Chaikin's Algorithm" by R. F. Riesenfeld,
Computer Graphics and Image Processing, 4, Academic Press,
1975, 304-310.
*****************************************************************************/
chaikin_spline(x1, y1, x2, y2, x3, y3, x4, y4)
float x1, y1, x2, y2, x3, y3, x4, y4;
{
float xmid, ymid;
xmid = (x2 + x3) / 2; ymid = (y2 + y3) / 2;
if (fabs(x1 - xmid) < 1 && fabs(y1 - ymid) < 1)
draw_vector(x1, y1, xmid, ymid);
else {
chaikin_spline(x1, y1,
((x1 + x2) / 2), ((y1 + y2) / 2),
((3*x2 + x3) / 4), ((3*y2 + y3) / 4), xmid, ymid);
}
if (fabs(xmid - x4) < 1 && fabs(ymid - y4) < 1) {
draw_vector(xmid, ymid, x4, y4);
}
else {
chaikin_spline(xmid, ymid,
((x2 + 3*x3) / 4), ((y2 + 3*y3) / 4),
((x3 + x4) / 2), ((y3 + y4) / 2), x4, y4);
}
}
draw_vector(x1, y1, x2, y2)
float x1, y1, x2, y2;
{
fprintf(tfp, "\t%6.3f %6.3f\n",
x2 / PIX_PER_INCH, y2 / PIX_PER_INCH);
}
/********************************************************************
LaTeX Object Optimizer Routines
********************************************************************/
/*
* Slopes implemented in LaTeX and the corresponding args to \line
*/
float slopes[][2]= { {0.,1.},
{1.,1.},{2.,1.},{3.,1.},{4.,1.},{5.,1.},{6.,1.},
{1.,2.}, {3.,2.}, {5.,2.},
{1.,3.},{2.,3.}, {4.,3.},{5.,3.},
{1.,4.}, {3.,4.}, {5.,4.},
{1.,5.},{2.,5.},{3.,5.},{4.,5.},{6.,5.},
{1.,6.}, {5.,6.},
{-1.,0.}};
float upslope[2]={1.,0.}, downslope[2]={-1.,0.};
/*
* latexline - generate a LaTeX line if possible
*/
latexline(x1, y1, x2, y2)
float x1, y1, x2, y2;
{
float *lineargs;
float len, sl, t, delta;
int sign = 1;
int i;
if (cur_style != SOLID_LINE) return(0);
if (CLOSE(x1, x2)) {
len = fabs(y2-y1);
if (y2 > y1)
lineargs = upslope;
else {
lineargs = downslope;
}
}
else {
if (x2 < x1) {
SWITCH(float, x1, x2);
SWITCH(float, y1, y2);
}
len = x2 - x1;
if (len*mag < 1/7.) return(0);
sl = (y2 - y1) / (x2 - x1);
if (sl < 0) {
sl = -sl;
sign = -1;
}
for (i=0, delta=1.0; slopes[i][0] >= 0; i++)
if ((t = fabs(atan(sl) - atan(slopes[i][0]/slopes[i][1]))) < delta) {
delta = t;
lineargs = slopes[i];
}
}
if (CLOSE(delta, 0.0)) {
fprintf(tfp, "\\if \\picturemode \\optpics\n");
fprintf(tfp,"\\put {\\line(%.0f,%.0f){%6.3f}} [Bl] at %6.3f %6.3f\n",
lineargs[1], sign*lineargs[0], len, x1, y1);
return(1);
}
else
return(0);
}
/*
* latexcircle - generate a LaTeX circle if possible
*/
latexcircle(w, h, x, y)
float w, h, x, y;
{
if (cur_style != SOLID_LINE) return(0);
if (!CLOSE(w, h)) return(0);
if (2*w > 15.5/72.27) return(0);
fprintf(tfp, "\\if \\picturemode \\optpics\n");
fprintf(tfp, "\\put {\\circle{%6.3f}} [lB] at %6.3f %6.3f\n",
2*w, x, y);
return(1);
}