|
|
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: 15112 (0x3b08)
Types: TextFile
Names: »fig2latex.c«
└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
└─⟦this⟧ »./tex82/TeXgraphics/fig2latex/fig2latex.c«
/*
* 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");
}