plot(3) library for HPGL plotters
David Trueman
david at utzoo.UUCP
Fri Oct 26 13:25:11 AEST 1984
Following is a shell archive of the source for a V7 plot(3) library for
Hewlett-Packard plotters which speak HPGL (HP Graphics Language). We have
now had fairly extensive experience using this software with our HP7470
2-pen plotter.
We have had enough requests for this software that we felt it was worth
posting to the net. The package was written jointly by myself and
Henry Spencer. While the package has been fairly well-exercised, should
any bugs show up, please let us know.
# This is a shell archive. Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file". (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# Makefile arc.c box.c circle.c close.c cont.c dot.c erase.c hpglchord.c label.c line.c linmod.c move.c onoff.c open.c point.c space.c
echo x - Makefile
cat > "Makefile" << '//E*O*F Makefile//'
# Define CIRELBUG if the plotter has the firmware bug that puts it into
# relative-coordinate mode after a circle or an arc.
CFLAGS=-O -DCIRELBUG
all: libhpgl.a
libhpgl.a: arc.o box.o circle.o close.o cont.o dot.o erase.o label.o line.o \
linmod.o move.o open.o point.o space.o onoff.o hpglchord.o
ar rc libhpgl.a *.o
clean:
rm -f *.o libhpgl.a
mv: all
mv libhpgl.a ..
//E*O*F Makefile//
echo x - arc.c
cat > "arc.c" << '//E*O*F arc.c//'
/* @(#)arc.c 1.5 of 4 Aug 84 */
#include <math.h>
#define sq(x) ((double)(x) * (double)(x))
extern int hpglchord();
arc(xc, yc, xs, ys, xe, ye)
int xc, yc; /* center of arc */
int xs, ys; /* starting point */
int xe, ye; /* end point */
{
double as, ae;
double angle;
double rs;
double pi = 3.14159265358979323846;
as = atan2((double)(ys - yc), (double)(xs - xc)) * (180/pi);
ae = atan2((double)(ye - yc), (double)(xe - xc)) * (180/pi);
angle = ae - as;
if (angle < 0)
angle += 360;
rs = sqrt(sq(xs - xc) + sq(ys - yc));
move(xs, ys);
on();
printf("PD;");
printf("AA %d,%d,%.2f,%d;", xc, yc, angle, hpglchord((int)rs));
#ifdef CIRELBUG
printf("PA;"); /* back into absolute mode -- firmware bug */
#endif
off();
}
//E*O*F arc.c//
echo x - box.c
cat > "box.c" << '//E*O*F box.c//'
box(x0, y0, x1, y1)
int x0, y0; /* one corner */
int x1, y1; /* other corner */
{
move(x0, y0);
cont(x0, y1);
cont(x1, y1);
cont(x1, y0);
cont(x0, y0);
move(x1, y1);
}
//E*O*F box.c//
echo x - circle.c
cat > "circle.c" << '//E*O*F circle.c//'
/* @(#)circle.c 1.4 of 31 July 84 */
extern int hpglchord();
circle(x, y, r)
int x, y; /* center */
int r; /* radius */
{
move(x, y);
on();
printf("CI %d,%d;", r, hpglchord(r));
#ifdef CIRELBUG
printf("PA;"); /* back into absolute mode -- firmware bug */
#endif
off();
}
//E*O*F circle.c//
echo x - close.c
cat > "close.c" << '//E*O*F close.c//'
/* @(#)close.c 1.2 of 26 July 84 */
#include <stdio.h>
closepl()
{
on();
printf("PU;"); /* pen up */
printf("SP;"); /* put pen away */
off();
fflush(stdout);
}
//E*O*F close.c//
echo x - cont.c
cat > "cont.c" << '//E*O*F cont.c//'
cont(x, y)
int x, y; /* point to move to */
{
on();
printf("PD %d,%d;", x, y);
off();
}
//E*O*F cont.c//
echo x - dot.c
cat > "dot.c" << '//E*O*F dot.c//'
dot()
{
on();
off();
}
//E*O*F dot.c//
echo x - erase.c
cat > "erase.c" << '//E*O*F erase.c//'
erase()
{
on();
off();
}
//E*O*F erase.c//
echo x - hpglchord.c
cat > "hpglchord.c" << '//E*O*F hpglchord.c//'
/* @(#)hpglchord.c 1.2 of 2 Oct 84 */
extern int hpglsize; /* Size of coordinate space. */
#define MINCHA 5 /* Minimum chord angle. */
/*
* hpglchord - compute a suitable chord angle for circle/arc
*/
int
hpglchord(r)
int r; /* radius */
{
int changle;
/*
* The following calculation is essentially just chord/radius,
* where chord is the desired chord size (10 machine units).
* This yields an (approximate) result in radians, which is then
* multiplied by (360/2pi), about 57, to yield degrees. The
* messy part is that the desired chord needs to be expressed in
* user units, and care is needed to avoid overflow and underflow
* in integer arithmetic. A 10-unit chord is 1/720 of the machine
* coordinate space, so hpglsize/720 would be the chord. Shuffling,
* we have (57/720)*(hpglsize/r). (1/13) is close to (57/720)
* and involves much less chance of over/underflow problems.
*
* Actually, the machine coordinate space isn't always (in fact,
* ever!) 7200x7200 any more, but the numbers still come out close
* enough that it's not worth worrying about.
*
* After all that, we enforce a minimum chord for speed. This
* pretty much eliminates residual underflow worries.
*/
changle = (hpglsize/r)/13;
if (changle < MINCHA)
changle = MINCHA;
return(changle);
}
//E*O*F hpglchord.c//
echo x - label.c
cat > "label.c" << '//E*O*F label.c//'
/* @(#)label.c 1.3 of 26 July 84 */
label(s)
char *s;
{
on();
printf("CP -0.3333,-0.25;"); /* offset to center first char */
printf("LB%s%c", s, 03);
off();
}
//E*O*F label.c//
echo x - line.c
cat > "line.c" << '//E*O*F line.c//'
line(x0,y0,x1,y1)
int x0, y0; /* starting point */
int x1, y1; /* end point */
{
move(x0,y0);
cont(x1,y1);
}
//E*O*F line.c//
echo x - linmod.c
cat > "linmod.c" << '//E*O*F linmod.c//'
/* @(#)linmod.c 1.2 of 9 Aug 84 */
#define STREQ(x, y) (strcmp((x), (y)) == 0)
linemod(s)
char *s;
{
char *pattern;
if (STREQ(s, "dotted"))
pattern = "1,1";
else if (STREQ(s, "solid"))
pattern = "";
else if (STREQ(s, "longdashed"))
pattern = "3,1";
else if (STREQ(s, "shortdashed"))
pattern = "2,1";
else if (STREQ(s, "dotdashed"))
pattern = "4,2";
on();
printf("LT %s;", pattern);
off();
}
//E*O*F linmod.c//
echo x - move.c
cat > "move.c" << '//E*O*F move.c//'
move(x,y)
int x, y; /* point to move to */
{
on();
printf("PU %d,%d;", x, y);
off();
}
//E*O*F move.c//
echo x - onoff.c
cat > "onoff.c" << '//E*O*F onoff.c//'
on()
{
printf("\033.Y"); /* wakeup plotter */
}
off()
{
printf("\033.Z"); /* turn plotter off again */
}
//E*O*F onoff.c//
echo x - open.c
cat > "open.c" << '//E*O*F open.c//'
/* @(#)open.c 1.5 of 2 Oct 84 */
openpl()
{
on();
printf("\033.I81;;17:"); /* set threshold for sending XOFF to 81
* and set XON character to DC1
*/
printf("\033.N;19:"); /* set XOFF character to DC3 */
printf("IN;"); /* initialize everything */
printf("SP 1;"); /* select left pen */
printf("VS 20;"); /* reduce pen velocity */
printf("SI 0.1368,0.27;"); /* char size absolute, shrunk a bit */
off();
}
//E*O*F open.c//
echo x - point.c
cat > "point.c" << '//E*O*F point.c//'
point(xi,yi){
move(xi,yi);
cont(xi,yi);
}
//E*O*F point.c//
echo x - space.c
cat > "space.c" << '//E*O*F space.c//'
/* @(#)space.c 1.3 of 2 Oct 84 */
#define PLOTX 10300 /* How wide is plotter in physical units. */
#define PLOTY 7650 /* How high is plotter in physical units. */
int hpglsize = 7200; /* Size of coordinate space, for chord calculations. */
space(x0,y0,x1,y1)
int x0, y0; /* lower left corner */
int x1, y1; /* upper right corner */
{
int absy;
long aspect; /* In thousandths. */
int llx, lly, urx, ury;
/*
* compute physical plot area: use as much of the paper as
* possible while preserving the aspect ratio of the user space.
*/
aspect = (1000L * abs(x1 - x0)) / abs(y1 - y0);
if (aspect > (1000L * PLOTX) / PLOTY) { /* Wide and squat. */
llx = 0;
urx = PLOTX;
lly = (PLOTY - (int)((1000L * PLOTX) / aspect)) / 2;
ury = lly + (int)((1000L * PLOTX) / aspect);
} else { /* Limited by height, not width. */
lly = 0;
ury = PLOTY;
llx = (PLOTX - (int)((PLOTY * aspect)/1000)) / 2;
urx = llx + (int)((PLOTY * aspect)/1000);
}
on();
printf("IP %d,%d,%d,%d;", llx, lly, urx, ury); /* set plot area */
printf("SC %d,%d,%d,%d;", x0, x1, y0, y1); /* set scaling */
off();
hpglsize = abs(x1 - x0);
absy = abs(y1 - y0);
if (absy > hpglsize)
hpglsize = absy;
}
//E*O*F space.c//
exit 0
--
David Trueman @ U of Toronto Zoology
{allegra,ihnp4,linus,decvax}!utzoo!david
More information about the Comp.sources.unix
mailing list