edf@ROCKEFELLER.ARPA (David MacKenzie) (07/16/88)
Posting-number: Volume 3, Issue 88 Submitted-by: "David MacKenzie" <edf@ROCKEFELLER.ARPA> Archive-name: hpglplot/Part2 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 2 (of 3)." # Contents: end_ref.c ep_map.c hpglfix.c hpglplot.doc ib_map.c # lj_map.c step.c # Wrapped by dave@zedfdc on Fri Jul 8 20:50:51 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'end_ref.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'end_ref.c'\" else echo shar: Extracting \"'end_ref.c'\" \(3894 characters\) sed "s/^X//" >'end_ref.c' <<'END_OF_FILE' X/* X * end_ref.c X * X * Copyright (c) 1988 Environmental Defense Fund, Inc. X */ X X#include <stdio.h> X#include <math.h> X#include "const.h" X#include "vars.h" X#include "fillcnst.h" X#include "fillvars.h" X#ifdef TESTVER X#include "dbgvars.h" X#endif X X#ifdef __STDC__ Xint Xend_ref(POINT A, POINT B, POINT C); Xint Xchoose_step(FPOINT *f_pt_s1p, double chg_x_s1, double chg_y_s1, X FPOINT *f_pt_s2p, double chg_x_s2, double chg_y_s2, X int status, int limit); X X#endif X X/* =========================== end_ref() =================================== */ Xend_ref(C, A, B) X POINT C, X A, X B; X{ X /* endpt of hatch segment on CB, ... etc: coordinates are doubles */ X FPOINT f_pt_CB, X f_pt_CA, X f_pt_AB; X X /* endpt of hatch segment on CB, ... etc: coordinates are integers */ X POINT endpt_CB, X endpt_CA, X endpt_AB; X double xdiff, X ydiff; X int limit; X X#ifdef TESTVER X if (debug4) { X fprintf(errfp, "A: ( %d, %d ); ", A.x, A.y); X fprintf(errfp, "B: ( %d, %d ); ", B.x, B.y); X fprintf(errfp, "C: ( %d, %d )\n", C.x, C.y); X } X#endif X X /* assign 1st set of hatch segment endpoints (along 1st side) */ X endpt_CB = C; X f_pt_CB.xx = (double) endpt_CB.x; X f_pt_CB.yy = (double) endpt_CB.y; X if (C_A == PARL) { X endpt_CA = A; X f_pt_CA.xx = (double) endpt_CA.x; X f_pt_CA.yy = (double) endpt_CA.y; X } else { X endpt_CA = C; X f_pt_CA.xx = (double) endpt_CA.x; X f_pt_CA.yy = (double) endpt_CA.y; X } X X /* plot hatch lines up to limiting point along 1st side of triangle */ X limit = ((C_A == VERT) ? A.y : A.x); X#ifdef TESTVER X if (debug4) X fprintf(errfp, "\nlimit: %d\n", limit); X if (debug1c) { X fprintf(stderr, "To: choose_step() - side 1;\n"); X } X if (debug1f) { X fprintf(errfp, "\nTo: choose_step() - side 1;\n"); X } X#endif X choose_step(&f_pt_CA, chg_x_CA, chg_y_CA, X &f_pt_CB, chg_x_CB, chg_y_CB, X C_A, limit); X X X /* do second side ------------------------- */ X if (A_B == PARL) { X#ifdef TESTVER X if (debug4) { X fprintf(errfp, "\nA_B parallel to hatch lines, side 2 skipped\n"); X } X#endif X } else { /* A_B not parallel to hatch lines */ X X /* assign next set of hatch segment endpoints (along 2nd side, AB) */ X /* fprintf( stderr, "\nStart side 2 -- chg_x_CB: %f\n", chg_x_CB ); */ X if (chg_x_CB == 0.0) { X ydiff = chg_y_AB * ((double) B.y - f_pt_CB.yy) / chg_y_CB; X if (chg_y_AB == 0.0) { X xdiff = (f_pt_CB.yy - (double) B.y) / tan(hatch_rads); X } else { X xdiff = ydiff * chg_x_AB / chg_y_AB; X } X } else { X xdiff = ((double) B.x - f_pt_CB.xx) * chg_x_AB / chg_x_CB; X if (chg_y_CB == 0.0) { X if (chg_x_AB == 0.0) { X ydiff = -(B.x - f_pt_CB.xx) * tan(hatch_rads); X#ifdef TESTVER X if (debug4) { X fprintf(errfp, "\nCase A - ydiff: %6.1f\n", ydiff); X } X#endif X } else { X ydiff = xdiff * (B.y - A.y) / (B.x - A.x); X#ifdef TESTVER X if (debug4) { X fprintf(errfp, "\nCase B - ydiff: %6.1f\n", ydiff); X } X#endif X } X } else { X ydiff = ((double) B.y - f_pt_CB.yy) * chg_y_AB / chg_y_CB; X#ifdef TESTVER X if (debug4) { X fprintf(errfp, "\nCase C - ydiff: %6.1f\n", ydiff); X } X#endif X } X } X f_pt_AB.xx = (double) B.x - xdiff; X f_pt_AB.yy = (double) B.y - ydiff; X#ifdef TESTVER X if (debug4) { X fprintf(errfp, "xdiff: %6.0f; ydiff: %6.0f\n", xdiff, ydiff); X fprintf(errfp, X "f_pt_CB: ( %6.0f, %6.0f ); f_pt_AB: ( %6.0f, %6.0f )\n", X f_pt_CB.xx, f_pt_CB.yy, f_pt_AB.xx, f_pt_AB.yy); X } X#endif X X /* plot hatch lines up to limiting point along 2nd side of triangle */ X limit = ((C_B == VERT) ? B.y : B.x); X#ifdef TESTVER X if (debug1c) { X fprintf(stderr, "To: choose_step() - side 2;\n"); X } X if (debug1f) { X fprintf(errfp, "\nTo: choose_step() - side 2;\n"); X } X#endif X choose_step(&f_pt_CB, chg_x_CB, chg_y_CB, X &f_pt_AB, chg_x_AB, chg_y_AB, X C_B, limit); X } X} END_OF_FILE if test 3894 -ne `wc -c <'end_ref.c'`; then echo shar: \"'end_ref.c'\" unpacked with wrong size! fi # end of 'end_ref.c' fi if test -f 'ep_map.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ep_map.c'\" else echo shar: Extracting \"'ep_map.c'\" \(5595 characters\) sed "s/^X//" >'ep_map.c' <<'END_OF_FILE' X/* X * ep_map.c X * X * Copyright (c) 1988 Environmental Defense Fund, Inc. X */ X X#include <stdio.h> X#include "const.h" X#include "fillcnst.h" X X#ifdef TESTVER X#include <signal.h> X#include "dbgvars.h" X#endif X X/* Constants */ X/* SCALEX = 10.15 (inches) / 10366 (plotter units) * 180 (dots/inch) */ X#define SCALEX 0.1762492 X/* SCALEY = 7.8 (inches) / 7963 (plotter units) * 180 (dots/inch) */ X#define SCALEY 0.1763154 X X#define YLIM 1404 X#define XLIM 231 X X#define ROUNDER 0.0 X X#ifdef TESTVER X#define PUT_BIT(x, y) map[(tempindex = (tempy = y) + YLIM * ((tempx = x) >> 3))] |= BITS[x & 7]; X#else X#define PUT_BIT(x, y) map[y + YLIM * (x >> 3)] |= BITS[x & 7] X#endif X X#define ABS(x) ( (x) > 0.0 ? (x) : -(x) ) X Xstatic char BITS[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; X X/* move bit map to maps.c for combined printer version --- */ X/* char map[XLIM * YLIM]; */ Xextern char map[]; X X#ifdef TESTVER Xstatic int tempindex, X tempx, X tempy; Xstatic POINT tempp1, X tempp2; X Xep_catch() X{ X fprintf(stderr, "Segmentation violation\n"); X fprintf(stderr, "tempindex = %d x = %d y = %d p1 = %d,%d p2 = %d,%d\n", tempindex, tempx, tempy, tempp1.x, tempp1.y, tempp2.x, tempp2.y); X ep_dump_map(FALSE); X exit(1); X} X Xepcatchi() X{ X ep_dump_map(FALSE); X exit(1); X} X X#endif X X Xep_put_seg(p1, p2) X POINT p1, X p2; X{ X double diffx, X diffy, X change_ratio; X register int x, X y; X register int inc; X X#ifdef TESTVER X if (debug2 || debug2x) { X fprintf(errfp, "p1 ( %d, %d ); p2 ( %d, %d )\n", X p1.x, p1.y, p2.x, p2.y); X } X#if 0 X signal(SIGSEGV, ep_catch); X signal(SIGINT, epcatchi); X#endif X tempp1 = p1; X tempp2 = p2; X#endif X X p1.x = SCALEX * (double) p1.x + ROUNDER; X p2.x = SCALEX * (double) p2.x + ROUNDER; X p1.y = SCALEY * (double) p1.y + ROUNDER; X p2.y = SCALEY * (double) p2.y + ROUNDER; X X diffx = p2.x - p1.x; X diffy = p2.y - p1.y; X X if (diffx != 0.0 && diffy != 0.0) { X if (ABS(diffx) > ABS(diffy)) { X inc = (diffx < 0) ? -1 : 1; X change_ratio = diffy / diffx; X for (x = p1.x; x != p2.x; x += inc) { X y = (x - p1.x) * change_ratio + p1.y + ROUNDER; X PUT_BIT(x, y); X } X PUT_BIT(p2.x, p2.y); X } else { X inc = (diffy < 0) ? -1 : 1; X change_ratio = diffx / diffy; X for (y = p1.y; y != p2.y; y += inc) { X x = (y - p1.y) * change_ratio + p1.x + ROUNDER; X PUT_BIT(x, y); X } X PUT_BIT(p2.x, p2.y); X } X } else { X if (diffx) { /* horizontal line */ X y = p1.y; X inc = (diffx < 0) ? -1 : 1; X for (x = p1.x; x != p2.x; x += inc) { X PUT_BIT(x, y); X } X PUT_BIT(p2.x, y); X } else { X x = p1.x; X inc = (diffy < 0) ? -1 : 1; X for (y = p1.y; y != p2.y; y += inc) { X PUT_BIT(x, y); X } X PUT_BIT(x, p2.y); X } X } X} X X X/* LEFT_CUTOFF is the number of dot rows along left edge of page to skip over. X * shifts image to the left by that many dot rows on the hardcopy page */ X#define LEFT_CUTOFF 72 X Xep_dump_map(to_printer) X int to_printer; X{ X register int k; X int map_max = XLIM * YLIM; X int i, X j; X char hdr[5]; X register char *pm0, X *pm1, X *pm2, X *pb; X char buf[180]; X int non_blank; X short int lim; X X#ifndef TESTVER X to_printer = TRUE; X#endif X X if (to_printer) { X hdr[0] = ESC; X hdr[1] = '3'; X hdr[2] = 24; /* Spacing at 24/180 inch per line */ X write(1, hdr, 3); X hdr[1] = '*'; X hdr[2] = 39; /* Triple density, 24 pins */ X hdr[3] = (YLIM - LEFT_CUTOFF) & 0x0ff; X hdr[4] = ((YLIM - LEFT_CUTOFF) >> 8) & 0x0ff; X for (k = 0; k < map_max; k += 3 * YLIM) { X write(1, hdr, 5); X pm0 = &map[k + LEFT_CUTOFF]; X pm1 = &map[k + YLIM + LEFT_CUTOFF]; X pm2 = &map[k + (2 * YLIM) + LEFT_CUTOFF]; X lim = YLIM - LEFT_CUTOFF; X while ((lim -= 60) >= 0) { X pb = buf; X for (i = 0; i < 60; i++) { X *pb++ = *pm0++; X *pb++ = *pm1++; X *pb++ = *pm2++; X } X write(1, buf, 180); X fflush(stdout); X } X X if (lim < 0) X for (lim += 60; lim > 0; lim--) { X pb = buf; X *pb++ = *pm0++; X *pb++ = *pm1++; X *pb++ = *pm2++; X write(1, buf, 3); X fflush(stdout); X } X write(1, "\n\r", 2);/* LF and CR to end line */ X } X hdr[0] = '\f'; /* Initialize the printer */ X write(1, hdr, 1); X fflush(stdout); X hdr[0] = ESC; /* Initialize the printer */ X hdr[1] = '@'; X write(1, hdr, 2); X fflush(stdout); X#ifdef TESTVER X fclose(errfp); X#endif X X } X#ifdef TESTVER X else { X FILE *tty, X *ttyout; X int dump_start, X dump_stop; X X if ((tty = fopen(TTY, "r")) == NULL) { X perror(TTY); X exit(10); X } X if ((ttyout = fopen(TTY, "w")) == NULL) { X perror(TTY); X exit(10); X } X fprintf(ttyout, "Enter start bit:"); X fflush(ttyout); X fscanf(tty, "%d", &dump_start); X dump_stop = dump_start + 79; X non_blank = 0; X pb = buf; X for (k = 0; k < XLIM * YLIM; k += YLIM) { X for (i = 0; i < 8; i++) { X for (j = k + dump_start; j < k + dump_stop; j++) { X if (map[j] & BITS[i]) { X sprintf(pb, "."); X non_blank = 1; X } else { X sprintf(pb, " "); X } X pb++; X } X if (non_blank) { X sprintf(pb, "\n\000"); X printf("%s", buf); X } X non_blank = 0; X pb = buf; X } X } X } X#endif X X} X X Xep_init_map() X{ X register int k; X int map_max = XLIM * YLIM; X register char *mp; X X#ifdef TRUESOLID X extern double PUs_per_dot; /* declared in file filltype.c */ X X PUs_per_dot = 1.0 / SCALEX; /* used by fix_fill() in file filltype.c */ X#endif X X mp = map; X for (k = 0; k < map_max; k++) { X *mp++ = 0; X } X} END_OF_FILE if test 5595 -ne `wc -c <'ep_map.c'`; then echo shar: \"'ep_map.c'\" unpacked with wrong size! fi # end of 'ep_map.c' fi if test -f 'hpglfix.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hpglfix.c'\" else echo shar: Extracting \"'hpglfix.c'\" \(7097 characters\) sed "s/^X//" >'hpglfix.c' <<'END_OF_FILE' X/* X * hpglfix X * X * Copyright (c) 1988 Environmental Defense Fund, Inc. X * X * For use with HPGL files generated by the 20/20 spreadsheet. X * Takes HPGL input file from stdin and writes fixed HPGL file to stdout. X * X * Currently fixes two problems: piecharts and multi-line line charts. X * X * A 20/20 rounding error bug generates HPGL pie charts whose sector angles X * may add up to less than 360 degrees. The current solution is to use the X * starting angles for the sectors, and re-compute the sweep angles based on X * the values of the adjacent start angles. This does NOT necessarily correct X * the rounding errors, which are present in both the starting angles and the X * sweep angles, but it produces a good looking graph, with angles off by no X * more than 1 degree. This process is duplicated for both the EW and WG X * commands. EW = 'edge wedge' -- outline a pie sector. WG = 'wedge' -- fill X * a pie sector. X * X * A 20/20 bug generates HPGL multi-line graphs with the last point on one line X * connected to the 1st point of the next line. The current solution is to X * insert a PU (pen up) command after each occurrence of an LT (line type) X * command. This may need to be revised. X * X * Usage: hpglfix < hpglfile | hpglplot X */ X X#include <stdio.h> X X#define FILEMAX 20000 /* max hpgl filesize that can be processed */ X#define SECTORMAX 200 /* max # of pie sectors that can be processed */ X#define EW_MARKER 23 X#define WG_MARKER 24 X#define INFILE 0 X#define ANGLES 1 X Xchar nextchar(); Xchar c; Xchar hpgl[FILEMAX]; /* ram storage for hpgl file */ Xint offset; /* offset from start of hpgl[] */ Xint is_piechart = 0; Xint EW_start[SECTORMAX], X EW_sweep[SECTORMAX]; /* start and sweep angles */ Xint WG_start[SECTORMAX], X WG_sweep[SECTORMAX]; /* start and sweep angles */ Xint EW_cnt; /* count of number of pie sectors processed */ Xint WG_cnt; /* count of number of pie sectors processed */ Xint EW_sweep_sum = 0; /* sum of sweep angles processed */ Xint WG_sweep_sum = 0; /* sum of sweep angles processed */ X X X/* ============================ main() ============================ */ Xmain() X{ X input(); X if (is_piechart) { X piefix(EW_start, EW_sweep, EW_cnt, EW_sweep_sum); X piefix(WG_start, WG_sweep, WG_cnt, WG_sweep_sum); X } X output(); X} X X X/* ============================ input() ============================ */ Xinput() X{ X char label_terminator = 3; X X EW_cnt = 0; X WG_cnt = 0; X offset = 0; X X while ((c = nextchar()) != EOF) { /* Read from stdin until EOF */ X switch (c) { X case 'D': X if ((c = nextchar()) == 'T') { X label_terminator = nextchar(); X } X break; X case 'L': X c = nextchar(); X if (c == 'B') { /* skip over chars in labels */ X while (nextchar() != label_terminator); X } else { X if (c == 'T') { X linefix(); X } X } X break; X case 'E': X if ((c = nextchar()) == 'W') { X prep_pie(EW_start, EW_sweep, &EW_cnt, X EW_MARKER, &EW_sweep_sum); X } X break; X case 'W': X if ((c = nextchar()) == 'G') { X prep_pie(WG_start, WG_sweep, &WG_cnt, X WG_MARKER, &WG_sweep_sum); X } X break; X } X } X check(INFILE, offset); X *(hpgl + offset) = NULL; X} X X X/* ============================ nextchar() ============================ */ X/* X * read next char from stdin, check to see that there is room for it in X * array hpgl[], and if so store it in hpgl[] X */ X Xchar Xnextchar() X{ X char ch; X X ch = getchar(); X check(INFILE, offset); X *(hpgl + offset++) = ch; /* put ch in hpgl[] */ X return ch; X} X X X/* ============================ prep_pie() ========================= */ Xprep_pie(start, sweep, cntp, marker, sum_p) X int start[], X sweep[], X *sum_p; X int *cntp; X char marker; X{ X int cnt; X X cnt = *cntp; X is_piechart = 1; X while ((c = nextchar()) != ','); /* put radius & ',' in hpgl[] */ X X /* X * on output, marker will be replaced by corrected start_angle, the X * intervening ',', and the corrected sweep_angle X */ X check(INFILE, offset); X *(hpgl + offset++) = marker; X X check(ANGLES, cnt); X scanf("%d,%d", &start[cnt], &sweep[cnt]); X *sum_p += sweep[cnt]; X (*cntp)++; X} X X X/* ============================ linefix() ============================ */ Xlinefix() X{ X while ((c = nextchar()) != ';'); /* put LT params & ';' in hpgl[] */ X check(INFILE, offset + 3); X *(hpgl + offset++) = 'P'; /* insert the PU command */ X *(hpgl + offset++) = 'U'; X *(hpgl + offset++) = ';'; X} X X X/* ============================ check() ============================ */ X/* X * exit with error msg if array for storage of input file or angle arrays X * are about to overflow. X */ X Xcheck(type, size) X int type, X size; X{ X if (type == INFILE) { X if (size >= FILEMAX) { X fprintf(stderr, X "Hpglfix fatal error. Input file exceeds %d bytes.\n", FILEMAX); X exit(1); X } X } else { X if (size >= SECTORMAX) { X fprintf(stderr, X "Hpglfix fatal error. Number of pie sectors exceeds %d.\n", X SECTORMAX); X exit(1); X } X } X} X X X/* ============================ piefix() ============================ */ Xpiefix(start, sweep, cnt, sweep_sum) X int start[], X sweep[], X cnt, X sweep_sum; X{ X int i; X int max_chg = 0; X X if (sweep_sum > 380) { X fprintf(stderr, "Hpglfix warning: "); X fprintf(stderr, X "More than one pie, or input file error. No fix was made.\n"); X } else { X if (start[cnt - 1] == 89) { X start[cnt - 1] = 90; X max_chg = 1; X } X sweep[0] = new_sweep(cnt - 1, 0, &max_chg, start, sweep); X for (i = 1; i < cnt; i++) { X sweep[i] = new_sweep(i - 1, i, &max_chg, start, sweep); X } X X if (max_chg > 1) { X fprintf(stderr, "Hpglfix warning: "); X fprintf(stderr, X "At least one angle of pie was changed by %d degrees.\n", X max_chg); X } X } X} X X X/* ======================== new_sweep() ===================== */ X/* X * return new value for current sweep angle, based on prev start angle and X * current start angle. Reset max_chg if it increases. max_chg is the X * largest change made to any sweep angle X */ X Xint Xnew_sweep(prev, curr, maxchg_p, start, sweep) X int prev, X curr, X *maxchg_p; X int start[], X sweep[]; X{ X int sw_angle, X change; X X if (start[prev] >= start[curr]) { X sw_angle = start[prev] - start[curr]; X } else { X sw_angle = (start[prev] + 360) - start[curr]; X } X change = abs(sw_angle - sweep[curr]); X if (change > *maxchg_p) X *maxchg_p = change; X return sw_angle; X} X X X/* ============================ output() ============================ */ Xoutput() X{ X char c; X char *hp; X X hp = hpgl; X EW_cnt = 0; X WG_cnt = 0; X X while ((c = *hp++) != NULL) { X if (c == EW_MARKER) { X printf("%d,%d", EW_start[EW_cnt], EW_sweep[EW_cnt]); X EW_cnt++; X } else if (c == WG_MARKER) { X printf("%d,%d", WG_start[WG_cnt], WG_sweep[WG_cnt]); X WG_cnt++; X } else { X putchar(c); X } X } X putchar(NULL); X} END_OF_FILE if test 7097 -ne `wc -c <'hpglfix.c'`; then echo shar: \"'hpglfix.c'\" unpacked with wrong size! fi # end of 'hpglfix.c' fi if test -f 'hpglplot.doc' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hpglplot.doc'\" else echo shar: Extracting \"'hpglplot.doc'\" \(9035 characters\) sed "s/^X//" >'hpglplot.doc' <<'END_OF_FILE' XHPGLPLOT X XAl Chase X XCopyright (c) 1988 Environmental Defense Fund, Inc. X X XHpglplot is a filter to read HPGL commands (Hewlett-Packard Graphics XLanguage, used by HP7475A 6-pen plotter, among others) and produce bit Xmap graphics commands for various printers. X XAuthors: X Mel Brooks X (415) 530-0300 X Al Chase X (916) 273-7047 X David MacKenzie X (202) 387-3500 X XCOMMAND LINE OPTIONS X X-e produce output for Epson LQ-1500 X-i produce output for IBM Proprinter X-l produce output for HP LaserJet+ X-n disable area fill routines (bug-prone) X X * * * * * * * * * * * * * * * * * * * X XThe following information is intended to ease the task of modifying the Xcode of the hpglplot program. X X XPREPROCESSOR CONSTANTS X XTESTVER enables lines of code used for debugging. The test version Xmakes a wealth of debugging output available, and does some range Xchecking to prevent setting bits which are outside the bounds of the Xbit map. X XTRUESOLID enables true solid fill versus a triple cross- hatch Xsubstitute for solid fill. See more below. X XIn ep_map.c, LEFT_CUTOFF controls the displacement of the graphics Ximage to the left on the Epson hardcopy. There are 180 dots/in, so a Xvalue of 180 for LEFT_CUTOFF will displace the image 1 inch to the left Xon the paper. Adjust the value of LEFT_CUTOFF to suit. X X XPRINTERS X XHpglplot can produce output for the HP LaserJet+, the Epson LQ-1500, Xand the IBM Proprinter. In the production version, use a command line Xflag -l for the LaserJet, -e for the Epson, or -i for the IBM XProprinter. In the test version (#define TESTVER), use flag -e for Xoutput to the Epson, -i for output to an IBM Proprinter, and no flag Xfor output to the screen. Screen output was created by Mel Brooks, the Xinitial programmer of hpglplot. I haven't succeeded in getting useful Xinformation from it. The test version will not output to the LaserJet. X X XINTERNAL CONTROL OF MULTIPLE PRINTERS X XThe original function map_bits() is replaced with maps(), ep_map(), Xlj_map(), and ib_map(). maps() dispatches map-related function calls Xto either ep_map(), ib_map(), or lj_map(), depending on how the Xvariable 'printer' was set by the command line flag. maps.c also Xdeclares a single bit map array which is accessed by whichever set of Xmap-related functions is active. The bit maps which had been declared Xin ep_map(), ib_map(), and lj_map() have been commented out in those Xfiles. Each function in the respective version of map_bits() was given Xa prefix of ep_, ib_, or lj_. Otherwise, the three files are quite Xindependent of each other, so that they could easily be pulled apart Xinto single-printer versions; and a new working single-printer version Xcould be added very quickly. X X XDOS ENVIRONMENT X XAs it stands, the bit map array, map(), is too large for C Ximplementations (Turbo C, anyhow) in the DOS environment. A quick fix Xis to reduce each dimension of the Proprinter output to one half of Xnormal (see XLIM and YLIM at the top of file ib_map.c), and declare Xarray map() in file map.c to be of size 25000. The quarter page images Xare cute, anyhow. A longer fix would be to convert from array to Xpointer. X X XNON-STANDARD EXTENSIONS X XInstructions PG, polygon area fill, and EP, edge a polygon, are Xdocumented in their respective files, do_pg.c and do_ep.c. X XComments in an HPGL file may be placed in curly braces, {}. Comments Xmay be nested, and are guarded against the occurence of a closing brace Xin a label instruction. Useful for writing or elucidating HPGL files. XIndispensable for isolating problem instructions in a larger file, when Xdebugging the hpglplot program. A DT instruction, define label Xterminator, should not be commented out. X XSpaces may be embedded between instructions, and between instructions Xand comments. X XTwo other instructions which serve as debugging aids: ESC.! will Xterminate the program without dumping the bit map (see main.c); and an Xexclamation point ! can be used to call any user defined test routine Xnamed in that case of the switch statement. Depending on the test Xroutine, the ! may be followed by parameters. X X XSOLID FILL X XThere are two solid fill routines; one gives a true solid fill, the Xother is a triple cross hatch with angles of 30, 90, and 150. Since Xthe algorithm used to plot a line segment (the edge of a figure) is Xdifferent from the one used to locate the limits of the true solid Xfilling, a figure which is true solid- filled and edged shows a few Xopen dots just inside the edging. This effect is extremely noticeable Xat the lowest resolutions that I use, and very slightly noticeable at Xthe finest resolution that I can get (120 dots per inch by 72). It Xshould be scarcely noticeable at all with the Epson and LaserJet Xresolutions. I've left both solid fills in place, under the control of Xthe preprocessor constant TRUESOLID. If the hardcopy output of the Xtrue solid fill doesn't look ok, don't define TRUESOLID. Try it both Xways. The true solid fill is a matter of plotting vertical hatch lines Xat a spacing equal to the spacing of the dots. X X#ifdef TRUESOLID structures are found in fix_fill() in file fill.c, and Xat the top of file fill.c; in hatch() in file hatch.c; and in Xep/lj_init_map(), towards the bottom of file ep/lj_map.c. X X XOVERVIEW OF AREA-FILL ROUTINES X XThe approach taken to the area fill is to divide each area into a set Xof triangles, all of which share a common vertex (the center of the Xcircle, in the case of a pie sector). In each triangle, the first Xhatch segment is drawn through the common vertex, so that the hatch Xsegments of the adjoining triangles that make up the figure are all in Xalignment with each other. (The common vertex serves as a reference Xpoint for the alignment.) The common vertex is referred to as: X points[0] in do_Rx(), do_WG(), and do_PG() X pts[0] in hatch(), and fill_figure() X P[0] in fill_figure(), and fill_triangle() X (vertex) C in fill_triangle(), get_3_chgs(), end_ref(), and mid_ref() X XHorizontal hatch lines have not been implemented. See (*) below. X XIn any of the component triangles, call the x-intercept of the hatch Xline containing vertex C x_int_C, and likewise for x_int_A and x_int_B. XIf x_int_C <= x_int_A and x_int_C <= x_int_B, the reference point C Xis considered to be at the 'left' end of the triangle. Note that Xdepending on the hatch line angle, C may not actually be the leftmost Xvertex, but it is the first (or ties for first with A or B) vertex that Xwould be intersected by a succession of hatch lines moving from left to Xright. X XIn this case, where C is at the 'left', the next vertex intersected by Xthe succession of hatch lines is named A and the last vertex is named XB. Starting with the hatch line through C, successive hatch segments Xare plotted from left to right, with one endpoint on side CA and one Xendpoint on side CB, until the next hatch line would no longer Xintersect CA. From there, the hatch lines are plotted with one Xendpoint on AB and one on CB until the next hatch line would no longer Xintersect CB. X XIf C is at the 'right' of the triangle, the succession of hatch lines Xstarts at C and moves from right to left, encountering A before (or at Xthe same time as) B. X XThe above scenarios are handled by function end_ref() -- the reference Xpoint is at one 'end' of the triangle or the other. X XIf x_int_C is between x_int_A and x_int_B, the vertex to the 'left' of XC is named A, and that to the 'right' of C is named B. The first hatch Xsegment is plotted with one endpoint at C and the other on side AB. XThen hatch segments proceed to the right with endpoints on AB and CB, Xand finally hatch segments are plotted to the left, starting with the Xfirst one to the left of the segment containing C. This scenario is Xhandled by function mid_ref() -- the reference point is in the 'middle' Xof the triangle. X Xfix_fill() is used to compensate for the lack of distinct pens. A Xformula is used to change the appearance of the fill when only the pen Xnumber is changed in the HPGL file. If pen 1 is selected, the fill Xtype and fill angle(*) set by the last FT instruction are used. If a Xdifferent pen is selected, pen number, fill type, fill angle, and fill Xspacing are combined in the fix_fill() formula to give a different Xfill. X X(*) Horizontal lines have not been implemented because the x-intercept Xof the hatch lines is the basis for the approach taken, and horizontal Xlines don't have x-intercepts. A second set of routines, based on the Xy-intercepts of the hatch lines, could be written for horizontal hatch Xlines, (and in that case, for all hatch lines inclined closer to Xhorizontal than vertical). X XBecause horizontal lines have not been implemented, actual fill angles Xnamed by the FT instruction have been altered as follows: Xfor parallel hatching: X0 degrees -> 25 degrees X45 -> 65 X90 -> 90 X135 -> 115 Xand for cross-hatching: X0/90 -> 20/160 X45/135 -> 70/110 XHowever, any hatch angle other than 0, 45, or 135 will plot exactly. XIt's not advisable to name hatch angles very close to 0 degrees. END_OF_FILE if test 9035 -ne `wc -c <'hpglplot.doc'`; then echo shar: \"'hpglplot.doc'\" unpacked with wrong size! fi # end of 'hpglplot.doc' fi if test -f 'ib_map.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ib_map.c'\" else echo shar: Extracting \"'ib_map.c'\" \(4583 characters\) sed "s/^X//" >'ib_map.c' <<'END_OF_FILE' X/* X * ib_map.c X * X * Copyright (c) 1988 Environmental Defense Fund, Inc. X */ X X#include <stdio.h> X#include "const.h" X#include "fillcnst.h" X X#ifdef TESTVER X#include <signal.h> X#include "dbgvars.h" X#endif X X#define XLIM 32 /* 47 for 1/2 pg output, 94 for full page X * output */ X#define YLIM 320 /* 240/480 for half/full pg output, mode K... */ X /* ...480/960 for half/full pg output, mode L */ X#define MODE 'L' /* 'K' / 'L': 60 dots per in / 120 dots per X * in */ X X#define LEFT_CUTOFF 0 X X/* X * Constants X * SCALEX and SCALEY have been changed to vars, set in init_map, X * to simplify quick changes of scale, depending on XLIM, YLIM X */ X X#define ROUNDER 0.0 X X#ifndef TESTVER X#define PUT_BIT(x,y) map[(x >> 3) + (XLIM * y)] |= BITS[x & 7] X#endif X X#define ABS(x) ((x) > 0.0 ? (x) : -(x)) X Xlong MAP_MAX; Xdouble SCALEX, X SCALEY; /* <<<<<<<<<<<< */ Xchar BITS[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; Xextern char map[]; /* in maps.c */ X X X/******************************* X * catch(), catchi() were here * X *******************************/ X X#ifdef TESTVER XPUT_BIT(x, y) X int x, X y; X{ X int offset; X X offset = ((x >> 3) + (XLIM * y)); X if ((offset >= (MAP_MAX)) || (offset < 0)) { X fprintf(stderr, X "PUTBIT offset overflow: %d; x: %d; y: %d\n", offset, x, y); X fprintf(errfp, X "PUTBIT offset overflow: %d; x: %d; y: %d\n", offset, x, y); X fclose(errfp); X dump_map(TRUE); X exit(1); X } X map[offset] |= BITS[x & 7]; X} X X#endif X X Xib_put_seg(p1, p2) X POINT p1, X p2; X{ X double diffx, X diffy, X change_ratio; X register int x, X y; X register int inc; X X#if 0 X signal(SIGSEGV, catch); X signal(SIGINT, catchi); X#endif X X#ifdef TESTVER X if (debug2 || debug2x) { X fprintf(errfp, "p1 ( %d, %d ); p2 ( %d, %d )\n", X p1.x, p1.y, p2.x, p2.y); X } X#endif X X p1.x = SCALEX * (double) p1.x + ROUNDER; X p2.x = SCALEX * (double) p2.x + ROUNDER; X p1.y = SCALEY * (double) p1.y + ROUNDER; X p2.y = SCALEY * (double) p2.y + ROUNDER; X X diffx = p2.x - p1.x; X diffy = p2.y - p1.y; X X if (diffx != 0.0 && diffy != 0.0) { /* neither horiz nor vert */ X if (ABS(diffx) > ABS(diffy)) { /* closer to horizontal */ X inc = (diffx < 0) ? -1 : 1; X change_ratio = diffy / diffx; X for (x = p1.x; x != p2.x; x += inc) { X y = (x - p1.x) * change_ratio + p1.y + ROUNDER; X PUT_BIT(x, y); X } X PUT_BIT(p2.x, p2.y); X } else { /* closer to vertical */ X inc = (diffy < 0) ? -1 : 1; X change_ratio = diffx / diffy; X for (y = p1.y; y != p2.y; y += inc) { X x = (y - p1.y) * change_ratio + p1.x + ROUNDER; X PUT_BIT(x, y); X } X PUT_BIT(p2.x, p2.y); X } X } else { X if (diffx) { /* horizontal line */ X y = p1.y; X inc = (diffx < 0) ? -1 : 1; X for (x = p1.x; x != p2.x; x += inc) { X PUT_BIT(x, y); X } X PUT_BIT(p2.x, y); X } else { /* vert. line */ X x = p1.x; X inc = (diffy < 0) ? -1 : 1; X for (y = p1.y; y != p2.y; y += inc) { X PUT_BIT(x, y); X } X PUT_BIT(x, p2.y); X } X } X} X X Xib_dump_map(to_printer) X int to_printer; X{ X int i; X register int j; X char ch; X char hdr[5]; X X if (to_printer) { X hdr[0] = ESC; X hdr[1] = '3'; X hdr[2] = 24; /* Line spacing for graphics: 24/216 inch */ X write(1, hdr, 3); X hdr[1] = MODE; /* 'K'/'L': 480/960 bit image graphics */ X hdr[2] = (YLIM - LEFT_CUTOFF) & 0xff; /* n1 = YLIM mod 256 */ X hdr[3] = ((YLIM - LEFT_CUTOFF) >> 8) & 0xff; /* n2 = YLIM / 256 */ X X for (i = 0; i < XLIM; i++) { X write(1, hdr, 4); X for (j = LEFT_CUTOFF * XLIM; j < MAP_MAX; j += XLIM) { X ch = map[i + j]; X if (ch == 26) X ch = 18; /* bug in proprinter graphics */ X if (ch == '\n') X ch = 8; /* prevent add'n of \r to \n */ X write(1, &ch, 1); X#ifdef TESTVER X if (debug5) X fprintf(errfp, "%4d", ch); X#endif X } X#ifdef TESTVER X if (debug5) X fprintf(errfp, "%3d*\n", i); X#endif X putchar('\n'); /* LF and CR to end line */ X putchar('\r'); X fflush(stdout); X } X X /* putchar( '\f' ); *//* form feed */ X#ifdef TESTVER X fclose(errfp); X#endif X X } /* end if ( to_printer )... */ X} X X Xib_init_map() X{ X#ifdef TRUESOLID X extern double PUs_per_dot; /* declared in file filltype.c */ X X#endif X register int k; X register char *mp; X X MAP_MAX = XLIM * YLIM; X SCALEX = (double) (XLIM * 8) / 10366; X SCALEY = (double) (YLIM) / 7963; X X#ifdef TRUESOLID X PUs_per_dot = 1.0 / SCALEX; /* used by fix_fill() in file filltype.c */ X#endif X X mp = map; X for (k = 0; k < MAP_MAX; k++) X *mp++ = 0; X} END_OF_FILE if test 4583 -ne `wc -c <'ib_map.c'`; then echo shar: \"'ib_map.c'\" unpacked with wrong size! fi # end of 'ib_map.c' fi if test -f 'lj_map.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'lj_map.c'\" else echo shar: Extracting \"'lj_map.c'\" \(5523 characters\) sed "s/^X//" >'lj_map.c' <<'END_OF_FILE' X/* X * lj_map.c X * X * Copyright (c) 1988 Environmental Defense Fund, Inc. X */ X X#include <stdio.h> X#include "const.h" X#include "fillcnst.h" X X#ifdef TESTVER X#include <signal.h> X#endif X X/* X * Origin is at lower left corner. X * Bytes of raster data are oriented along the x-axis, hi bit at left: X * (0,0) is bit 7 of byte 0; X * (7,0) is bit 0 of byte 0; X * (16,0) is bit 7 of byte 2; X * (16,3) is bit 7 of byte (2 + XLIM*3) X */ X X/* X * Constants X * YLIM = 1440 dot rows, plus a couple extra for rounding error X */ X#define YLIM 1442 X#define XLIM 235 X X/* SCALEX = SCALEY = number of dots per plotter unit X = 1440 dot rows in y-direction / 7962 PU's in y-dir */ X#define SCALEX 0.180859 X#define SCALEY 0.180859 X#define ROUNDER 0.0 X X#ifdef TESTVER X#define PUT_BIT(x, y) map[(tempindex = (tempx = (x >> 3)) + ((tempy = y) * XLIM))] |= BITS[x & 7]; X#else X#define PUT_BIT(x, y) map[(x >> 3) + (y * XLIM)] |= BITS[x & 7]; X#endif X X#define ABS(x) ((x) > 0.0 ? (x) : -(x)) X X/* move bit map to maps.c for combined printer version --- */ X#if 0 Xchar map[XLIM * YLIM]; X X#endif Xextern char map[]; X Xstatic char BITS[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; X X#ifdef TESTVER Xstatic int tempindex, X tempx, X tempy; Xstatic POINT tempp1, X tempp2; X Xlj_catch() X{ X fprintf(stderr, "Segmentation violation\n"); X fprintf(stderr, "tempindex = %d x = %d y = %d p1 = %d,%d p2 = %d,%d\n", X tempindex, tempx, tempy, tempp1.x, tempp1.y, tempp2.x, tempp2.y); X lj_dump_map(FALSE); X exit(1); X} X Xljcatchi() X{ X lj_dump_map(FALSE); X exit(1); X} X X#endif X Xlj_put_seg(p1, p2) X POINT p1, X p2; X{ X double diffx, X diffy, X change_ratio; X register int x, X y; X register int inc; X X#ifdef TESTVER X#if 0 X signal(SIGSEGV, lj_catch); X signal(SIGINT, ljcatchi); X#endif X tempp1 = p1; X tempp2 = p2; X#endif X X p1.x = SCALEX * (double) p1.x + ROUNDER; X p2.x = SCALEX * (double) p2.x + ROUNDER; X p1.y = SCALEY * (double) p1.y + ROUNDER; X p2.y = SCALEY * (double) p2.y + ROUNDER; X X diffx = p2.x - p1.x; X diffy = p2.y - p1.y; X X if (diffx != 0.0 && diffy != 0.0) { X if (ABS(diffx) > ABS(diffy)) { X inc = (diffx < 0) ? -1 : 1; X change_ratio = diffy / diffx; X for (x = p1.x; x != p2.x; x += inc) { X y = (x - p1.x) * change_ratio + p1.y + ROUNDER; X PUT_BIT(x, y); X } X PUT_BIT(p2.x, p2.y); X } else { X inc = (diffy < 0) ? -1 : 1; X change_ratio = diffx / diffy; X for (y = p1.y; y != p2.y; y += inc) { X x = (y - p1.y) * change_ratio + p1.x + ROUNDER; X PUT_BIT(x, y); X } X PUT_BIT(p2.x, p2.y); X } X } else { X if (diffx) { /* horizontal line */ X y = p1.y; X inc = (diffx < 0) ? -1 : 1; X for (x = p1.x; x != p2.x; x += inc) { X PUT_BIT(x, y); X } X PUT_BIT(p2.x, y); X } else { X x = p1.x; X inc = (diffy < 0) ? -1 : 1; X for (y = p1.y; y != p2.y; y += inc) { X PUT_BIT(x, y); X } X PUT_BIT(x, p2.y); X } X } X} X X Xlj_dump_map(to_printer) X int to_printer; X{ X register int r; X char hdr[7]; X char *mp = map; X char *p, X *maxp; /* for LF-char test */ X short int hdr_length; X X if (to_printer) { X hdr[0] = ESC; X X /* reset printer */ X hdr_length = 1 + n_strcpy(&hdr[1], "E"); X write(1, hdr, hdr_length); X X /* set printer to interpret a '\n' char to a '\r\n' pair */ X hdr_length = 1 + n_strcpy(&hdr[1], "&k2G"); X write(1, hdr, hdr_length); X X /* raster graphics resolution: 300 dots/in */ X hdr_length = 1 + n_strcpy(&hdr[1], "*t300R"); X write(1, hdr, hdr_length); X X /* set cursor to col 11 */ X hdr_length = 1 + n_strcpy(&hdr[1], "&a11C"); X write(1, hdr, hdr_length); X X /* set cursor to row 10 */ X hdr_length = 1 + n_strcpy(&hdr[1], "&a10R"); X write(1, hdr, hdr_length); X X /* start graphics at current cursor posn */ X hdr_length = 1 + n_strcpy(&hdr[1], "*r1A"); X write(1, hdr, hdr_length); X X /* transfer-line-of-graphics escape sequence -- 235 is XLIM */ X hdr_length = 1 + n_strcpy(&hdr[1], "*b235W"); X X /* X * write YLIM rows, each row is XLIM bytes starting at offset r from X * map[0] X */ X for (r = (YLIM - 1) * XLIM; r >= 0; r -= XLIM) { X /* check this row for LF-chars; replace with byte value of 8 */ X p = mp + r; X maxp = p + XLIM; X while (p < maxp) { X if (*p == '\n') { X *p = 8; X } X p++; X } X write(1, hdr, hdr_length); X write(1, mp + r, XLIM); X fflush(stdout); X } X X /* end raster graphics */ X hdr_length = 1 + n_strcpy(&hdr[1], "*rB"); X write(1, hdr, hdr_length); X X /* reset printer and eject the page */ X hdr_length = 1 + n_strcpy(&hdr[1], "E"); X write(1, hdr, hdr_length); X X /* X * set printer to interpret a '\n' char to a '\r\n' pair. this works X * in combo with the plot script, which also controls interpretation X * of \n's at the port X */ X hdr_length = 1 + n_strcpy(&hdr[1], "&k2G"); X write(1, hdr, hdr_length); X X fflush(stdout); X } X} X X X/* X * copy string from src to dst, including terminating \0. X * return number of chars copied, excluding terminating \0 X */ Xint Xn_strcpy(dst, src) X char *dst, X *src; X{ X char *p; X X p = src; X while (*dst++ = *src++); X return ((--src) - p); X} X X Xlj_init_map() X{ X register int k; X register char *mp; X int map_max = YLIM * XLIM; X X#ifdef TRUESOLID X extern double PUs_per_dot; /* declared in file filltype.c */ X X PUs_per_dot = 1.0 / SCALEX; /* used by fix_fill() in file filltype.c */ X#endif X X mp = map; X for (k = 0; k < map_max; k++) { X *mp++ = 0; X } X} END_OF_FILE if test 5523 -ne `wc -c <'lj_map.c'`; then echo shar: \"'lj_map.c'\" unpacked with wrong size! fi # end of 'lj_map.c' fi if test -f 'step.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'step.c'\" else echo shar: Extracting \"'step.c'\" \(6760 characters\) sed "s/^X//" >'step.c' <<'END_OF_FILE' X/* X * step.c X * X * Copyright (c) 1988 Environmental Defense Fund, Inc. X */ X X#include <stdio.h> X#include <math.h> X#include <string.h> /* for debug4 in get_chgs() */ X#include "const.h" X#include "vars.h" X#include "fillcnst.h" X#include "fillvars.h" X#ifdef TESTVER X#include "dbgvars.h" X#endif X X#ifdef __STDC__ X/* function prototypes */ Xint Xchoose_step(FPOINT *f_pt_s1p, double chg_x_s1, double chg_y_s1, X FPOINT *f_pt_s2p, double chg_x_s2, double chg_y_s2, X int status, int limit); Xint Xstep(FPOINT *f_pt_s1p, double chg_x_s1, double chg_y_s1, X FPOINT *f_pt_s2p, double chg_x_s2, double chg_y_s2, X POINT *endpt_s1p, POINT *endpt_s2p); Xint Xcvt_pt(POINT *pt, FPOINT *f_pt); Xint Xget_chgs(double *chg_xp, double *chg_yp, POINT p1, POINT p2); Xdouble Xreduce_rads(double angle); X X#else Xdouble reduce_rads(); X X#endif X X/* 1 dot in 10 inches at 300 dots/in; in radians */ X#define APPROX 0.0003 X X X/* =========================== choose_step() =============================== */ X/* X * while the current hatch segment X * intersects both side s1 and side s2 of the triangle, X * call step(): X * write the segment to the map[] array, X * and calculate the endpts for the next hatch segment. X * Side s1 is the side used to determine the limit of the hatching. X */ X Xchoose_step(f_pt_s1p, chg_x_s1, chg_y_s1, X f_pt_s2p, chg_x_s2, chg_y_s2, X status, limit) X FPOINT *f_pt_s1p, X *f_pt_s2p; X double chg_x_s1, X chg_y_s1, X chg_x_s2, X chg_y_s2; X int status, X limit; X{ X POINT endpt_s1, X endpt_s2; X X#ifdef TESTVER X if (debug4) { X fprintf(errfp, X "f_pt_s1: ( %6.1f, %6.1f ); f_pt_s2: ( %6.1f, %6.1f )\n", X f_pt_s1p->xx, f_pt_s1p->yy, f_pt_s2p->xx, f_pt_s2p->yy); X fprintf(errfp, X "status: %d; limit: %d\n", status, limit); X fprintf(errfp, X "chg_x_s1: %6.1f; chg_y_s1: %6.1f; chg_x_s2: %6.1f; chg_y_s2: %6.1f\n", X chg_x_s1, chg_y_s1, chg_x_s2, chg_y_s2); X fflush(errfp); X } X#endif X X cvt_pt(&endpt_s1, f_pt_s1p); X cvt_pt(&endpt_s2, f_pt_s2p); X X if (status == VERT) { X if (chg_y_s1 > 0.0) { X while (endpt_s1.y <= limit) { X step(f_pt_s1p, chg_x_s1, chg_y_s1, X f_pt_s2p, chg_x_s2, chg_y_s2, X &endpt_s1, &endpt_s2); X } X } else { X while (endpt_s1.y >= limit) { X step(f_pt_s1p, chg_x_s1, chg_y_s1, X f_pt_s2p, chg_x_s2, chg_y_s2, X &endpt_s1, &endpt_s2); X } X } X } else { /* non-vertical, use x-values for reference */ X if (chg_x_s1 > 0.0) { X while (endpt_s1.x <= limit) { X step(f_pt_s1p, chg_x_s1, chg_y_s1, X f_pt_s2p, chg_x_s2, chg_y_s2, X &endpt_s1, &endpt_s2); X } X } else { X while (endpt_s1.x >= limit) { X step(f_pt_s1p, chg_x_s1, chg_y_s1, X f_pt_s2p, chg_x_s2, chg_y_s2, X &endpt_s1, &endpt_s2); X } X } X } X} X X X/* =========================== step() ====================================== */ X/* X * write the current hatch segment to the map[] array, X * and calculate the endpts for the succeeding hatch segment. X */ X Xstep(f_pt_s1p, chg_x_s1, chg_y_s1, X f_pt_s2p, chg_x_s2, chg_y_s2, X endpt_s1p, endpt_s2p) X FPOINT *f_pt_s1p, X *f_pt_s2p; X double chg_x_s1, X chg_y_s1, X chg_x_s2, X chg_y_s2; X POINT *endpt_s1p, X *endpt_s2p; X{ X put_seg(*endpt_s1p, *endpt_s2p); X X f_pt_s1p->xx += chg_x_s1; X f_pt_s1p->yy += chg_y_s1; X f_pt_s2p->xx += chg_x_s2; X f_pt_s2p->yy += chg_y_s2; X X cvt_pt(endpt_s1p, f_pt_s1p); X cvt_pt(endpt_s2p, f_pt_s2p); X} X X X/* =========================== cvt_pt() ==================================== */ Xcvt_pt(pt, f_pt) X POINT *pt; X FPOINT *f_pt; X{ X pt->x = (int) floor(f_pt->xx + 0.5); X pt->y = (int) floor(f_pt->yy + 0.5); X} X X X/* =========================== get_chgs() ================================== */ Xint Xget_chgs(chg_xp, chg_yp, p1, p2) X double *chg_xp, X *chg_yp; X POINT p1, X p2; X{ X double seg_shift; X int diffx, X diffy; X double seg_rads; /* angle of segment p1-p2 in radians */ X int status; /* local var status */ X X#ifdef TESTVER X static char *stat_type[] = {"GENERIC", X "PARALLEL", X "VERTICAL", X "HORIZONTAL"}; X X#endif X X X#ifdef TESTVER X if (debug7) { X fprintf(errfp, "\nIn: get_chgs();\n"); X } X if (debug7) { X fprintf(errfp, "p1: ( %d, %d ); p2: ( %d, %d )\n", X p1.x, p1.y, p2.x, p2.y); X fflush(errfp); X } X#endif X X /* find the angle of inclination of segment p1-p2 */ X diffy = p2.y - p1.y; X diffx = p2.x - p1.x; X if (diffx != 0) { X seg_rads = atan2((double) diffy, (double) diffx); X } else { X seg_rads = (double) PI_2; X } X X /* X * find the x- and y- increments for successive hatch line intersections X * along segment p1-p2 X */ X hatch_rads = reduce_rads(hatch_rads); X seg_rads = reduce_rads(seg_rads); X X#ifdef TESTVER X if (debug7) { X fprintf(errfp, "diffy: %6d; diffx: %6d\n", diffy, diffx); X fprintf(errfp, "seg_rads: %6.4f; hatch_rads: %6.4f; abs diff: %6.4f\n", X seg_rads, hatch_rads, fabs(hatch_rads - seg_rads)); X } X#endif X X if (fabs(hatch_rads - seg_rads) < APPROX) { /* parallel */ X status = PARL; X *chg_xp = x_shift; X *chg_yp = 0.0; X } else if (fabs(seg_rads) < APPROX) { /* horizontal */ X status = HORZ; X *chg_xp = x_shift; X *chg_yp = 0.0; X } else if (fabs(seg_rads - PI_2) < APPROX) { /* vertical */ X status = VERT; X *chg_xp = 0.0; X *chg_yp = -tan(hatch_rads) * x_shift; X } else { X /* X * spacing of intercepts of adjacent hatch lines along segment p1-p2 X * uses law of sines X */ X status = GENR; X seg_shift = (x_shift * sin(PI - hatch_rads)) / X sin(hatch_rads - seg_rads); X *chg_xp = seg_shift * cos(seg_rads); X *chg_yp = seg_shift * sin(seg_rads); X } X /* remove error due to digital storage, for tests for equality later */ X if (fabs(*chg_xp) < 0.001) X *chg_xp = 0.0; X if (fabs(*chg_yp) < 0.001) X *chg_yp = 0.0; X X#ifdef TESTVER X if (debug7) { X fprintf(errfp, "seg_rads (deg): %6.1f; seg_rads (rads): %6.4f\n", X (seg_rads / DEG_TO_RAD), seg_rads); X fprintf(errfp, "sin(PI-hatch_rads): %6.4f; sin(hatch-seg): %6.4f\n", X sin(PI - hatch_rads), sin(hatch_rads - seg_rads)); X fprintf(errfp, "x_shift: %6.1f; seg_shift: %6.1f\n", X x_shift, seg_shift); X fprintf(errfp, "Angle relationship: %s\n", stat_type[status]); X fprintf(errfp, "chg_x: %6.1f; chg_y: %6.1f\n", *chg_xp, *chg_yp); X fflush(errfp); X } X#endif X X return (status); X} X X X/* =========================== reduce_rads() =============================== */ X/* modify angle so that 0 <= angle <= PI */ Xdouble Xreduce_rads(angle) X double angle; X{ X while (angle > PI) { X angle -= PI; X } X while (angle < 0.0) { X angle += PI; X } X return (angle); X} END_OF_FILE if test 6760 -ne `wc -c <'step.c'`; then echo shar: \"'step.c'\" unpacked with wrong size! fi # end of 'step.c' fi echo shar: End of archive 2 \(of 3\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 3 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0