date and time created 83/04/18 13:45:30 by slatteng
authorDave Slattengren <slatteng@ucbvax.Berkeley.EDU>
Tue, 19 Apr 1983 04:45:30 +0000 (20:45 -0800)
committerDave Slattengren <slatteng@ucbvax.Berkeley.EDU>
Tue, 19 Apr 1983 04:45:30 +0000 (20:45 -0800)
SCCS-vsn: local/ditroff/ditroff.old.okeeffe/gremlin.aed/gremlin/graphics2.c 1.1

usr/src/local/ditroff/ditroff.old.okeeffe/gremlin.aed/gremlin/graphics2.c [new file with mode: 0644]

diff --git a/usr/src/local/ditroff/ditroff.old.okeeffe/gremlin.aed/gremlin/graphics2.c b/usr/src/local/ditroff/ditroff.old.okeeffe/gremlin.aed/gremlin/graphics2.c
new file mode 100644 (file)
index 0000000..845b0c4
--- /dev/null
@@ -0,0 +1,509 @@
+\f
+/* graphics2.c
+ *
+ * Copyright -C- 1982 Barry S. Roitblat
+ *
+ * This file contains more routines for implementing the graphics primitives
+ * for the gremlin picture editor
+ *
+ * (Modified from software written by John Ousterhout for the caesar
+ *  program)
+ */
+
+#include "gremlin.h"
+#include "grem2.h"
+
+/* imports from graphics1.c */
+
+extern GRsetlinestyle(), GRsetcharstyle(), GRsetcharsize(),
+       GRsetpos(), GRoutxy20(), GRSetRead();
+extern FILE *display;
+extern int curx, cury, rmask, GrXMax, GrYMax, charysize, charxsize, descenders;
+
+/* imports from main.c */
+
+extern error();
+
+/* The following is available to the outside world */
+
+int artmode;
+
+GRVector(point1,point2,style)
+POINT *point1,*point2;
+int   style;
+{
+       GRsetlinestyle(style);
+       GRsetpos((int) point1->x,(int) point1->y);
+       putc('A',display);       /* Draw vector absolute */
+       GRoutxy20((int) point2->x,(int) point2->y);
+       curx = point2->x;
+       cury = point2->y;
+        (void) fflush(display);
+}
+
+\f
+static RelativeVector(x, y)
+float x, y;
+/*
+ *     This routine outputs the proper character sequence to the AED
+ * to draw a vector in the current line style and from the current position
+ * to the point (x, y).
+ */
+
+{
+       int nextx, nexty;
+
+       nextx = (int) x;
+       nexty = (int) y;
+
+       putc('A', display);  /* draw vector absolute */
+       GRoutxy20(nextx, nexty); /* output coordinates */
+       curx = nextx;
+       cury = nexty;
+}  /* end RelativeVector */
+
+\f
+#define pi 3.14159265357
+#define log2_10 3.321915
+
+int
+GRArc(center,cpoint,angle,style)
+POINT *center, *cpoint;
+double angle;
+int   style;
+{
+       double xs, ys, radius, resolution, t1, epsalon, fullcircle;
+       double degreesperpoint;
+       int    i, extent;
+       POINT  next;
+
+       xs = cpoint->x - center->x;
+       ys = cpoint->y - center->y;
+       if ((xs == 0) && (ys == 0))       /* radius = 0 */
+       {
+               error("zero radius");
+               return(-1);
+       }
+
+/* calculate drawing parameters */
+
+       radius = sqrt(xs * xs + ys * ys);
+       t1 = floor(log10(radius) * log2_10);
+       resolution = pow(2.0, t1);
+       epsalon = 1.0 / resolution;
+       fullcircle = ceil(2 * pi * resolution);
+       degreesperpoint = 360.0 / fullcircle;
+
+       if (angle == 0) 
+       {
+               extent = fullcircle;
+               if ( (int) radius < 128)    /* manageable by AED hardware */
+               {
+                       GRsetpos((int) center->x, (int) center->y);
+                       GRsetlinestyle(style);
+                       putc('O',display);  /* draw circle */
+                       putc(((int) radius) &0377, display); 
+                       return(0);
+               }
+       }
+       else extent = angle/degreesperpoint;
+
+        GRsetpos((int) cpoint->x, (int) cpoint->y);
+        GRsetlinestyle(style);
+       for (i=0; i<extent; ++i)
+       {
+               xs -= epsalon * ys;
+               next.x = xs + center->x ;   /* round */
+               ys += epsalon * xs;
+               next.y = ys + center->y ;   /* round */
+               RelativeVector(next.x, next.y);
+       }   /* end for */;
+       return(0);
+}  /* end GRArc */;
+
+\f
+#define MAXPOINTS 200
+
+static Paramaterize(x, y, h, n)
+float x[MAXPOINTS], y[MAXPOINTS], h[MAXPOINTS];
+int n;
+/*     This routine calculates parameteric values for use in calculating
+ * curves.  The parametric values are returned in the array u.  The values
+ * are an approximation of cumulative arc lengths of the curve (uses cord
+ * length).  For additional information, see paper cited below.
+ */
+
+{
+       int i,j;
+       float u[MAXPOINTS];
+
+       for (i=1; i<=n; ++i)
+       {
+               u[i] = 0;
+               for (j=1; j<i; ++j)
+               {
+                       u[i] += sqrt(pow((double) (x[j+1] - x[j]), (double) 2.0)
+                                + pow((double) (y[j+1] - y[j]), (double) 2.0));
+               }
+       }
+       for (i=1; i<n; ++i)
+               h[i] = u[i+1] - u[i];
+}  /* end Paramaterize */
+
+static PeriodicSpline(h, z, dz, d2z, d3z, npoints)
+float h[MAXPOINTS], z[MAXPOINTS];      /* Point list and paramaterization  */
+float dz[MAXPOINTS];                   /* to return the 1st derivative */
+float d2z[MAXPOINTS], d3z[MAXPOINTS];  /* 2nd and 3rd derivatives */
+int npoints;                           /* number of valid points */
+/*
+ *     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 alogrithms for this 
+ * curve are from the "Spline Curve Techniques" paper cited below.
+ */
+
+{
+       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)
+       {
+               if (h[i] != 0)
+                       deltaz[i] = (z[i+1] - z[i]) / h[i];
+               else
+                       deltaz[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]);
+       if (a[1] == 0) return(-1);  /* 3 consecutive knots at same point */
+       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];
+               if (a[i] == 0) return(-1);  /* 3 consec knots at same point */
+               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;
+               if (h[i] != 0)
+                       d3z[i] = (d2z[i+1] - d2z[i])/h[i];
+               else
+                       d3z[i] = 0;
+       }
+       return(0);
+}  /* end PeriodicSpline */
+
+\f
+static NaturalEndSpline(h, z, dz, d2z, d3z, npoints)
+float h[MAXPOINTS], z[MAXPOINTS];      /* Point list and parameterization */
+float dz[MAXPOINTS];                   /* to return the 1st derivative */
+float d2z[MAXPOINTS], d3z[MAXPOINTS];  /* 2nd and 3rd derivatives */
+int npoints;                           /* number of valid points */
+/*
+ *     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 below.
+ */
+
+{
+       float d[MAXPOINTS];
+       float deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS];
+       int i;
+
+                   /* step 1 */
+       for (i=1; i<npoints; ++i)
+       {
+               if (h[i] != 0)
+                       deltaz[i] = (z[i+1] - z[i]) / h[i];
+               else
+                       deltaz[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]);
+       if (a[0] == 0) return(-1);  /* 3 consec knots at same point */
+       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];
+               if (a[i] == 0) return(-1);  /* 3 consec knots at same point */
+               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;
+               if (h[i] != 0)
+                       d3z[i] = (d2z[i+1] - d2z[i])/h[i];
+               else
+                       d3z[i] = 0;
+       }
+       return(0);
+}  /* end NaturalEndSpline */
+
+\f
+#define PointsPerInterval 16
+
+GRCurve(pointlist,style)
+POINT *pointlist;
+int   style;
+/*
+ *    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.
+ */
+{
+       float h[MAXPOINTS];
+       float x[MAXPOINTS], y[MAXPOINTS], dx[MAXPOINTS], dy[MAXPOINTS];
+       float d2x[MAXPOINTS], d2y[MAXPOINTS], d3x[MAXPOINTS], d3y[MAXPOINTS];
+       float t, t2, t3, xinter, yinter;
+       POINT *ptr;
+       int numpoints, i, j, k, stat;
+
+       GRsetlinestyle(style);
+       GRsetpos((int) pointlist->x, (int) pointlist->y);
+
+              /* Copy point list to array for easier access */
+
+       ptr = pointlist;
+       for (i=1; (!Nullpoint(ptr)); ++i)
+       {
+               x[i] = ptr->x;
+               y[i] = ptr->y;
+               if (i >= MAXPOINTS - 1) break;
+               ptr = PTNextPoint(ptr);
+       }
+
+            /* Solve for derivatives of the curve at each point 
+              * separately for x and y (parametric).
+             */
+       numpoints = i - 1;
+       Paramaterize(x, y, h, numpoints);
+       stat = 0;
+       if ((x[1] == x[numpoints]) && (y[1] == y[numpoints]))/* closed curve */
+       {
+               stat |= PeriodicSpline(h, x, dx, d2x, d3x, numpoints);
+               stat |= PeriodicSpline(h, y, dy, d2y, d3y, numpoints);
+       }
+       else
+       {
+               stat |= NaturalEndSpline(h, x, dx, d2x, d3x, numpoints);
+               stat |= NaturalEndSpline(h, y, dy, d2y, d3y, numpoints);
+       }
+       if (stat != 0) return(-1);  /* error occurred */
+            
+             /* generate the curve using the above information and 
+              * PointsPerInterval vectors between each specified knot.
+              */
+
+       for (j=1; j<numpoints; ++j)
+       {
+               for (k=0; k<=PointsPerInterval; ++k)
+               {
+                       t = (float) k * h[j] / (float) PointsPerInterval;
+                       t2 = t * t;
+                       t3 = t * t * t;
+                       xinter = x[j] + t * dx[j] + t2 * d2x[j]/2.0
+                              + t3 * d3x[j]/6.0;
+                       yinter = y[j] + t * dy[j] + t2 * d2y[j]/2.0
+                              + t3 * d3y[j]/6.0;
+                       RelativeVector(xinter, yinter);
+               }  /* end for k */
+       }  /* end for j */
+       return(0);
+}  /* end GRCurve */
+
+
+\f
+GRPutText(justify,point1,font,size,string,pos)
+int justify, font, size;
+POINT *point1, *pos;
+char string[];
+{
+       int length, nchars, i;
+
+       GRsetcharstyle(font);
+       GRsetcharsize(size);
+       nchars = strlen(string);
+       length = nchars * charxsize ;
+        switch (justify)
+       {
+                 case BOTLEFT: pos->x = point1->x;
+                               pos->y = point1->y;
+                               break;
+                 case BOTCENT: pos->x = point1->x - (length/2);
+                               pos->y = point1->y;
+                               break;
+                case BOTRIGHT: pos->x = point1->x - length;
+                               pos->y = point1->y;
+                               break;
+                case CENTLEFT: pos->x = point1->x;
+                               pos->y = point1->y - (charysize/2);
+                               break;
+                case CENTCENT: pos->x = point1->x - (length/2);
+                               pos->y = point1->y - (charysize/2);
+                               break;
+               case CENTRIGHT: pos->x = point1->x - length;
+                               pos->y = point1->y - (charysize/2);
+                               break;
+                 case TOPLEFT: pos->x = point1->x;
+                               pos->y = point1->y - charysize + descenders;
+                               break;
+                 case TOPCENT: pos->x = point1->x - (length/2);
+                               pos->y = point1->y - charysize + descenders;
+                               break;
+                case TOPRIGHT: pos->x = point1->x - length;
+                               pos->y = point1->y - charysize + descenders;
+                               break;
+       }
+       if ((pos->x < 0) || ((pos->x + length - charxsize) > GrXMax))
+       {
+               TxPutMsg("\7string too long");
+       }
+       if (( pos->y + charysize ) > GrYMax )
+               pos->y = GrYMax - charysize;
+       if (pos->y < 0) pos->y = 0;
+       GRsetpos((int) pos->x, (int) pos->y);
+       putc('\6',display);    /* enter text mode */
+       for ( i=0; i<nchars; ++i )
+       {
+               putc(string[i],display);
+       }
+       fputs("\33Q", display);  /* re-enter graphics mode */
+       GRoutxy20(curx,cury);
+       (void) fflush(display);
+} /* end PutText */;
+
+\f
+GRClear(mask)
+int mask;
+/*
+ *      This routine clears the memory planes enabled by mask.
+ * The read mask is first set to avoid an annoying flash when the
+ * clear is performed.
+ */
+
+{
+       int savemask;
+
+       savemask = rmask;
+       GRSetRead(rmask & ~mask);
+       GRsetwmask(mask);
+       putc('~',display);
+       GRSetRead(savemask);
+       (void) fflush(display);
+}  /* end GRClear */
+
+GRDisplayPoint(x, y, number, mark)
+int x, y, number, mark;
+/*
+ *      This routine displays a point on the screen.  The point is
+ * displayed as a '+' centered about the point (x,y) and followed by
+ * number.
+ */
+
+{
+       POINT p1, p2;
+       int psize;
+
+       if (artmode) psize = 1;
+       else psize = halfpoint;
+       GRsetwmask(pointmask);
+       p1.y = p2.y = y;
+       p1.x = x - psize;
+       p2.x = x + psize;
+       GRVector(&p1, &p2, mark);
+       p1.x = p2.x = x;
+       p1.y = y - psize;
+       p2.y = y + psize;
+       GRVector(&p1, &p2, mark);
+       if ( !artmode )
+       {
+               GRsetcharsize(pointchar);
+               GRsetpos( (x + numspace), (y - charysize/2 + 1) );
+               fprintf(display,"\6%d\33",number);
+       }
+       GRsetpos(x, y);
+       (void) fflush(display);
+}  /* end DisplayPoint */
+
+
+\f
+GRErasePoint(x, y, number)
+int x, y, number;
+/*
+ *      This routine erases the specified point by redrawing it in the
+ * background color
+ */
+
+{
+       GRDisplayPoint(x, y, number, eraseany);
+}  /* end ErasePoint */
+
+
+GRBlankPoints()
+/*
+ *      This routine clears all displayed points by clearing
+ * the memory plane they are written on.
+ */
+
+{
+       GRClear(pointmask);
+}  /* end BlankPoints */