DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T f

⟦44d41c603⟧ TextFile

    Length: 15112 (0x3b08)
    Types: TextFile
    Names: »fig2latex.c«

Derivation

└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
    └─⟦this⟧ »./tex82/TeXgraphics/fig2latex/fig2latex.c« 

TextFile

/* 
 *	Fig2latex : Fig-to-LaTeX translator
 *
 *	Modified 4/88 from f2p, the Fig-to-pic translator
 *	Modified 6/88 from fig2tex, the Fig-to-PiCTeX translator
 *
 *	Copyright (c) 1985, 1988 by Supoj Sutanthavibul (supoj@sally.UTEXAS.EDU)
 *	January 1985.
 *	1st revision : October 1985.
 *	2nd revision : March 1988 - read fig 1.4
 *	converted    : April 1988 - produce PiCTeX output
 *		by Micah Beck, Cornell Univ. (beck@svax.cs.cornell.edu)
 *	converted    : June 1988 - produce LaTeX picture environment output
 *		by Frank Schmuck, Cornell Univ. (schmuck@svax.cs.cornell.edu)
 *
 *	%W	%G%
*/
#include <sys/file.h>
#include <stdio.h>
#include <math.h>
#include "object.h"
#include "fig2latex.h"

#define TOP		840
#define THINLINES	1
#define THICKLINES	2

#define	SWAP(x,y)	{tmp=x; x=y; y=tmp;}
#define round(x)	((rint(1000.0*(x))/1000.0))
#define TRANS(x,y)		translate_coordinates(&x,&y)
#define TRANS2(x1,y1,x2,y2)	translate_coordinates(&x1,&y1); \
				translate_coordinates(&x2,&y2)

extern int getopt();
extern char *optarg;
extern int optind;

extern double sin(), cos(), acos(), fabs();

char		Usage[] =
	"Usage: fig2latex [-f font] [-l thick] [-m mag] [-d dashm] [-Lvo] [in_file [out_file]]\n";
char		Err_incomp[] = "Incomplete %s object at line %d.";
char		Err_mem[] = "Running out of memory.";

char		*from = NULL, *to = NULL;
int		verbose = 0;
int		oval = 0;
float		mag = 1.0;
float		dash_mag = 1.0;
char		textfont[64] = "\\twltt ";
int		thick_width = 2;
double		tolerance = 2.0;
int		(*translate_coordinates)() = NULL;
double		ppi;
double		unitlength;
int		cur_thickness = -1;
double		dot_diameter = THINDOT;
double		ldot_diameter = THIN_LDOT;

put_msg(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
char   *format, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8;
{
	fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
	}

translate1(xp, yp)
int	*xp, *yp;
{
	*xp = *xp + 1;
	*yp = *yp + 1;
	}

translate2(xp, yp)
int	*xp, *yp;
{
	*xp = *xp + 1;
	*yp = TOP - *yp -1;
	}

get_args(argc, argv)
int	 argc;
char	*argv[];
{
	char c;

	while ((c = getopt(argc, argv, "f:l:Lm:d:ov")) != EOF)
	    switch (c) {
		case 'f':		/* set text font */
		    if (strcmp(optarg, ":")) {
			strncpy(textfont, optarg, 62);
			strcat(textfont, " ");
			}
		    else
			textfont[0] = '\0';
		    break;
		case 'l':		/* set thin/thick line threshold */
		    thick_width = atoi(optarg);
		    break;
		case 'L':
		    thick_width = 0;	/* thick lines only */
		    break;
		case 'm':
		    mag = atof(optarg);	/* set magnification */
		    break;
		case 'd':
		    dash_mag = atof(optarg);	/* set dash magnification */
		    break;
		case 'o':
		    oval = 1;	/* make circle from ovals */
		    break;
		case 'v':
		    verbose = 1;	/* verbose mode */
		    break;
		case '?':
		    fprintf(stderr, Usage);
		    exit(1);
		    break;
	    }
	if (optind < argc) from = argv[optind++];  /*  from file  */
	if (optind < argc) to   = argv[optind];  /*  to file    */
	}

main(argc, argv)
int	 argc;
char	*argv[];
{
	F_compound	objects;
	int		status;
	char		c;

	get_args(argc, argv);
	if (from != NULL  &&  freopen(from, "r", stdin) == NULL) {
	    perror(from);
	    exit(-1);
	    }
	if (to != NULL  &&  freopen(to, "w", stdout) == NULL) {
	    perror(to);
	    exit(-1);
	    }

	c = fgetc(stdin);
	ungetc(c, stdin);
	if (c == '#')
	    status = read_objects(stdin, &objects);
	else
	    status = read_1_3_objects(stdin, &objects);

	if (status != 0) {
	    if (from) read_fail_message(from, status);
	    exit(0);
	    }
	gentex_objects(&objects);
	}

gentex_objects(objects)
F_compound	*objects;
{
	int		coord_system;
	F_arc		*a;
	F_compound	*c;
	F_ellipse	*e;
	F_line		*l;
	F_spline	*s;
	F_text		*t;
	int		llx, lly, urx, ury;
	int		tmp;

	if (0 == (ppi = (double)objects->nwcorner.x)) {
	    fprintf(stderr, "Resolution is zero!! default to 80 ppi\n");
	    ppi = 80.0;
	    }
	unitlength = mag/ppi;
	coord_system = objects->nwcorner.y;
	switch (coord_system) {
	    case 1:
		translate_coordinates = translate1;
		break;
	    case 2:
		translate_coordinates = translate2;
		break;
	    default:
		fprintf(stderr, "Wrong coordinate system; cannot continue\n");
		return;
	    }
	compound_bound(objects, &llx, &lly, &urx, &ury);
	TRANS2(llx, lly, urx, ury);
	if (llx > urx) SWAP(llx, urx)
	if (lly > ury) SWAP(lly, ury)

	/* LaTeX start */
	printf("\\setlength{\\unitlength}{%.3fin}\n", round(unitlength));
	printf("\\begin{picture}(%d,%d)(%d,%d)\n",
	  urx-llx, ury-lly+15, llx, lly-10);

	for (a = objects->arcs; a != NULL; a = a->next) gentex_arc(a);
	for (c = objects->compounds; c != NULL; c = c->next) gentex_compound(c);
	for (e = objects->ellipses; e != NULL; e = e->next) gentex_ellipse(e);
	for (l = objects->lines; l != NULL; l = l->next) gentex_line(l);
	for (s = objects->splines; s != NULL; s = s->next) gentex_spline(s);
	for (t = objects->texts; t != NULL; t = t->next) gentex_text(t);

	/* LaTeX ending */
	printf("\\end{picture}\n");
	}

set_linewidth(w)
int	w;
{
	int		latex_w;

	if (w == 0) return;
	/* latex only knows thin lines or thick lines */
	latex_w = (w >= thick_width)? THICKLINES: THINLINES;
	if (latex_w != cur_thickness) {
	    cur_thickness = latex_w;
	    if (cur_thickness == THICKLINES) {
		printf("\\thicklines\n");
		dot_diameter = THICKDOT;
		ldot_diameter = THICK_LDOT;
		}
	    else {
		printf("\\thinlines\n");
		dot_diameter = THINDOT;
		ldot_diameter = THIN_LDOT;
		}
	    }
	}

gentex_compound(com)
F_compound	*com;
{
	F_arc		*a;
	F_compound	*c;
	F_ellipse	*e;
	F_line		*l;
	F_spline	*s;
	F_text		*t;

	for (a = com->arcs; a != NULL; a = a->next) gentex_arc(a);
	for (c = com->compounds; c != NULL; c = c->next) gentex_compound(c);
	for (e = com->ellipses; e != NULL; e = e->next) gentex_ellipse(e);
	for (l = com->lines; l != NULL; l = l->next) gentex_line(l);
	for (s = com->splines; s != NULL; s = s->next) gentex_spline(s);
	for (t = com->texts; t != NULL; t = t->next) gentex_text(t);
	}

gentex_line(l)
F_line	*l;
{
	F_point		*p, *q;
	int		x, y, llx, lly, urx, ury, arrow;

	if (verbose) printf("%%\n%% Fig POLYLINE object\n%%\n");

	set_linewidth(l->thickness);

	p = l->points;
	q = p->next;

	if (q == NULL) { /* A single point line */
	    x = p->x; y = p->y;
	    TRANS(x, y);
	    printf("\\put(%3d,%3d){\\circle*{%.3}}\n",
	      x, y, dot_diameter/unitlength);
	    return;
	    }

	if (l->type == T_BOX) { /* A box */
	    x = p->x; y = p->y;
	    TRANS(x, y);
	    llx = urx = x;
	    lly = ury = y;
	    while (q != NULL) {
		x = q->x; y = q->y;
		TRANS(x, y);
		if (x < llx) llx = x;
		if (y < lly) lly = y;
		if (x > urx) urx = x;
		if (y > ury) ury = y;
		q = q->next;
		}
	    put_box (llx, lly, urx, ury, l->style, l->style_val);
	    return;
	    }

	while (q != NULL) {
	    arrow = 0;
	    if (l->for_arrow  &&  q->next == NULL)
		arrow = 1;
	    if (l->back_arrow  &&  p == l->points)
		arrow = (arrow)? 2: -1;
	    single_line(p->x, p->y, q->x, q->y, arrow, l->style, l->style_val);
	    p = q;
	    q = q->next;
	    }
	}

single_line (x1, y1, x2, y2, arrow, style, val)
int	x1, y1, x2, y2, arrow, style;
float	val;
{
	int    dx, dy, sx, sy;
	double l, m, deviation;

	TRANS2(x1, y1, x2, y2);
	dx = x2-x1;
	dy = y2-y1;
	/*** compute direction vector ***/
	get_slope(dx, dy, &sx, &sy, arrow);
	/*** compute line length in x-direction ***/
	if (sx == 0) {
	    l = (double)abs(dy);
	} else {
	    m = (double)abs(sy) / (double)abs(sx);
	    l = ((double)abs(dx) + m*(double)abs(dy)) / (1.0 + m*m);
	    deviation = fabs(l-abs(dx)) + fabs(m*l-abs(dy));
	    if (deviation > tolerance)
		fprintf(stderr,
		  "Not a LaTeX slope (%d, %d), deviation %.1f pixels\n",
		  dx, dy, deviation);
	}
	l = round(l);
	/*** output letex command ***/
	switch (style) {
	    case SOLID_LINE:
		put_solidline(x1, y1, sx, sy, l, arrow);
		break;
	    case DASH_LINE:
		put_dashline(x1, y1, sx, sy, l, arrow, val);
		break;
	    case DOTTED_LINE:
		put_dotline(x1, y1, sx, sy, l, arrow, val);
		break;
	    }
	}


/*
 * draw box
 */
put_box (llx, lly, urx, ury, style, val)
int	llx, lly, urx, ury, style;
float	val;
{
	int	dlen;

	switch (style) {
	    case SOLID_LINE:
		printf("\\put(%3d,%3d){\\framebox(%d,%d){}}\n",
		  llx, lly, urx-llx, ury-lly);
		break;
	    case DASH_LINE:
		dlen = (int)(val*dash_mag + 0.5);
		printf("\\put(%3d,%3d){\\dashbox{%d}(%d,%d){}}\n",
		  llx, lly, dlen, urx-llx, ury-lly);
		break;
	    case DOTTED_LINE:
		put_dotline (llx, lly, 1, 0, (double)(urx-llx), 0, val);
		put_dotline (llx, ury, 1, 0, (double)(urx-llx), 0, val);
		put_dotline (llx, lly, 0, 1, (double)(ury-lly), 0, val);
		put_dotline (urx, lly, 0, 1, (double)(ury-lly), 0, val);
		break;
	    }
	return;
	}

/*
 * draw a solid line given latex slope
 */
put_solidline (x, y, sx, sy, l, arrow)
int	x, y, sx, sy, arrow;
double	l;
{
double	cosine;		/* cosine of line angle */
double	dx, dy;
int	x2, y2, n;

	if (sx) {
	    cosine = (double)abs(sx) / sqrt((double)(sx*sx + sy*sy));
	    x2 = (sx >= 0)? x + (int)(l + 0.5): x - (int)(l + 0.5);
	    y2 = y + (int)(((sx>=0)? l: -l)*(double)sy/(double)sx + 0.5);
	    }
	else {
	    cosine = 1.0;
	    x2 = x;
	    y2 = (sy >= 0)? y + (int)(l + 0.5): y - (int)(l + 0.5);
	    }
	if (sx == 0  ||  sy == 0  ||  (l/cosine)*unitlength >= MIN_LEN) {
	    switch (arrow) {
	    case 0:  /* simple line */
		printf("\\put(%3d,%3d){\\line(%2d,%2d)", x, y, sx,sy);
		break;
	    case 1:  /* forward arrow */
		printf("\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx,sy);
		break;
	    case -1: /* backward arrow */
		printf("\\put(%3d,%3d){\\vector(%2d,%2d)", x2, y2, -sx,-sy);
		break;
	    case 2:  /* double arrow */
		printf("\\put(%3d,%3d){\\vector(%2d,%2d){  0}}\n", x,y,-sx,-sy);
		printf("\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx, sy);
		break;
		}
	    if (l == floor(l))
		printf("{%3.0f}}\n", l);
	    else
		printf("{%7.3f}}\n", l);
	    }
	else {
	    n = 2 * (l/cosine) / (ldot_diameter/unitlength);
	    fprintf(stderr, "Line too short; will do %d dots\n", n);
	    dx = l / (double)n;
	    if (sx < 0) dx = -dx;
	    dy = dx * (double)sy / (double)sx;
	    printf("\\multiput(%3d,%3d)(%.4f,%.4f){%d}{\\circle*{%.4f}}\n",
	      x, y, dx, dy, n+1, ldot_diameter/unitlength);
	    if (arrow == 1  ||  arrow == 2)  /* forward arrow */
		printf("\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2,y2, sx,sy);
	    if (arrow == -1  ||  arrow == 2) /* backward arrow */
		printf("\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x,y, -sx,-sy);
	    }
	}

/*
 * draw a dashed line given latex slope
 */
put_dashline (x, y, sx, sy, l, arrow, val)
int	x, y, sx, sy, arrow;
double	l;
float	val;
{
double	cosine;		/* cosine of line angle */
double	nd;		/* number of dashes and gaps fitting on line */
int	n;		/* nd rounded to the nearest odd integer */
double	dl;		/* actual x-length of each dash */
double	dg;		/* actual x-length of each gap */
double	dx, dy;		/* step between dashes */
int	x2, y2;


	if (sx) {
	    cosine = (double)abs(sx) / sqrt((double)(sx*sx + sy*sy));
	    x2 = (sx >= 0)? x + (int)(l + 0.5): x - (int)(l + 0.5);
	    y2 = y + (int)(((sx>=0)? l: -l)*(double)sy/(double)sx + 0.5);
	    }
	else {
	    cosine = 1.0;
	    x2 = x;
	    y2 = (sy >= 0)? y + (int)(l + 0.5): y - (int)(l + 0.5);
	    }
	/*** compute number of dashes, length of dashes and gaps ***/
	nd = l / (val*dash_mag*cosine);
	n = (int) (rint((nd + 1.0)/2.0)*2 - 1);
	dl = l / (double)n;
	if (sx  &&  sy  &&  (dl/cosine)*unitlength < MIN_LEN) {
	    fprintf(stderr, "Dash too small; using larger dash\n");
	    dl = MIN_LEN/unitlength * cosine;
	    nd = l / dl;
	    n = (int) (rint((nd + 1.0)/2.0)*2 - 1);
	    }
	if (2*dl >= l  ||  (sx  &&  sy  &&  (l/cosine)*unitlength < MIN_LEN)) {
	    fprintf(stderr, "Dashed line too short; drawing solid line\n");
	    put_solidline (x, y, sx, sy, l, arrow);
	    return;
	    }
	dg = (l - (n/2+1)*dl) / (double)(n/2);
	if (sx) {
	    dx = dl+dg;
	    if (sx < 0) dx = -dx;
	    dy = dx * (double)sy / (double)sx;
	    }
	else {
	    dx = 0.0;
	    dy = dl+dg;
	    if (sy < 0) dy = -dy;
	    }
	/*** draw dashed line ***/
	printf("\\multiput(%3d,%3d)(%7.3f,%7.3f){%d}{\\line(%2d,%2d){%7.3f}}\n",
	    x, y, dx, dy, n/2+1, sx, sy, dl);
	/*** draw arrow heads ***/
	if (arrow == 1  ||  arrow == 2)
	    printf("\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy);
	if (arrow == -1  ||  arrow == 2)
	    printf("\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy);
	}

/*
 * draw a dotted line given latex slope
 */
put_dotline (x, y, sx, sy, l, arrow, val)
int	x, y, sx, sy, arrow;
double	l;
float	val;
{
double	cosine;		/* cosine of line angle */
double	nd;		/* number of dots fitting on line */
int	n;		/* nd rounded to the nearest integer */
double	dx, dy;		/* step between dashes */
int	x2, y2;


	cosine = (sx)? (double)abs(sx) / sqrt((double)(sx*sx + sy*sy)): 1.0;
	/*** compute step width ***/
	nd = l / (3*val*cosine);
	n = rint(nd);
	dx = l / (double)n;
	if (sx) {
	    dx = l / (double)n;
	    if (sx < 0) dx = -dx;
	    dy = dx * (double)sy / (double)sx;
	    }
	else {
	    dx = 0.0;
	    dy = l / (double)n;
	    if (sy < 0) dy = -dy;
	    }
	/*** draw arrow heads ***/
	if (arrow == 1  ||  arrow == 2) {
	    /* forward arrow */
	    if (sx) {
		x2 = (sx >= 0)? x + (int)(l + 0.5): x - (int)(l + 0.5);
	    y2 = y + (int)(((sx>=0)? l: -l)*(double)sy/(double)sx + 0.5);
		}
	    else {
		x2 = x;
		y2 = (sy >= 0)? y + (int)(l + 0.5): y - (int)(l + 0.5);
		}
	    printf("\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy);
	    n--;
	    }
	if (arrow == -1  ||  arrow == 2) {
	    printf("\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy);
	    x = x + dx + 0.5;
	    y = y + dy + 0.5;
	    n--;
	    }
	/*** draw dotted line ***/
	printf("\\multiput(%3d,%3d)(%7.3f,%7.3f){%d}{\\circle*{%7.3f}}\n",
	    x, y, dx, dy, n+1, dot_diameter/unitlength);
	}


gentex_spline(s)
F_spline	*s;
{
	fprintf(stderr, "Can't generate spline; omitting object\n");
	}

gentex_ellipse(e)
F_ellipse	*e;
{
	int  x, y, d, dx, dy;

	if (verbose) printf("%%\n%% Fig ELLIPSE\n%%\n");

	set_linewidth(e->thickness);
	switch (e->style) {
	    case SOLID_LINE:
		break;
	    case DASH_LINE:
		fprintf(stderr, "Dashed circles and elipses not supported\n");
		break;
	    case DOTTED_LINE:
		fprintf(stderr, "Dotted circles and elipses not supported\n");
		break;
		}

	x = e->center.x;
	y = e->center.y;
	TRANS(x, y);
	if (e->radiuses.x == e->radiuses.y) {
	    d = 2 * e->radiuses.x;
	    if (oval)
		printf("\\put(%3d,%3d){\\oval(%d,%d)}\n", x, y, d, d);
	    else
		printf("\\put(%3d,%3d){\\circle{%d}}\n", x, y, d);
	    }
	else {
	    fprintf(stderr,
	      "Can't generate ellipse; approximating by oval\n");
	    dx = 2 * e->radiuses.x;
	    dy = 2 * e->radiuses.y;
		printf("\\put(%3d,%3d){\\oval(%d,%d)}\n", x, y, dx, dy);
	    }
	}

gentex_text(t)
F_text	*t;
{
	int    x, y;

	if (verbose) printf("%%\n%% Fig TEXT object\n%%\n");

	x = t->base_x;
	y = t->base_y;   /* + font_size ? XXX */
	TRANS(x, y);
	printf("\\put(%3d,%3d){%s%s}\n", x, y, textfont, t->cstring);
	}

gentex_arc(a)
F_arc	*a;
{
	fprintf(stderr, "Can't generate arc; omitting object\n");
	}