home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Der Mediaplex Sampler - Die 6 von Plex
/
6_v_plex.zip
/
6_v_plex
/
DISK2
/
MULTI_04
/
SHOWGL15.ZIP
/
HPGL1.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-27
|
30KB
|
1,056 lines
#pragma linesize(132) /* listing linewidth = 132 */
/* hpgl1.c Rev. A. 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 "graph.h" /* this must preceed hpgl.h */
#include "hpgl.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;
extern int debugging;
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 (!debugging) return; /* no output if not asked for */
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;
if (get_val (infile, &val4))
{
val4 = fabs (val4); /* only positive values allowed */
if (chord_type == ANG || val4 == 0.0) /* using angles, not deviations */
{
if (val4 == 0.0) val4 = DEF_CHORD; /* set default chord angle or deviation */
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 = acos ( (radius - val4) / radius) * RAD_2_DEG;
}
}
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");)
if (!get_val (infile, &radius))
{
print_string ("CI: radius not specified\n");
return; /* error: no param's */
}
ang2 = val2 = DEF_CHORD; /* default chord angle or deviation for circle/arc */
if ( get_val (infile, &val2))
{
val2 = fabs (val2); /* only positive values allowed */
if (chord_type == ANG || val2 == 0.0) /* using angles, not deviations */
{
if (val2 == 0.0) val2 = DEF_CHORD; /* set default chord angle or deviation */
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 = acos ( (radius - val2) / radius) * RAD_2_DEG;
}
}
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));
val5 = ang2 = DEF_CHORD;
if (get_val (infile, &val5))
{
val5 = fabs (val5); /* only positive values allowed */
/* note: if no tolerance is specified, the default is a
chord ANGLE of 5 DEGREES, regardless of chord_type */
if (chord_type == ANG || val5 == 0.0) /* using angles, not deviations */
{
if (val5 == 0.0) val5 = DEF_CHORD; /* set default chord angle */
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 = acos ( (radius - val5) / radius) * RAD_2_DEG;
/* note that this value is being left in radians (for now) */
}
}
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);)
val4 = ang3 = DEF_CHORD;
if (get_val (infile, &val4))
{
val4 = fabs (val4); /* only positive values allowed */
if (chord_type == ANG || val4 == 0.0) /* using angles, not deviations */
{
if (val4 == 0.0) val4 = DEF_CHORD; /* set default chord angle or deviation */
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 = acos ( (radius - val4) / radius) * RAD_2_DEG;
}
}
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;
}
/*--------------------------------------*/