diff options
Diffstat (limited to 'contrib/groff/grn/hgraph.cc')
-rw-r--r-- | contrib/groff/grn/hgraph.cc | 1043 |
1 files changed, 0 insertions, 1043 deletions
diff --git a/contrib/groff/grn/hgraph.cc b/contrib/groff/grn/hgraph.cc deleted file mode 100644 index db3bfef..0000000 --- a/contrib/groff/grn/hgraph.cc +++ /dev/null @@ -1,1043 +0,0 @@ -/* Last non-groff version: hgraph.c 1.14 (Berkeley) 84/11/27 - * - * This file contains the graphics routines for converting gremlin pictures - * to troff input. - */ - -#include "gprint.h" - -#ifdef NEED_DECLARATION_HYPOT -extern "C" { - double hypot(double, double); -} -#endif /* NEED_DECLARATION_HYPOT */ - -#define MAXVECT 40 -#define MAXPOINTS 200 -#define LINELENGTH 1 -#define PointsPerInterval 64 -#define pi 3.14159265358979324 -#define twopi (2.0 * pi) -#define len(a, b) hypot((double)(b.x-a.x), (double)(b.y-a.y)) - - -extern int dotshifter; /* for the length of dotted curves */ - -extern int style[]; /* line and character styles */ -extern double thick[]; -extern char *tfont[]; -extern int tsize[]; -extern int stipple_index[]; /* stipple font index for stipples 0 - 16 */ -extern char *stipple; /* stipple type (cf or ug) */ - - -extern double troffscale; /* imports from main.c */ -extern double linethickness; -extern int linmod; -extern int lastx; -extern int lasty; -extern int lastyline; -extern int ytop; -extern int ybottom; -extern int xleft; -extern int xright; -extern enum { - OUTLINE, FILL, BOTH -} polyfill; - -extern double adj1; -extern double adj2; -extern double adj3; -extern double adj4; -extern int res; - -void HGSetFont(int font, int size); -void HGPutText(int justify, POINT pnt, register char *string); -void HGSetBrush(int mode); -void tmove2(int px, int py); -void doarc(POINT cp, POINT sp, int angle); -void tmove(POINT * ptr); -void cr(void); -void drawwig(POINT * ptr); -void HGtline(int x1, int y1); -void dx(double x); -void dy(double y); -void HGArc(register int cx, register int cy, int px, int py, int angle); -void picurve(register int *x, register int *y, int npts); -void Paramaterize(int x[], int y[], float h[], int n); -void PeriodicSpline(float h[], int z[], - float dz[], float d2z[], float d3z[], - int npoints); -void NaturalEndSpline(float h[], int z[], - float dz[], float d2z[], float d3z[], - int npoints); - - - -/*----------------------------------------------------------------------------* - | Routine: HGPrintElt (element_pointer, baseline) - | - | Results: Examines a picture element and calls the appropriate - | routine(s) to print them according to their type. After the - | picture is drawn, current position is (lastx, lasty). - *----------------------------------------------------------------------------*/ - -void -HGPrintElt(ELT *element, - int baseline) -{ - register POINT *p1; - register POINT *p2; - register int length; - register int graylevel; - - if (!DBNullelt(element) && !Nullpoint((p1 = element->ptlist))) { - /* p1 always has first point */ - if (TEXT(element->type)) { - HGSetFont(element->brushf, element->size); - switch (element->size) { - case 1: - p1->y += adj1; - break; - case 2: - p1->y += adj2; - break; - case 3: - p1->y += adj3; - break; - case 4: - p1->y += adj4; - break; - default: - break; - } - HGPutText(element->type, *p1, element->textpt); - } else { - if (element->brushf) /* if there is a brush, the */ - HGSetBrush(element->brushf); /* graphics need it set */ - - switch (element->type) { - - case ARC: - p2 = PTNextPoint(p1); - tmove(p2); - doarc(*p1, *p2, element->size); - cr(); - break; - - case CURVE: - length = 0; /* keep track of line length */ - drawwig(p1); - cr(); - break; - - case VECTOR: - length = 0; /* keep track of line length so */ - tmove(p1); /* single lines don't get long */ - while (!Nullpoint((p1 = PTNextPoint(p1)))) { - HGtline((int) (p1->x * troffscale), - (int) (p1->y * troffscale)); - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } /* end while */ - cr(); - break; - - case POLYGON: - { - /* brushf = style of outline; size = color of fill: - * on first pass (polyfill=FILL), do the interior using 'P' - * unless size=0 - * on second pass (polyfill=OUTLINE), do the outline using a series - * of vectors. It might make more sense to use \D'p ...', - * but there is no uniform way to specify a 'fill character' - * that prints as 'no fill' on all output devices (and - * stipple fonts). - * If polyfill=BOTH, just use the \D'p ...' command. - */ - float firstx = p1->x; - float firsty = p1->y; - - length = 0; /* keep track of line length so */ - /* single lines don't get long */ - - if (polyfill == FILL || polyfill == BOTH) { - /* do the interior */ - char command = (polyfill == BOTH && element->brushf) ? 'p' : 'P'; - - /* include outline, if there is one and */ - /* the -p flag was set */ - - /* switch based on what gremlin gives */ - switch (element->size) { - case 1: - graylevel = 1; - break; - case 3: - graylevel = 2; - break; - case 12: - graylevel = 3; - break; - case 14: - graylevel = 4; - break; - case 16: - graylevel = 5; - break; - case 19: - graylevel = 6; - break; - case 21: - graylevel = 7; - break; - case 23: - graylevel = 8; - break; - default: /* who's giving something else? */ - graylevel = NSTIPPLES; - break; - } - /* int graylevel = element->size; */ - - if (graylevel < 0) - break; - if (graylevel > NSTIPPLES) - graylevel = NSTIPPLES; - printf("\\h'-%du'\\D'f %du'", - stipple_index[graylevel], - stipple_index[graylevel]); - cr(); - tmove(p1); - printf("\\D'%c", command); - - while (!Nullpoint((PTNextPoint(p1)))) { - p1 = PTNextPoint(p1); - dx((double) p1->x); - dy((double) p1->y); - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } /* end while */ - - /* close polygon if not done so by user */ - if ((firstx != p1->x) || (firsty != p1->y)) { - dx((double) firstx); - dy((double) firsty); - } - putchar('\''); - cr(); - break; - } - /* else polyfill == OUTLINE; only draw the outline */ - if (!(element->brushf)) - break; - length = 0; /* keep track of line length */ - tmove(p1); - - while (!Nullpoint((PTNextPoint(p1)))) { - p1 = PTNextPoint(p1); - HGtline((int) (p1->x * troffscale), - (int) (p1->y * troffscale)); - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } /* end while */ - - /* close polygon if not done so by user */ - if ((firstx != p1->x) || (firsty != p1->y)) { - HGtline((int) (firstx * troffscale), - (int) (firsty * troffscale)); - } - cr(); - break; - } /* end case POLYGON */ - } /* end switch */ - } /* end else Text */ - } /* end if */ -} /* end PrintElt */ - - -/*----------------------------------------------------------------------------* - | Routine: HGPutText (justification, position_point, string) - | - | Results: Given the justification, a point to position with, and a - | string to put, HGPutText first sends the string into a - | diversion, moves to the positioning point, then outputs - | local vertical and horizontal motions as needed to justify - | the text. After all motions are done, the diversion is - | printed out. - *----------------------------------------------------------------------------*/ - -void -HGPutText(int justify, - POINT pnt, - register char *string) -{ - int savelasty = lasty; /* vertical motion for text is to be */ - /* ignored. Save current y here */ - - printf(".nr g8 \\n(.d\n"); /* save current vertical position. */ - printf(".ds g9 \""); /* define string containing the text. */ - while (*string) { /* put out the string */ - if (*string == '\\' && - *(string + 1) == '\\') { /* one character at a */ - printf("\\\\\\"); /* time replacing // */ - string++; /* by //// to prevent */ - } /* interpretation at */ - printf("%c", *(string++)); /* printout time */ - } - printf("\n"); - - tmove(&pnt); /* move to positioning point */ - - switch (justify) { - /* local vertical motions */ - /* (the numbers here are used to be somewhat compatible with gprint) */ - case CENTLEFT: - case CENTCENT: - case CENTRIGHT: - printf("\\v'0.85n'"); /* down half */ - break; - - case TOPLEFT: - case TOPCENT: - case TOPRIGHT: - printf("\\v'1.7n'"); /* down whole */ - } - - switch (justify) { - /* local horizontal motions */ - case BOTCENT: - case CENTCENT: - case TOPCENT: - printf("\\h'-\\w'\\*(g9'u/2u'"); /* back half */ - break; - - case BOTRIGHT: - case CENTRIGHT: - case TOPRIGHT: - printf("\\h'-\\w'\\*(g9'u'"); /* back whole */ - } - - printf("\\&\\*(g9\n"); /* now print the text. */ - printf(".sp |\\n(g8u\n"); /* restore vertical position */ - lasty = savelasty; /* vertical position restored to where it */ - lastx = xleft; /* was before text, also horizontal is at */ - /* left */ -} /* end HGPutText */ - - -/*----------------------------------------------------------------------------* - | Routine: doarc (center_point, start_point, angle) - | - | Results: Produces either drawarc command or a drawcircle command - | depending on the angle needed to draw through. - *----------------------------------------------------------------------------*/ - -void -doarc(POINT cp, - POINT sp, - int angle) -{ - if (angle) /* arc with angle */ - HGArc((int) (cp.x * troffscale), (int) (cp.y * troffscale), - (int) (sp.x * troffscale), (int) (sp.y * troffscale), angle); - else /* a full circle (angle == 0) */ - HGArc((int) (cp.x * troffscale), (int) (cp.y * troffscale), - (int) (sp.x * troffscale), (int) (sp.y * troffscale), 0); -} - - -/*----------------------------------------------------------------------------* - | Routine: HGSetFont (font_number, Point_size) - | - | Results: ALWAYS outputs a .ft and .ps directive to troff. This is - | done because someone may change stuff inside a text string. - | Changes thickness back to default thickness. Default - | thickness depends on font and pointsize. - *----------------------------------------------------------------------------*/ - -void -HGSetFont(int font, - int size) -{ - printf(".ft %s\n" - ".ps %d\n", tfont[font - 1], tsize[size - 1]); - linethickness = DEFTHICK; -} - - -/*----------------------------------------------------------------------------* - | Routine: HGSetBrush (line_mode) - | - | Results: Generates the troff commands to set up the line width and - | style of subsequent lines. Does nothing if no change is - | needed. - | - | Side Efct: Sets `linmode' and `linethicknes'. - *----------------------------------------------------------------------------*/ - -void -HGSetBrush(int mode) -{ - register int printed = 0; - - if (linmod != style[--mode]) { - /* Groff doesn't understand \Ds, so we take it out */ - /* printf ("\\D's %du'", linmod = style[mode]); */ - linmod = style[mode]; - printed = 1; - } - if (linethickness != thick[mode]) { - linethickness = thick[mode]; - printf("\\h'-%.2fp'\\D't %.2fp'", linethickness, linethickness); - printed = 1; - } - if (printed) - cr(); -} - - -/*----------------------------------------------------------------------------* - | Routine: dx (x_destination) - | - | Results: Scales and outputs a number for delta x (with a leading - | space) given `lastx' and x_destination. - | - | Side Efct: Resets `lastx' to x_destination. - *----------------------------------------------------------------------------*/ - -void -dx(double x) -{ - register int ix = (int) (x * troffscale); - - printf(" %du", ix - lastx); - lastx = ix; -} - - -/*----------------------------------------------------------------------------* - | Routine: dy (y_destination) - | - | Results: Scales and outputs a number for delta y (with a leading - | space) given `lastyline' and y_destination. - | - | Side Efct: Resets `lastyline' to y_destination. Since `line' vertical - | motions don't affect `page' ones, `lasty' isn't updated. - *----------------------------------------------------------------------------*/ - -void -dy(double y) -{ - register int iy = (int) (y * troffscale); - - printf(" %du", iy - lastyline); - lastyline = iy; -} - - -/*----------------------------------------------------------------------------* - | Routine: tmove2 (px, py) - | - | Results: Produces horizontal and vertical moves for troff given the - | pair of points to move to and knowing the current position. - | Also puts out a horizontal move to start the line. This is - | a variation without the .sp command. - *----------------------------------------------------------------------------*/ - -void -tmove2(int px, - int py) -{ - register int dx; - register int dy; - - if ((dy = py - lasty)) { - printf("\\v'%du'", dy); - } - lastyline = lasty = py; /* lasty is always set to current */ - if ((dx = px - lastx)) { - printf("\\h'%du'", dx); - lastx = px; - } -} - - -/*----------------------------------------------------------------------------* - | Routine: tmove (point_pointer) - | - | Results: Produces horizontal and vertical moves for troff given the - | pointer of a point to move to and knowing the current - | position. Also puts out a horizontal move to start the - | line. - *----------------------------------------------------------------------------*/ - -void -tmove(POINT * ptr) -{ - register int ix = (int) (ptr->x * troffscale); - register int iy = (int) (ptr->y * troffscale); - register int dx; - register int dy; - - if ((dy = iy - lasty)) { - printf(".sp %du\n", dy); - } - lastyline = lasty = iy; /* lasty is always set to current */ - if ((dx = ix - lastx)) { - printf("\\h'%du'", dx); - lastx = ix; - } -} - - -/*----------------------------------------------------------------------------* - | Routine: cr ( ) - | - | Results: Ends off an input line. `.sp -1' is also added to counteract - | the vertical move done at the end of text lines. - | - | Side Efct: Sets `lastx' to `xleft' for troff's return to left margin. - *----------------------------------------------------------------------------*/ - -void -cr(void) -{ - printf("\n.sp -1\n"); - lastx = xleft; -} - - -/*----------------------------------------------------------------------------* - | Routine: line ( ) - | - | Results: Draws a single solid line to (x,y). - *----------------------------------------------------------------------------*/ - -void -line(int px, - int py) -{ - printf("\\D'l"); - printf(" %du", px - lastx); - printf(" %du'", py - lastyline); - lastx = px; - lastyline = lasty = py; -} - - -/*---------------------------------------------------------------------------- - | Routine: drawwig (ptr) - | - | Results: The point sequence found in the structure pointed by ptr is - | placed in integer arrays for further manipulation by the - | existing routing. With the proper parameters, HGCurve is - | called. - *----------------------------------------------------------------------------*/ - -void -drawwig(POINT * ptr) -{ - register int npts; /* point list index */ - int x[MAXPOINTS], y[MAXPOINTS]; /* point list */ - - for (npts = 1; !Nullpoint(ptr); ptr = PTNextPoint(ptr), npts++) { - x[npts] = (int) (ptr->x * troffscale); - y[npts] = (int) (ptr->y * troffscale); - } - if (--npts) { - /* HGCurve(&x[0], &y[0], npts); */ /*Gremlin looks different, so... */ - picurve(&x[0], &y[0], npts); - } -} - - -/*---------------------------------------------------------------------------- - | Routine: HGArc (xcenter, ycenter, xstart, ystart, angle) - | - | Results: This routine plots an arc centered about (cx, cy) counter - | clockwise starting from the point (px, py) through `angle' - | degrees. If angle is 0, a full circle is drawn. It does so - | by creating a draw-path around the arc whose density of - | points depends on the size of the arc. - *----------------------------------------------------------------------------*/ - -void -HGArc(register int cx, - register int cy, - int px, - int py, - int angle) -{ - double xs, ys, resolution, fullcircle; - int m; - register int mask; - register int extent; - register int nx; - register int ny; - register int length; - register double epsilon; - - xs = px - cx; - ys = py - cy; - - length = 0; - - resolution = (1.0 + hypot(xs, ys) / res) * PointsPerInterval; - /* mask = (1 << (int) log10(resolution + 1.0)) - 1; */ - (void) frexp(resolution, &m); /* A bit more elegant than log10 */ - for (mask = 1; mask < m; mask = mask << 1); - mask -= 1; - - epsilon = 1.0 / resolution; - fullcircle = (2.0 * pi) * resolution; - if (angle == 0) - extent = (int) fullcircle; - else - extent = (int) (angle * fullcircle / 360.0); - - HGtline(px, py); - while (--extent >= 0) { - xs += epsilon * ys; - nx = cx + (int) (xs + 0.5); - ys -= epsilon * xs; - ny = cy + (int) (ys + 0.5); - if (!(extent & mask)) { - HGtline(nx, ny); /* put out a point on circle */ - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } - } /* end for */ -} /* end HGArc */ - - -/*---------------------------------------------------------------------------- - | Routine: picurve (xpoints, ypoints, num_of_points) - | - | Results: Draws a curve delimited by (not through) the line segments - | traced by (xpoints, ypoints) point list. This is the `Pic' - | style curve. - *----------------------------------------------------------------------------*/ - -void -picurve(register int *x, - register int *y, - int npts) -{ - register int nseg; /* effective resolution for each curve */ - register int xp; /* current point (and temporary) */ - register int yp; - int pxp, pyp; /* previous point (to make lines from) */ - int i; /* inner curve segment traverser */ - int length = 0; - double w; /* position factor */ - double t1, t2, t3; /* calculation temps */ - - if (x[1] == x[npts] && y[1] == y[npts]) { - x[0] = x[npts - 1]; /* if the lines' ends meet, make */ - y[0] = y[npts - 1]; /* sure the curve meets */ - x[npts + 1] = x[2]; - y[npts + 1] = y[2]; - } else { /* otherwise, make the ends of the */ - x[0] = x[1]; /* curve touch the ending points of */ - y[0] = y[1]; /* the line segments */ - x[npts + 1] = x[npts]; - y[npts + 1] = y[npts]; - } - - pxp = (x[0] + x[1]) / 2; /* make the last point pointers */ - pyp = (y[0] + y[1]) / 2; /* point to the start of the 1st line */ - tmove2(pxp, pyp); - - for (; npts--; x++, y++) { /* traverse the line segments */ - xp = x[0] - x[1]; - yp = y[0] - y[1]; - nseg = (int) hypot((double) xp, (double) yp); - xp = x[1] - x[2]; - yp = y[1] - y[2]; - /* `nseg' is the number of line */ - /* segments that will be drawn for */ - /* each curve segment. */ - nseg = (int) ((double) (nseg + (int) hypot((double) xp, (double) yp)) / - res * PointsPerInterval); - - for (i = 1; i < nseg; i++) { - w = (double) i / (double) nseg; - t1 = w * w; - t3 = t1 + 1.0 - (w + w); - t2 = 2.0 - (t3 + t1); - xp = (((int) (t1 * x[2] + t2 * x[1] + t3 * x[0])) + 1) / 2; - yp = (((int) (t1 * y[2] + t2 * y[1] + t3 * y[0])) + 1) / 2; - - HGtline(xp, yp); - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } - } -} - - -/*---------------------------------------------------------------------------- - | Routine: HGCurve(xpoints, ypoints, num_points) - | - | Results: This routine generates a smooth curve through a set of - | points. The method used is the parametric spline curve on - | unit knot mesh described in `Spline Curve Techniques' by - | Patrick Baudelaire, Robert Flegal, and Robert Sproull -- - | Xerox Parc. - *----------------------------------------------------------------------------*/ - -void -HGCurve(int *x, - int *y, - int numpoints) -{ - float h[MAXPOINTS], dx[MAXPOINTS], dy[MAXPOINTS]; - float d2x[MAXPOINTS], d2y[MAXPOINTS], d3x[MAXPOINTS], d3y[MAXPOINTS]; - float t, t2, t3; - register int j; - register int k; - register int nx; - register int ny; - int lx, ly; - int length = 0; - - lx = x[1]; - ly = y[1]; - tmove2(lx, ly); - - /* - * Solve for derivatives of the curve at each point separately for x and y - * (parametric). - */ - Paramaterize(x, y, h, numpoints); - - /* closed curve */ - if ((x[1] == x[numpoints]) && (y[1] == y[numpoints])) { - PeriodicSpline(h, x, dx, d2x, d3x, numpoints); - PeriodicSpline(h, y, dy, d2y, d3y, numpoints); - } else { - NaturalEndSpline(h, x, dx, d2x, d3x, numpoints); - NaturalEndSpline(h, y, dy, d2y, d3y, numpoints); - } - - /* - * generate the curve using the above information and PointsPerInterval - * vectors between each specified knot. - */ - - for (j = 1; j < numpoints; ++j) { - if ((x[j] == x[j + 1]) && (y[j] == y[j + 1])) - continue; - for (k = 0; k <= PointsPerInterval; ++k) { - t = (float) k *h[j] / (float) PointsPerInterval; - t2 = t * t; - t3 = t * t * t; - nx = x[j] + (int) (t * dx[j] + t2 * d2x[j] / 2 + t3 * d3x[j] / 6); - ny = y[j] + (int) (t * dy[j] + t2 * d2y[j] / 2 + t3 * d3y[j] / 6); - HGtline(nx, ny); - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } /* end for k */ - } /* end for j */ -} /* end HGCurve */ - - -/*---------------------------------------------------------------------------- - | Routine: Paramaterize (xpoints, ypoints, hparams, num_points) - | - | Results: This routine calculates parameteric values for use in - | calculating curves. The parametric values are returned - | in the array h. The values are an approximation of - | cumulative arc lengths of the curve (uses cord length). - | For additional information, see paper cited below. - *----------------------------------------------------------------------------*/ - -void -Paramaterize(int x[], - int y[], - float h[], - int n) -{ - register int dx; - register int dy; - register int i; - register int j; - float u[MAXPOINTS]; - - for (i = 1; i <= n; ++i) { - u[i] = 0; - for (j = 1; j < i; j++) { - dx = x[j + 1] - x[j]; - dy = y[j + 1] - y[j]; - /* Here was overflowing, so I changed it. */ - /* u[i] += sqrt ((double) (dx * dx + dy * dy)); */ - u[i] += hypot((double) dx, (double) dy); - } - } - for (i = 1; i < n; ++i) - h[i] = u[i + 1] - u[i]; -} /* end Paramaterize */ - - -/*---------------------------------------------------------------------------- - | Routine: PeriodicSpline (h, z, dz, d2z, d3z, npoints) - | - | Results: This routine solves for the cubic polynomial to fit a spline - | curve to the the points specified by the list of values. - | The Curve generated is periodic. The algorithms for this - | curve are from the `Spline Curve Techniques' paper cited - | above. - *----------------------------------------------------------------------------*/ - -void -PeriodicSpline(float h[], /* paramaterization */ - int z[], /* point list */ - float dz[], /* to return the 1st derivative */ - float d2z[], /* 2nd derivative */ - float d3z[], /* 3rd derivative */ - int npoints) /* number of valid points */ -{ - float d[MAXPOINTS]; - float deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS]; - float c[MAXPOINTS], r[MAXPOINTS], s[MAXPOINTS]; - int i; - - /* step 1 */ - for (i = 1; i < npoints; ++i) { - deltaz[i] = h[i] ? ((double) (z[i + 1] - z[i])) / h[i] : 0; - } - h[0] = h[npoints - 1]; - deltaz[0] = deltaz[npoints - 1]; - - /* step 2 */ - for (i = 1; i < npoints - 1; ++i) { - d[i] = deltaz[i + 1] - deltaz[i]; - } - d[0] = deltaz[1] - deltaz[0]; - - /* step 3a */ - a[1] = 2 * (h[0] + h[1]); - b[1] = d[0]; - c[1] = h[0]; - for (i = 2; i < npoints - 1; ++i) { - a[i] = 2 * (h[i - 1] + h[i]) - - pow((double) h[i - 1], (double) 2.0) / a[i - 1]; - b[i] = d[i - 1] - h[i - 1] * b[i - 1] / a[i - 1]; - c[i] = -h[i - 1] * c[i - 1] / a[i - 1]; - } - - /* step 3b */ - r[npoints - 1] = 1; - s[npoints - 1] = 0; - for (i = npoints - 2; i > 0; --i) { - r[i] = -(h[i] * r[i + 1] + c[i]) / a[i]; - s[i] = (6 * b[i] - h[i] * s[i + 1]) / a[i]; - } - - /* step 4 */ - d2z[npoints - 1] = (6 * d[npoints - 2] - h[0] * s[1] - - h[npoints - 1] * s[npoints - 2]) - / (h[0] * r[1] + h[npoints - 1] * r[npoints - 2] - + 2 * (h[npoints - 2] + h[0])); - for (i = 1; i < npoints - 1; ++i) { - d2z[i] = r[i] * d2z[npoints - 1] + s[i]; - } - d2z[npoints] = d2z[1]; - - /* step 5 */ - for (i = 1; i < npoints; ++i) { - dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i + 1]) / 6; - d3z[i] = h[i] ? (d2z[i + 1] - d2z[i]) / h[i] : 0; - } -} /* end PeriodicSpline */ - - -/*---------------------------------------------------------------------------- - | Routine: NaturalEndSpline (h, z, dz, d2z, d3z, npoints) - | - | Results: This routine solves for the cubic polynomial to fit a spline - | curve the the points specified by the list of values. The - | alogrithms for this curve are from the `Spline Curve - | Techniques' paper cited above. - *----------------------------------------------------------------------------*/ - -void -NaturalEndSpline(float h[], /* parameterization */ - int z[], /* Point list */ - float dz[], /* to return the 1st derivative */ - float d2z[], /* 2nd derivative */ - float d3z[], /* 3rd derivative */ - int npoints) /* number of valid points */ -{ - float d[MAXPOINTS]; - float deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS]; - int i; - - /* step 1 */ - for (i = 1; i < npoints; ++i) { - deltaz[i] = h[i] ? ((double) (z[i + 1] - z[i])) / h[i] : 0; - } - deltaz[0] = deltaz[npoints - 1]; - - /* step 2 */ - for (i = 1; i < npoints - 1; ++i) { - d[i] = deltaz[i + 1] - deltaz[i]; - } - d[0] = deltaz[1] - deltaz[0]; - - /* step 3 */ - a[0] = 2 * (h[2] + h[1]); - b[0] = d[1]; - for (i = 1; i < npoints - 2; ++i) { - a[i] = 2 * (h[i + 1] + h[i + 2]) - - pow((double) h[i + 1], (double) 2.0) / a[i - 1]; - b[i] = d[i + 1] - h[i + 1] * b[i - 1] / a[i - 1]; - } - - /* step 4 */ - d2z[npoints] = d2z[1] = 0; - for (i = npoints - 1; i > 1; --i) { - d2z[i] = (6 * b[i - 2] - h[i] * d2z[i + 1]) / a[i - 2]; - } - - /* step 5 */ - for (i = 1; i < npoints; ++i) { - dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i + 1]) / 6; - d3z[i] = h[i] ? (d2z[i + 1] - d2z[i]) / h[i] : 0; - } -} /* end NaturalEndSpline */ - - -/*----------------------------------------------------------------------------* - | Routine: change (x_position, y_position, visible_flag) - | - | Results: As HGtline passes from the invisible to visible (or vice - | versa) portion of a line, change is called to either draw - | the line, or initialize the beginning of the next one. - | Change calls line to draw segments if visible_flag is set - | (which means we're leaving a visible area). - *----------------------------------------------------------------------------*/ - -void -change(register int x, - register int y, - register int vis) -{ - static int length = 0; - - if (vis) { /* leaving a visible area, draw it. */ - line(x, y); - if (length++ > LINELENGTH) { - length = 0; - printf("\\\n"); - } - } else { /* otherwise, we're entering one, remember */ - /* beginning */ - tmove2(x, y); - } -} - - -/*---------------------------------------------------------------------------- - | Routine: HGtline (xstart, ystart, xend, yend) - | - | Results: Draws a line from current position to (x1,y1) using line(x1, - | y1) to place individual segments of dotted or dashed lines. - *----------------------------------------------------------------------------*/ - -void -HGtline(int x1, - int y1) -{ - register int x0 = lastx; - register int y0 = lasty; - register int dx; - register int dy; - register int oldcoord; - register int res1; - register int visible; - register int res2; - register int xinc; - register int yinc; - register int dotcounter; - - if (linmod == SOLID) { - line(x1, y1); - return; - } - - /* for handling different resolutions */ - dotcounter = linmod << dotshifter; - - xinc = 1; - yinc = 1; - if ((dx = x1 - x0) < 0) { - xinc = -xinc; - dx = -dx; - } - if ((dy = y1 - y0) < 0) { - yinc = -yinc; - dy = -dy; - } - res1 = 0; - res2 = 0; - visible = 0; - if (dx >= dy) { - oldcoord = y0; - while (x0 != x1) { - if ((x0 & dotcounter) && !visible) { - change(x0, y0, 0); - visible = 1; - } else if (visible && !(x0 & dotcounter)) { - change(x0 - xinc, oldcoord, 1); - visible = 0; - } - if (res1 > res2) { - oldcoord = y0; - res2 += dx - res1; - res1 = 0; - y0 += yinc; - } - res1 += dy; - x0 += xinc; - } - } else { - oldcoord = x0; - while (y0 != y1) { - if ((y0 & dotcounter) && !visible) { - change(x0, y0, 0); - visible = 1; - } else if (visible && !(y0 & dotcounter)) { - change(oldcoord, y0 - yinc, 1); - visible = 0; - } - if (res1 > res2) { - oldcoord = x0; - res2 += dy - res1; - res1 = 0; - x0 += xinc; - } - res1 += dx; - y0 += yinc; - } - } - if (visible) - change(x1, y1, 1); - else - change(x1, y1, 0); -} - -/* EOF */ |