|
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); }