home *** CD-ROM | disk | FTP | other *** search
- #pragma linesize(132) /* listing linewidth = 132 */
-
- /* hpgl1.c this file contains the following functions:
-
- arc_3pt ()
- calc_ticksize ()
- chord_t ()
- circle ()
- cot ()
- draw_arc ()
- draw_xtick ()
- draw_ytick ()
- draw_wedge ()
- draw_rect ()
- fill_rect ()
- fill_type ()
- fix_hatch ()
- get_xy ()
- get_val ()
- init_fills ()
- new_plot ()
- plotted_on ()
- print_error ()
- tick_length ()
- velocity_sel ()
-
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <float.h>
- #include "hpgl.h"
- #include "graph.h"
-
- extern double gdu_cm, p1x, p1y, p2x, p2y;
- extern int chord_type, p_status, symbol_mode;
- extern double uu_2_pux, uu_2_puy;
- extern char symbol;
-
- static void fill_rect (double, double, double, double, double, double);
- static double cot ( double );
-
- static char copyright[] = "Copyright 1991, Robert C. Becker, Lantern Systems";
-
- struct poly_fills
- {
- int mode;
- double opt1, opt2;
- double alt_opt1;
- };
-
- static struct poly_fills fill_code [6]; /* hold values for types 1, 2, 3, 4, 10, 11 */
- /* values for these type stored in this order in struct array */
-
- static int select_fill; /* last fill type selected */
- static double tnx, tny, tpx, tpy; /* x, y tick negative & positive lengths in GDU's */
- static double anchor_x, anchor_y; /* corner anchors for fill types */
- static int dirty_plot; /* flag to mark if plot has been plotted on yet */
- static char bfr[256]; /* scratch char buffer for get_val */
-
- /*--------------------------------------*/
-
- void velocity_sel (FILE *infile)
- {
- double x;
-
- DB (printf ("VS\n");)
- if (get_val (infile, &x)) /* optional speed argument: not used */
- {
- get_val (infile, &x); /* optional pen # argument: not used */
- }
- return;
- }
-
- /*--------------------------------------*/
-
- void tick_length (FILE *infile)
- {
- double tp, tn;
-
- tp = DEF_TICK;
- tn = DEF_TICK; /* default tick lengths */
- if ( get_val (infile, &tp)) /* got one value: try for two */
- {
- if (!get_val (infile, &tn)) tn = 0.0; /* if only have one value, tn = 0 */
- }
- calc_ticksize (tp, tn);
- return;
- }
- /*--------------------------------------*/
-
- void calc_ticksize (double tp, double tn)
- {
-
- tp = MAX (-128.00, (MIN (127.9999, tp)));
- tn = MAX (-128.00, (MIN (127.9999, tn)));
-
- tpx = (tp * (p2x - p1x) * 0.00254 / 100.0) * gdu_cm;
- tpy = (tp * (p2y - p1y) * 0.00254 / 100.0) * gdu_cm;
- tnx = (tn * (p2x - p1x) * 0.00254 / 100.0) * gdu_cm;
- tny = (tn * (p2y - p1y) * 0.00254 / 100.0) * gdu_cm;
- /* P1, P2 are in mils. 0.00254 cm/mil */
-
- return;
- }
-
- /*--------------------------------------*/
-
- void draw_xtick (void)
- {
- double x_1, y_1; /* local variables */
-
- setgu();
- where (&x_1, &y_1);
- rmove (0.0, -tny);
- rdraw (0.0, tpy); /* draw vertical tick mark */
- move (x_1, y_1); /* NOP: establish new position for subsequent rmove/draw ()'s */
- setuu ();
- plotted_on (1); /* we drew something on this plot */
- return;
- }
-
- /*--------------------------------------*/
-
- void draw_ytick (void)
- {
- double x_1, y_1; /* local variables */
-
- setgu ();
- where (&x_1, &y_1);
- rmove (-tnx, 0.0);
- rdraw (tpx, 0.0); /* draw horizontal tick mark */
- move (x_1, y_1); /* NOP: establish new position for subsequent rmove/draw ()'s */
- setuu ();
- plotted_on (1); /* we drew something on this plot */
- return;
- }
-
- /*--------------------------------------*/
-
- void print_error (char *instr, int type)
- {
-
- if (type)
- fprintf (stderr, "%s", instr);
- else
- fprintf (stderr, "%s instruction not implimented\n", instr);
- return;
- }
-
- /*--------------------------------------*/
-
- int get_xy (FILE *infile, double *xv, double *yv)
- {
-
- if (get_val (infile, xv)) /* get x values */
- {
- if ( !get_val (infile, yv)) /* get y value */
- {
- print_string ("get_xy(): missing y-value\n");
- return (0);
- }
- return (1); /* have 2 values */
- }
- return (0); /* no values */
- }
-
- /*--------------------------------------*/
-
- void new_plot ( void )
- {
-
- dirty_plot = 0; /* plot is clean (not plotted on) */
- return;
- }
-
- /*--------------------------------------*/
-
- int plotted_on (int plot_flag)
- {
-
- if (plot_flag > 0)
- dirty_plot = 1; /* mark plot as plotted on */
- return (dirty_plot);
- }
-
- /*--------------------------------------*/
-
- int get_val (FILE *infile, double *rval)
- {
- int j;
- char c;
-
- c = getc (infile);
- while ( c && c != (char) EOF && isspace (c) ) c = getc (infile);
- /* remove leading white-space */
-
- if ( c == TERMCHAR || c == (char) EOF) return (0); /* terminated: return # params read */
- if ( ! (isdigit (c) || c == ',' || c == '-' || c == '+' || c == '.'))
- {
- ungetc (c, infile); /* put back what we grabbed */
- return (0); /* next char not a number */
- }
- if (c == ',') c = getc (infile);
-
- j = 0;
- while ( isdigit ( c ) || c == '-' || c == '+' || c == '.' )
- {
- bfr[j] = c;
- c = getc (infile);
- ++j;
- }
- bfr[j] = '\0'; /* terminate string */
- if (c != ',' && !isspace (c) ) ungetc (c, infile); /* DO NOT INCLUDE termchar IN THIS TEST!! */
-
- /* including termchar in the test to unget a char will cause a failure if termchar was read
- by this routine and it is called again immediately thereafter (will return 1 argument of zero value [error]) */
-
- if (j == 0) /* trap zero length arguments */
- {
- print_string ("? Null argument in get_val ()\n");
- return (0);
- }
-
- DB (printf ("get_val: instring = %s\n", bfr);)
- *rval = atof (bfr);
- return (1);
- }
-
- /*--------------------------------------*/
-
- void draw_arc (FILE * infile, int type )
- { /* type: 0 -> absolute, 1 -> relative */
- double radius, x, y, x_1, y_1, x_2, y_2, val4, ang1, ang2, ang3;
- unsigned char c2;
- int segs;
-
- DB (if (type) printf ("AR\n"); else printf ("AA\n");)
- if (!get_xy (infile, &x, &y))
- {
- if (type)
- print_string ("AR: missing x- or y-value\n");
- else
- print_string ("AA: missing x- or y-value\n");
- return; /* illegal instr */
- }
- if (!get_val (infile, &ang1)) /* arc angle */
- {
- if (type)
- print_string ("AR: missing arc angle\n");
- else
- print_string ("AA: missing arc angle\n");
- return; /* illegal instr */
- }
- DB (printf ("input value: x = %lf, y = %lf, ang1 = %lf\n", x, y, ang1);)
- where (&x_1, &y_1); /* get starting point */
- if (type)
- { /* relative */
- DB (printf ("current location: (x,y) = (%lf, %lf)\n", x_1, y_1);)
- x_2 = x_1 + x;
- y_2 = y_1 + y;
- x_1 = -x;
- y_1 = -y;
- }
- else
- { /* absolute */
- x_2 = x;
- y_2 = y; /* save center position */
- x_1 -= x;
- y_1 -= y; /* delta-x, -y */
- }
- DB (printf ("arc center: (x,y) = (%lf, %lf), angle = %lf\n", x_2, y_2, ang1);)
- move (x_2, y_2); /* move to center of arc */
- radius = sqrt (x_1*x_1 + y_1*y_1);
-
- ang2 = val4 = DEF_CHORD; /* set default chord angle or deviation */
- if (get_val (infile, &val4))
- {
- val4 = fabs (val4); /* only positive values allowed */
- if (chord_type) /* using angles, not deviations */
- {
- ang2 = MIN (MAX_CHORD, (MAX (val4, MIN_CHORD)));
- }
- else /* chord angle determined by deviation of segments from circle radius */
- { /* at this point, val4 is length in current units, not angle in degrees */
- if (val4 > 2.0 * radius) val4 = 2.0 * radius; /* limit deviation: resulting chord angle < 180 deg. */
- ang2 = RAD_2_DEG * acos ( (radius - val4) / radius);
- }
- }
- segs = (int) (fabs (ang1) / ang2 + 0.5); /* # segments in "ang1" deg. */
- /* sign of 'segs' changes direction of arc () */
- DB (printf ("chord = %lf, # segments = %d\n", ang2, segs);)
- ang3 = RAD_2_DEG * atan2 (y_1, x_1);
- if (p_status == PENDOWN) /* draw the arc only if pen is down */
- {
- DB (printf ("radius = %lf, start angle = %lf, stop angle = %lf\n", radius, ang3, ang1 + ang3);)
- arc ( radius, segs, ang3, ang1 + ang3);
- }
- if (symbol_mode)
- {
- move (x_2, y_2);
- symbol_mark (symbol);
- }
- plotted_on (1); /* we drew something on this plot */
- return;
- }
-
- /*--------------------------------------*/
-
- void circle (FILE * infile)
- {
- double ang, ang2, radius, val2, x_1, y_1;
- unsigned char c2;
- int segs;
-
- DB(printf ("CI\n");)
- ang2 = val2 = DEF_CHORD; /* default chord angle or deviation for circle/arc */
- if (!get_val (infile, &radius))
- {
- print_string ("CI: radius not specified\n");
- return; /* error: no param's */
- }
- if ( get_val (infile, &val2))
- {
- val2 = fabs (val2); /* only positive values allowed */
- if (chord_type) /* using angles, not deviations */
- {
- ang2 = MIN (MAX_CHORD, (MAX (val2, MIN_CHORD)));
- }
- else /* chord angle determined by deviation of segments from circle radius */
- { /* at this point, val2 is length in current units, not angle in degrees */
- if (val2 > 2.0 * radius) val2 = 2.0 * radius; /* limit deviation: resulting chord angle < 180 deg. */
- ang2 = RAD_2_DEG * acos ( (radius - val2) / radius);
- }
- }
- segs = (int) (360.0 / ang2 + 0.5); /* # segments in 360 deg. */
- /* sign of 'segs' changes direction of arc () */
- DB (printf ("CI: radius = %lf, chord = %lf, # segments = %d\n", radius, ang2, segs);)
- where (&x_1, &y_1);
- arc (radius, segs, 0.0, 360.0); /* circle with l segments */
- if (symbol_mode)
- {
- move (x_1, y_1);
- symbol_mark (symbol);
- }
- plotted_on (1); /* we drew something on this plot */
- return;
- }
-
- /*--------------------------------------*/
-
- void arc_3pt (FILE * infile, int type)
- { /* type 0 = absolute arc, type 1 = relative arc */
- double ma, mb, ba, bb, x_1, y_1, xi, yi, xe, ye;
- double dax, day, dbx, dby, xc, yc, ang_e, ang_i;
- double start_ang, stop_ang, radius, ang2, val5;
- int segs, cw;
-
- DB (if (type) printf ("AR\n"); else printf ("AT\n");)
- if (!get_xy (infile, &xi, &yi))
- {
- if (type)
- print_string ("AR: missing Xi or Yi value\n");
- else
- print_string ("AT: missing Xi or Yi value\n");
- return;
- }
- if (!get_xy (infile, &xe, &ye))
- {
- if (type)
- print_string ("AR: missing Xe or Ye value\n");
- else
- print_string ("AT: missing Xe or Ye value\n");
- return;
- }
-
- where (&x_1, &y_1); /* current position */
- if (type) /* relative arc in 3 pts */
- {
- xe += x_1;
- ye += y_1;
- xi += x_1;
- yi += y_1; /* convert from offsets to abs coordinates */
- }
-
- dax = xe - x_1;
- day = ye - y_1; /* delta-x, -y from ref. to end pt. */
- dbx = xi - xe;
- dby = yi - ye; /* delta-x, -y from end pt. to intermediate pt. */
-
- DB (printf ("P1: (%lf, %lf) Pi: (%lf, %lf), Pe: (%lf, %lf)\n", x_1, y_1, xi, yi, xe, ye);)
- DB (printf ("fabs (day) = %lf, fabs(dby) = %lf\n", fabs(day), fabs(dby));)
-
- if ( fabs (day) < FLT_EPSILON) /* P1, Pe horizontal or same */
- { /* FLT, not DBL: more conservative */
- DB (printf ("fabs (day) < FLT_EPSILON\n");)
- xc = x_1 + dax / 2; /* equation of vertical line */
- if (fabs (dby) < FLT_EPSILON || fabs (dax) < FLT_EPSILON)
- { /* all pts horizontal */
- DB (printf ("vertical or straight line curve\n");)
- if (symbol_mode)
- {
- move (x_1, y_1);
- symbol_mark (symbol);
- }
- draw (xi, yi); /* draw intermediate pt in case end & start same */
- draw (xe, ye); /* this is the curve */
-
- plotted_on (1); /* we drew something on this plot */
- return;
- }
- mb = -dbx / dby; /* slope of line normal to PePi */
- bb = (ye + dby / 2) - mb * (xe + dbx / 2); /* now have b-part of line equations */
- yc = mb * xc + bb;
- }
- else
- { /* FLT, not DBL: more conservative */
- if (fabs (dby) < FLT_EPSILON) /* Pe, Pi horizontal or same */
- {
- DB (printf ("fabs (dby) < FLT_EPSILON\n");)
- xc = xe + dbx / 2; /* equation of vertical line */
- if (fabs (day) < FLT_EPSILON || fabs (dbx) < FLT_EPSILON)
- { /* all pts horizontal or Pe == Pi */
- DB (printf ("horizontal or straight line curve\n");)
- if (symbol_mode)
- {
- move (x_1, y_1);
- symbol_mark (symbol);
- }
- draw (xi, yi); /* draw intermediate pt in case end & start same */
- draw (xe, ye); /* this is the curve */
- plotted_on (1); /* we drew something on this plot */
- return;
- }
- ma = -dax / day; /* slope of line normal to PiPe */
- ba = (y_1 + day / 2) - ma * (x_1 + dax / 2);
- yc = ma * xc + ba;
- }
- else
- {
-
- /* general case: can't handle dby = 0 or day = 0 */
- ma = -dax / day; /* slope of line normal to P1Pe */
- mb = -dbx / dby; /* slope of line normal to PePi */
-
- /* y_1 + day = y-value midway between y_1 and ye */
- /* x_1 + dax = x-value midway between x_1 and xe */
- /* ye + dby = y-value midway between ye and yi */
- /* xe + dbx = x-value midway between xe and yi */
- ba = (y_1 + day / 2) - ma * (x_1 + dax / 2);
- bb = (ye + dby / 2) - mb * (xe + dbx / 2); /* now have b-part of line equations */
-
- if (fabs (ma - mb) < FLT_EPSILON) /* that's right FLT, not DBL */
- { /* too small to prevent floating point overflow */
- DB (printf ("straight line curve\n");)
- if (symbol_mode)
- {
- move (x_1, y_1);
- symbol_mark (symbol);
- }
- draw (xi, yi); /* draw intermediate pt in case end & start same */
- draw (xe, ye); /* this is the curve */
- return;
- }
- xc = (bb - ba) / (ma - mb); /* now have x-center */
- yc = mb * xc + bb; /* can find yc using either line eqn. */
- }
- }
-
- DB (printf ("3-pt. arc: center at (%lf, %lf)\n", xc, yc);)
-
- radius = sqrt ((xc - x_1) * (xc - x_1) + (yc - y_1) * (yc - y_1));
-
- ang2 = val5 = DEF_CHORD; /* set default chord angle or deviation */
- if (get_val (infile, &val5))
- {
- val5 = fabs (val5); /* only positive values allowed */
- if (chord_type) /* using angles, not deviations */
- {
- ang2 = MIN (MAX_CHORD, (MAX (val5, MIN_CHORD)));
- }
- else /* chord angle determined by deviation of segments from circle radius */
- { /* at this point, val5 is length in current units, not angle in degrees */
- if (val5 > 2.0 * radius) val5 = 2.0 * radius; /* limit deviation: resulting chord angle < 180 deg. */
- ang2 = RAD_2_DEG * acos ( (radius - val5) / radius);
- }
- }
-
- DB (printf ("P1: (%lf, %lf), Pc: (%lf, %lf), Pe: (%lf, %lf)\n", x_1, y_1, xc, yc, xe, ye);)
-
- start_ang = RAD_2_DEG * atan2 (y_1 - yc, x_1 - xc); /* angle from center to starting pt */
- stop_ang = RAD_2_DEG * atan2 (ye - yc, xe - xc); /* angle from center to stopping pt */
-
- DB (printf ("initial: start_ang = %lf, stop_ang = %lf\n", start_ang, stop_ang);)
-
- ang_e = RAD_2_DEG * atan2 (day, dax);
- ang_i = RAD_2_DEG * atan2 ( yi - y_1, xi - x_1); /* determine direction of arc */
-
- cw = 1; /* direction defaults to clockwise rotation */
-
- if (ang_e >= 0.0 && ang_i >= 0.0) /* resolve direction of arc by */
- cw = (ang_e < ang_i) ? 1 : 0; /* angle between ref. pt and other 2 pts */
- else
- {
- if (ang_e <= 0.0 && ang_i <= 0.0)
- cw = (ang_e < ang_i) ? 1 : 0;
- else
- {
- if (ang_e <= 0.0 && ang_i >= 0.0) /* first conflict */
- cw = (ang_i - ang_e <= 180.0) ? 1 : 0;
- else
- if (ang_e >= 0.0 && ang_i <= 0.0)
- cw = (ang_e - ang_i >= 180.0) ? 1 : 0;
- }
- }
- /* now we have determined which direction the arc is drawn (either cw or ccw) */
-
- switch (cw)
- {
- case 0: /* counter clockwise rotation */
- DB (printf ("counter-clockwise rotation\n");)
- if (start_ang >= 0.0 && stop_ang >= 0.0)
- {
- stop_ang += (start_ang > stop_ang) ? 360.0 : 0.0; /* 1 */
- }
- else
- {
- if (start_ang <= 0.0 && stop_ang <= 0.0)
- {
- stop_ang += (start_ang > stop_ang) ? 360.0 : 0.0; /* 2 */
- }
- else
- if (start_ang >= 0.0 && stop_ang <= 0.0) /* 4 */
- {
- stop_ang += 360.0;
- }
- }
- break;
- case 1: /* clockwise rotation */
- DB (printf ("clockwise rotation\n");)
- if (stop_ang >= 0.0 && stop_ang >= 0.0)
- {
- stop_ang -= (start_ang < stop_ang) ? 360.0 : 0.0; /* 1a */
- }
- else
- {
- if (start_ang <= 0.0 && stop_ang <= 0.0)
- {
- stop_ang -= (start_ang < stop_ang) ? 360.0 : 0.0; /* 2a */
- }
- else
- if (start_ang <= 0.0 && stop_ang >= 0.0) /* 4a */
- {
- stop_ang -= 360.0;
- }
- }
- break;
- default: break;
- }
-
- segs = (int) (fabs (start_ang - stop_ang) / ang2 + 0.5); /* # segments in "ang1" deg. */
- /* sign of 'segs' changes direction of arc () */
-
- DB (printf ("final: start_ang = %lf, stop_ang = %lf\n", start_ang, stop_ang);)
- DB (printf ("chord angle = %lf, # segments = %d\n", ang2, segs);)
-
- move (xc, yc); /* move to center of arc */
- arc (radius, segs ,start_ang, stop_ang);
-
- plotted_on (1); /* we drew something on this plot */
- return;
- }
-
- /*--------------------------------------*/
-
- void init_fills (void)
- { /* since only hatched fill defined, only need to initialize it */
-
- /* values for hatched fill and cross-hatched fill */
- /* for DEFAULTUNITS, spacing must be determined at the same time
- the fill is used for drawing since P1 & P2 could have changed */
-
- fill_code [HATCH].mode = fill_code [XHATCH].mode = DEFAULTUNITS;
-
- /* don't care about either opt1 or alt_opt1 since default unit sizes
- are calculated when they are drawn */
-
- fill_code [HATCH].opt1 = fill_code [XHATCH].opt1 = 0.0;
- fill_code [HATCH].alt_opt1 = fill_code [XHATCH].alt_opt1 = 0.0;
-
- fill_code [HATCH].opt2 = fill_code [XHATCH].opt2 = 0.0; /* angle = 0 */
-
- select_fill = DEFAULT_FILL; /* select default fill */
-
- return;
- }
-
- /*--------------------------------------*/
-
- void fix_hatch ( void )
- {
- /* don't care if scaling is on or off. This only affects hatch sizes
- when they are in user units and the scale changes */
-
- /* fill_code [].opt1 is in user units; fill_code [].alt_opt1 is in plotter units */
-
- if (fill_code [HATCH].mode == USERUNITS)
- fill_code [HATCH].alt_opt1 = fill_code [HATCH].opt1 / uu_2_pux;
- if (fill_code [XHATCH].mode == USERUNITS)
- fill_code [XHATCH].alt_opt1 = fill_code [XHATCH].opt1 / uu_2_pux;
- return;
- }
-
- /*--------------------------------------*/
-
- void fill_type (FILE *infile, int scaling )
- {
- double ftype, opt1, opt2;
- int f1, f2, type;
-
- f1 = f2 = 0; /* no arguments */
- opt1 = opt2 = 0.0;
- if (get_val (infile, &ftype))
- {
- /* test for invalid type */
- if (ftype < 1.0 || ftype > 11.0 || (ftype > 4.0 && ftype < 10.0))
- {
- while (get_val (infile, &opt1)); /* dump trailing arguments */
- return;
- }
- /* have one value argument */
- if (get_val (infile, &opt1))
- {
- f1 = 1; /* mark option #1 present */
- if (get_val (infile, &opt2))
- f2 = 1; /* mark option #2 present */
- }
- type = (int) ftype;
- type = (type > 4) ? (type - 6) : type - 1; /* shift range to 0 - 5 */
- }
- else
- {
- type = DEFAULT_FILL; /* no fill-type -> default */
- select_fill = type; /* save current fill-type */
- fill_code [type].mode = DEFAULTUNITS;
- /* calculate size of units when fill is drawn */
- return;
- }
-
- switch (type)
- {
- case 0: select_fill = type; /* save current fill-type */
- return; /* solid fill: not yet implimented */
- break;
- case 1: select_fill = type; /* save current fill-type */
- return; /* solid_fill: not yet implimented */
- break;
- case HATCH: /* hatched fill */
- case XHATCH: /* crosshatched fill */
-
- select_fill = type; /* save current fill-type */
-
- if (f1 && opt1 == 0.0) /* use default spacing */
- fill_code [type].mode = DEFAULTUNITS;
- /* calculate size of units when fill is drawn */
-
- if (f1)
- {
- fill_code [type].mode = PLOTTERUNITS; /* assume plotter units */
- fill_code [type].alt_opt1 = opt1; /* save hatch x-spacing in plotter units */
- /* don't care about size in user units */
- if (scaling == ON)
- {
- fill_code [type].mode = USERUNITS; /* correct assumption about units */
- fill_code [type].opt1 = opt1; /* user units value */
- fill_code [type].alt_opt1 = opt1 / uu_2_pux;
- /* save value of option #1 in plotter units */
-
- /* we do this because HPGL/2 demands that use units
- be frozen in equivalent plotter units if scaling is
- turned off */
- }
- }
-
- /* update angle value only if user supplied */
-
- if (f2) fill_code [type].opt2 = opt2;
-
- break;
- case 4: select_fill = type; /* save current fill-type */
- return; /* shaded fill: not yet implimented */
- break;
- case 5: select_fill = type; /* save current fill-type */
- return; /* user defined fill: not yet implimented */
- break;
- default: break;
- }
-
- return;
- }
- /*--------------------------------------*/
-
- void draw_rect (FILE * infile, int type)
- { /* type 0 = absolute, type 1 = relative, 0x10 = absolute, filled,
- 0x11 = relative, filled */
- double xp, yp, xc, yc, x_sp, theta;
-
- DB ({if (type & 0x10) printf ("%s\n", (type & 1) ? "RR" : "RA");})
- DB ({if (!(type &0x10)) printf ("%s\n", (type & 1) ? "ER" : "EA");})
- where (&xp, &yp); /* get current position */
- if (get_xy (infile, &xc, &yc))
- {
- /* calculate width and height for rectangle () function */
- if (type & 1) /* relative rect */
- {
- xc += xp;
- yc += yp; /* calculate opposite corner pos */
- }
- DB (printf ("Rectangle from (%lf, %lf) to (%lf, %lf)\n", xp, yp, xc, yc);)
- rectangle (xp, yp, xc, yc);
- if (type & 0x10)
- {
- DB (printf ("filled rectangle: select_fill = %d\n", select_fill);)
- if (select_fill != HATCH && select_fill != XHATCH)
- {
- plotted_on (1); /* mark plot as dirty */
- return; /* for now, only hatched or cross-hatched fill */
- }
- theta = fill_code [select_fill].opt2; /* theta */
-
- /* get current hatch spacing in plotter units */
- /* for default units, calculate size now */
- switch (fill_code [select_fill].mode)
- {
- case DEFAULTUNITS:
- x_sp = 0.01 * sqrt ( (p2x - p1x) * (p2x - p1x) + (p2y - p1y) * (p2y - p1y));
- break;
- case PLOTTERUNITS:
- case USERUNITS:
- x_sp = fill_code [select_fill].alt_opt1;
- /* x-spacing is in plotter units */
- break;
- default: break;
- }
-
- plotter_units (&xp, &yp);
- plotter_units (&xc, &yc); /* corner coordinates in plotter units */
- fill_rect (xp, yp, xc, yc, x_sp, theta);
- if (select_fill == XHATCH) /* if cross-hatch, draw crossing hatch at theta + 90 */
- fill_rect (xp, yp, xc, yc, x_sp, theta + 90.0);
- }
- plotted_on (1); /* we drew something on this plot */
- return;
- }
-
- if (type & 0x10)
- {
- if (type & 1)
- print_string ("ER: missing argument\n");
- else
- print_string ("EA: missing argument\n");
- }
- else
- {
- if (type & 1)
- print_string ("RR: missing argument\n");
- else
- print_string ("RA: missing argument\n");
- }
-
- return;
- }
-
- /*--------------------------------------*/
-
- static void fill_rect (double x_1, double y_1, double x_2, double y_2, double x_sp, double theta)
- {
- double ymin, ymax, xmin, xmax;
- double xd1, yd1, xd2, yd2, ac_x, ac_y, x_off, xh;
- double yh, yi, xi, y_off, xlast, ylast, etan, ecot, theta_r;
- int n, sector;
-
- get_anchor (&ac_x, &ac_y); /* get anchor corner in plotter units */
- /* x_sp, x_1, x_2, y_1, y_2 all in plotter units */
-
- xmin = x_1;
- ymin = y_1;
- xmax = x_2;
- ymax = y_2;
-
- DB (printf ("hatch_fill: x_sp = %lf, theta = %lf\n", x_sp, theta);)
-
- theta = fmod (theta, 180.0);
- theta_r = theta / RAD_2_DEG;
-
- if (theta < 90.0)
- { /* sectors 1,5 */
- if (theta < 45.0)
- {
- sector = 1;
- yi = (x_1 - ac_x) * tan (theta_r) + ac_y;
- yh = x_sp / cos (theta_r); /* this fails at theta = 90 */
-
- y_off = fmod (y_2 - yi, yh); /* get distance below top edge for starting point */
-
- y_1 = ymax - y_off;
-
- if (y_1 > ymax) y_1 -= yh; /* check case of yi > y_1 */
- if (y_1 < ymin) y_1 += yh; /* check case of yi < y_1 */
- y_2 = y_1 + (xmax - xmin) * tan (theta_r);
- }
- else
- { /* sectors 2, 6 */
- sector = 2;
- xi = (y_1 - ac_y) * cot (theta_r) + ac_x;
- xh = x_sp / sin (theta_r); /* this fails at theta = 0 */
-
- x_off = fmod (x_2 - xi, xh); /* get distance inside of right edge for starting point */
-
- x_1 = xmax - x_off;
- if (x_1 > xmax) x_1 -= xh; /* check case of xi > x_1 */
- if (x_1 < xmin) x_1 += xh; /* check case of xi < x_1 */
- x_2 = x_1 + (ymax - ymin) * cot (theta_r);
- }
-
- }
- else /* sectors 4,8 */
- {
- if (theta > 135.0)
- {
- sector = 4;
- yi = (x_2 - ac_x) * tan (theta_r) + ac_y;
- yh = - x_sp / cos (theta_r); /* this fails at theta = 90 */
-
- /* get distance above bottom edge for starting point */
- y_off = fmod (y_2 - yi, yh);
-
- y_1 = ymax - y_off;
- if (y_1 > ymax) y_1 -= yh; /* check case of yi > y_1 */
- if (y_1 < ymin) y_1 += yh; /* check case of yi < y_1 */
- y_2 = y_1 - (xmax - xmin) * tan (theta_r);
- /* tan (theta) < 0 for 90 <= theta < 180 */
-
- xmin = x_2;
- xmax = x_1;
- }
- else
- { /* sectors 3,7 */
- sector = 3;
- xi = (y_2 - ac_y) * cot (theta_r) + ac_x;
- xh = x_sp / sin (theta_r); /* this fails at theta = 0 */
-
- x_off = fmod (x_2 - xi, xh); /* get distance inside of right edge for starting point */
-
- x_1 = xmax - x_off;
-
- if (x_1 > xmax) x_1 -= xh; /* check case of xi > x_1 */
- if (x_1 < xmin) x_1 += xh; /* check case of xi < x_1 */
- x_2 = x_1 - (ymax - ymin) * cot (theta_r);
-
- ymax = y_1;
- ymin = y_2;
- }
-
- }
-
-
- if (x_sp == 0.0) return; /* no point in wasting time */
-
- where (&xlast, &ylast); /* get current position */
-
- n = 0; /* emergency break-out counter */
-
- if (sector == 1 || sector == 4)
- {
- etan = tan (theta_r);
- while (y_2 > ymin && n < 2048) /* this loop only works for 0 <= theta < 90 */
- {
- ++n;
- xd1 = xmin;
- yd1 = y_1;
- xd2 = xmax;
- yd2 = y_2;
-
- if (yd2 > ymax)
- {
- yd2 = ymax;
- xd2 = xmin + (yd2 - y_1) / etan;
- } /* never reach this case if theta == 0 since */
- /* y_1 == y_2 and y_1 < ymax */
-
- if (yd1 < ymin)
- {
- yd1 = ymin;
- xd1 = xmin + (ymin - y_1) / etan;
- } /* never reach this case if theta == 0 since y_2 == y_1 */
- /* and loop begins with y_1 >= ymin */
-
- move (xd1, yd1);
- draw (xd2, yd2);
- y_1 -= yh;
- y_2 -= yh;
- }
- }
- else /* sectors 2, 3 */
- {
- ecot = cot (theta_r);
- while (x_2 > xmin && n < 2048) /* this loop decrements x sizes */
- {
- ++n;
- xd1 = x_1;
- yd1 = ymin;
- xd2 = x_2;
- yd2 = ymax;
-
- if (xd2 > xmax)
- {
- xd2 = xmax;
- yd2 = ymin + (xd2 - x_1) / ecot;
- } /* never reach this case if theta == 0 since */
- /* x_1 == x_2 and x_1 < xmax */
-
- if (xd1 < xmin)
- {
- xd1 = xmin;
- yd1 = ymin + (xmin - x_1) / ecot;
- } /* never reach this case if theta == 0 since y_2 == y_1 */
- /* and loop begins with x_1 >= xmin */
-
- move (xd1, yd1);
- draw (xd2, yd2);
- x_1 -= xh;
- x_2 -= xh;
- }
- }
-
- move (xlast, ylast); /* return to original position */
- }
-
- /*-------------------------------------*/
-
- static double cot ( double theta )
- { /* valid from 0 to 180 degrees */
- double a;
-
- a = cos (theta);
- return ( a * sqrt ( 1.0 - a * a));
- }
-
- /*--------------------------------------*/
-
- void draw_wedge (FILE * infile)
- {
- double radius, xc, yc, x_1, y_1, val4, ang1, ang2, ang3;
- int segs;
-
- DB (printf ("EW\n");)
- if (!get_val (infile, &radius))
- {
- print_string ("EW: missing radius\n");
- return; /* illegal instr */
- }
- if (!get_val (infile, &ang1))
- {
- print_string ("EW: missing start_ang\n");
- return; /* illegal instr */
- }
- if (!get_val (infile, &ang2)) /* arc angle */
- {
- print_string ("EW: missing sweep angle\n");
- return; /* illegal instr */
- }
- where (&xc, &yc); /* get starting point */
- DB (printf ("center: (x,y) = (%lf, %lf), start angle = %lf\n", xc, yc, ang1);)
-
- ang3 = val4 = DEF_CHORD; /* set default chord angle or deviation */
- if (get_val (infile, &val4))
- {
- val4 = fabs (val4); /* only positive values allowed */
- if (chord_type) /* using angles, not deviations */
- {
- ang3 = MIN (MAX_CHORD, (MAX (val4, MIN_CHORD)));
- }
- else /* chord angle determined by deviation of segments from circle radius */
- { /* at this point, val4 is length in current units, not angle in degrees */
- if (val4 > 2.0 * radius) val4 = 2.0 * radius; /* limit deviation: resulting chord angle < 180 deg. */
- ang3 = RAD_2_DEG * acos ( (radius - val4) / radius);
- }
- }
- segs = (int) (fabs (ang2) / ang3 + 0.5); /* # segments in "ang1" deg. */
- /* sign of 'segs' changes direction of arc () */
-
- DB (printf ("chord = %lf, # segments = %d\n", ang3, segs);)
- DB (printf ("radius = %lf, start angle = %lf, stop angle = %lf\n", radius, ang1, ang1 + ang2);)
- x_1 = xc + radius * cos (ang1 / RAD_2_DEG);
- y_1 = yc + radius * sin (ang1 / RAD_2_DEG); /* position of start of arc */
-
- draw (x_1, y_1); /* draw line from center to start of arc */
- move (xc, yc);
- arc ( radius, segs, ang1, ang1 + ang2); /* draw arc: leaves pen at end of arc */
- draw (xc, yc); /* draw line from end of arc to center */
-
- if (symbol_mode)
- {
- symbol_mark (symbol);
- }
-
- plotted_on (1); /* we drew something on this plot */
- return;
- }
-
- /*--------------------------------------*/
-
- void chord_t (FILE * infile)
- {
- double x;
-
- if (get_val (infile, &x))
- {
- if (x == 1.0)
- {
- chord_type = LENGTH;
- return;
- }
- if (x != 0.0)
- {
- print_string ("CT: invalid argument\n");
- return;
- }
- }
- chord_type = ANG; /* chord type in degree's */
- return;
- }
-
- /*--------------------------------------*/
-