Super Plot (6 of 8)

Marc Majka majka at ubc-vision.UUCP
Mon Apr 28 08:52:17 AEST 1986


- - - CUT - - - CUT - - - CUT - - - CUT - - - CUT - - - CUT - - - CUT - - -
#!/bin/sh
#
# shell archive - extract with /bin/sh
#
echo Plot archive part 6 of 8
echo
echo extracting file rplfns.c
sed 's/^X//' > rplfns.c <<'!FUNKY!STUFF!'
X/*************************************************************/
X/*                                                           */
X/*  Copyright (c) 1986                                       */
X/*  Marc S. Majka - UBC Laboratory for Computational Vision  */
X/*                                                           */
X/*  Permission is hereby granted to copy all or any part of  */
X/*  this program for free distribution.   The author's name  */
X/*  and this copyright notice must be included in any copy.  */
X/*                                                           */
X/*************************************************************/
X
X/*************************************************************/
X/*                                                           */
X/*   NOTE: The code for the vector generator (DDA) and the   */
X/*   bspline generator is based on those published in:       */
X/*                                                           */
X/*   [1] Newman, W.M. and Sproull, R.F., "Principles of      */
X/*       Interactive Computer Graphics", McGraw-Hill,        */ 
X/*       New York, 1979.                                     */
X/*                                                           */
X/*************************************************************/
X
X#include <stdio.h>
X#define GMAX 512  /* Max grid size */
X#define FPMAX 32
X#define MAXPATS 128
X#define BPPMAX 16
X#define STACKSIZE 65536
X
X/* Plot structure: contains the raster (grid), min and max defined co-ords,
X   x and y ranges, current point and current gray level, a line-generator
X   mask and a pointer for that mask, image file pointer and annotation
X   record, and max row and col. */
X
Xstruct implstruct {
X    int grid[GMAX][GMAX];       /* image raster         */
X    double x1, y1, x2, y2;      /* min and max points   */
X    double xr, yr;              /* x and y range        */
X    double xc, yc;              /* current point        */
X    int uhv;                    /* user space hv        */
X    int ubpp;                   /* user bits per pixel  */
X    double ubppr;               /* user bpp range       */
X    int bx1, by1, bx2, by2;     /* polygon bounding box */
X    int patc;                   /* current fill pattern */
X    long gray;                  /* current gray level   */
X    long lgray, ogray;          /* temp grays for fill  */
X    char linemask[100];         /* line generator mask  */
X    int lmp;                    /* mask pointer         */
X    FILE *ifp;                  /* image file pointer   */
X    int r1, c1, r2, c2;         /* image max & min      */
X    int rc, cc;                 /* current row and col  */
X    int rr, cr;                 /* row and col range    */
X    int dhv;                    /* image is hv          */
X    int dbpp;                   /* image bits per pixel */
X    double dbppr;               /* image bpp range      */
X    int nrows, ncols, bpp       /* image size & bpp     */
X};
X
Xstruct implstruct impl;
X
Xstruct fpstruct {
X    char grid[FPMAX][FPMAX];
X    int nr, nc;
X};
X
Xstruct fpstruct fpat[MAXPATS];
X
Xstatic int stack[STACKSIZE][2], top, knotk, knotn;
X
X/************************************************************************/
X/* plotopen: open an image file for output, initialize plot structure   */
X/************************************************************************/
X
Xplotopen(fname)
Xchar *fname;
X{
X    FILE *fopen();
X    int r,c;
X    
X    if (fname[0] == '\0') impl.ifp = stdout;
X    else impl.ifp = fopen(fname,"w");
X
X    if (impl.ifp == NULL) {
X        fprintf(stderr,"plotopen: can't open output file %s\n",fname);
X        exit(1);
X    }
X    
X    /* defaults */
X    frame(0,0,255,255,0);
X    space(0,0,255,255,0);
X    bppout(8);
X    bppin(8);
X    move(0,0);
X    gray(255);
X    linemod("1");
X    fillpat(0,1,1,"1");
X    font("sr");
X    fspec(1.0,1.0,0.0);
X    
X    for (r = 0; r < GMAX; r++) 
X        for (c = 0; c < GMAX; c++) impl.grid[r][c] = 0;
X}
X
X/************************************************************************/
X/* frame: initialize number of x and y divisions in the output image    */
X/************************************************************************/
X
Xframe(x1,y1,x2,y2,hv)
Xint x1,y1,x2,y2,hv;
X{
X    impl.r1 = x1; impl.c1 = y1;
X    impl.r2 = x2; impl.c2 = y2;
X    impl.rr = x2 - x1; impl.cr = y2 - y1;
X    impl.nrows = 1 + abs((int)(x2-x1));
X    impl.ncols = 1 + abs((int)(y2-y1));
X
X    if (impl.nrows > GMAX) {
X        fprintf(stderr,"frame: nrows (%d) > max (%d)\n",
X            impl.nrows,GMAX);
X        exit(1);
X    }
X    if (impl.ncols > GMAX) {
X        fprintf(stderr,"frame: ncols (%d) > max (%d)\n",
X            impl.ncols,GMAX);
X        exit(1);
X    }
X}
X
X/************************************************************************/
X/* bppout: set number of bits per pixel for output                      */
X/************************************************************************/
X
Xbppout(b)
Xint b;
X{
X    if ((b < 1) || (b > BPPMAX)) {
X        fprintf(stderr,"bpp: %d BPP exceeds %d maximum\n",b,BPPMAX);
X        exit(1);
X    }
X        
X    impl.bpp = b;
X    impl.dbpp = b;
X    impl.lgray = 1 + (1 << b);
X    impl.dbppr = (1 << b) - 1;
X}
X
X/************************************************************************/
X/* bppin: set number of bits per pixel for input                        */
X/************************************************************************/
X
Xbppin(b)
Xint b;
X{
X    impl.ubpp = b;
X    impl.ubppr = (1 << b) - 1;
X}
X
X/************************************************************************/
X/* plotclose: write the image                                           */
X/************************************************************************/
X
Xplotclose()
X{
X    int i, j, p, bytes;
X    
X    bytes = impl.dbpp / 8;
X    if (bytes == 0) bytes = 1;
X    
X    impl.nrows = impl.nrows;
X    impl.ncols = impl.ncols;
X
X    for (i = 0; i < impl.nrows; i++)
X        for (j = 0; j < impl.ncols; j++) {
X            p = impl.grid[i][j];
X            fwrite(&p,bytes,1,impl.ifp);
X        }
X    
X    fclose(impl.ifp);
X}
X
X/************************************************************************/
X/* space: define x and y max and min. set x and y range                 */
X/************************************************************************/
X
Xspace(x1,y1,x2,y2,hv)
Xint x1, y1, x2, y2, hv;
X{
X    impl.x1 = x1; impl.y1 = y1;
X    impl.x2 = x2; impl.y2 = y2;
X    impl.xr = x2 - x1; 
X    impl.yr = y2 - y1; 
X    impl.uhv = hv;
X    move(x1,y1);
X    impl.bx1 = impl.x1; impl.by1 = impl.y1;
X    impl.bx2 = impl.x2; impl.by2 = impl.y2;
X    if (impl.xr == 0) impl.xr = 1;
X    if (impl.yr == 0) impl.yr = 1;
X}
X
Xhvmatch()
X{
X    if (impl.uhv == impl.dhv) return(1);
X    return(0);
X}
X
X/************************************************************************/
X/* erase: fill the grid with current gray level                         */
X/************************************************************************/
X
Xerase()
X{
X    int x, y, pc;
X    
X    pc = impl.patc;
X    
X    for (x = 0; x < impl.nrows; x++)
X        for (y = 0; y < impl.ncols; y++)
X            if (fpat[pc].grid[x % fpat[pc].nr][y % fpat[pc].nc])
X                impl.grid[x][y] = impl.gray;
X}
X
X/************************************************************************/
X/* move: change the current point to (x, y).                            */
X/************************************************************************/
X
Xmove(x,y)
Xint x, y;
X{
X    dblmove((double)x,(double)y);
X}
X
Xdblmove(x,y)
Xdouble x,y;
X{
X    impl.xc = x; impl.yc = y;
X    
X    if (impl.uhv != impl.dhv) {
X        impl.cc = impl.c1 + (impl.xc - impl.x1) * (impl.cr / impl.xr);
X        impl.rc = impl.r1 + (impl.yc - impl.y1) * (impl.rr / impl.yr);
X    }
X    else {
X        impl.rc = impl.r1 + (impl.xc - impl.x1) * (impl.rr / impl.xr);
X        impl.cc = impl.c1 + (impl.yc - impl.y1) * (impl.cr / impl.yr);
X    }
X
X    if (impl.xc < impl.bx1) impl.bx1 = impl.xc;
X    if (impl.yc < impl.by1) impl.by1 = impl.yc;
X    if (impl.xc > impl.bx2) impl.bx2 = impl.xc;
X    if (impl.yc > impl.by2) impl.by2 = impl.yc;
X}
X
X/************************************************************************/
X/* point: plot a point                                              */
X/************************************************************************/
X
Xpoint(x,y)
Xint x, y;
X{
X    move(x,y);
X    if ((impl.rc>=0)&&(impl.rc<=GMAX)&&(impl.cc>=0)&&(impl.cc<=GMAX))
X        impl.grid[impl.rc][impl.cc] = impl.gray;
X}
X
X/************************************************************************/
X/* cont: line generator. Draws a line from current point to (x, y)  */
X/*         uses the line mask to decide when to set pixels.             */
X/************************************************************************/
X
Xcont(x,y)
Xint x, y;
X{
X    dblcont((double)x,(double)y);
X}
X
Xdblcont(x,y)
Xdouble x,y;
X{
X    double r1, c1, r2, c2, rinc, cinc, length, tlen, r, c, fabs();
X    int i;
X    
X    /* Based on the simple DDA from Newmann and Sproull[1] */
X
X    r1 = impl.rc; c1 = impl.cc; 
X    dblmove(x,y);
X    r2 = impl.rc; c2 = impl.cc; 
X
X    length = fabs(r2-r1);
X    tlen = fabs(c2-c1);
X    if (tlen > length) length = tlen;
X    if (length != 0.0) {
X        rinc = (r2 - r1)/length;
X        cinc = (c2 - c1)/length;
X        r = r1;
X        c = c1;
X        
X        for (i = 0; i < length; i++) {
X            if (impl.linemask[impl.lmp] == '\0') impl.lmp = 0;
X            if (impl.linemask[impl.lmp++] == '1')
X                if ((r>=0)&&(r<=GMAX)&&(c>=0)&&(c<=GMAX))
X                    impl.grid[(int)r][(int)c] = impl.gray;
X            r += rinc;
X            c += cinc;
X        }
X        if ((r != r2) || (c != c2)) {
X            if (impl.linemask[impl.lmp] == '\0') impl.lmp = 0;
X            if (impl.linemask[impl.lmp++] == '1')
X                if ((r2>=0)&&(r2<=GMAX)&&(c2>=0)&&(c2<=GMAX))
X                    impl.grid[(int)r2][(int)c2] = impl.gray; 
X        }
X    }
X}
X
X/************************************************************************/
X/* line: draw a line                                                    */
X/************************************************************************/
X
Xline(x1,y1,x2,y2)
Xint x1, y1, x2, y2;
X{
X    move(x1,y1);
X    cont(x2,y2);
X}
X
X/************************************************************************/
X/* chain: polyline                                                      */
X/************************************************************************/
X
Xchain(n,v)
Xshort n, *v;
X{
X    int i, p;
X    short x, y;
X
X    p = 0;
X    x = v[p++]; y = v[p++];
X    move(x,y);
X    
X    for (i = 1; i < n; i++) {
X        x = v[p++]; y = v[p++];
X        cont(x,y);
X    }
X}
X
X/************************************************************************/
X/* bspline: order k spline from Newmann & Sproull[1]                    */
X/************************************************************************/
X
Xbspline(k,n,v)
Xshort k,n,*v;
X{
X    double u, du, ufin, x, y;
X    short nn;
X    
X    nn = n - 1;
X    ufin = (double)(nn - k + 2);
X    du = ufin / (500.0 + (double)nn);
X    
X    u = 0.0;
X    Bpoint(&x,&y,0.0,nn,k,v);
X    move((int)x,(int)y);
X    
X    while (u <= ufin) {
X        u = u + du;
X        Bpoint(&x,&y,u,n,k,v);
X        cont((int)x,(int)y);
X    }
X    x = v[nn*2];
X    y = v[nn*2 + 1];
X    cont((int)x,(int)y);
X}
X
XBpoint(x,y,u,n,k,v)
Xdouble *x,*y,u;
Xint n,k;
Xshort *v;
X{
X    int i, m;
X    double b, Bnblend();
X    
X    *x = 0.0; *y = 0.0;
X    m = 0;
X    knotk = k;
X    knotn = n;
X
X    for (i = 0; i <= n; i++) {
X        b = Bnblend(i,k,u);
X        *x = *x + (double)(v[m]) * b;
X        *y = *y + (double)(v[m+1]) * b;
X        m += 2;
X    }
X}
X
XBknot(i)
Xint i;
X{
X    if (i < knotk) return(0);
X    else if (i > knotn) return(knotn - knotk + 2);
X    else return(i - knotk + 1);
X}
X
Xdouble Bnblend(i,k,u)
Xint i,k;
Xdouble u;
X{
X    double v, v1, v2, t1, t2;
X    
X    v1 = 0.0; v2 = 0.0; t1 = 0.0; t2 = 0.0;
X    
X    if (k == 1) {
X        if ((Bknot(i) <= u) && (u < Bknot(i+1))) v = 1.0;
X        else v = 0.0;
X    }
X    else {
X        t1 = Bknot(i+k-1) - Bknot(i);
X        if (t1 != 0) v1 = (u - Bknot(i)) * Bnblend(i,k-1,u) / t1;
X
X        t2 = Bknot(i+k) - Bknot(i+1);
X        if (t2 != 0) v2 = (Bknot(i+k) - u) * Bnblend(i+1,k-1,u) / t2;
X        
X        v = v1 + v2;
X    }
X    return(v);
X}
X
Xpolygon(n,v)
Xshort n, *v;
X{
X    int i, p;
X    short x, y;
X
X    startp();
X    p = 0;
X    x = v[p++]; y = v[p++];
X    move(x,y);
X    
X    for (i = 1; i < n; i++) {
X        x = v[p++]; y = v[p++];
X        cont(x,y);
X    }
X    endp();
X}
X
X/************************************************************************/
X/* moverel: relative move                                               */
X/************************************************************************/
X
Xmoverel(x,y)
Xint x, y;
X{
X    int newx, newy;
X    
X    newx = impl.xc + x;
X    newy = impl.yc + y;
X    move(newx,newy);
X
X}
X
Xdblmoverel(x,y)
Xdouble x, y;
X{
X    double newx, newy;
X    
X    newx = impl.xc + x;
X    newy = impl.yc + y;
X    dblmove(newx,newy);
X
X}
X
X/************************************************************************/
X/* contrel: relative cont                                               */
X/************************************************************************/
X
Xcontrel(x,y)
Xint x, y;
X{
X    int newx, newy;
X    
X    newx = impl.xc + x;
X    newy = impl.yc + y;
X    cont(newx,newy);
X}
X
Xdblcontrel(x,y)
Xdouble x, y;
X{
X    double newx, newy;
X    
X    newx = impl.xc + x;
X    newy = impl.yc + y;
X    dblcont(newx,newy);
X
X}
X
X/************************************************************************/
X/* gray: set the current gray level                                     */
X/************************************************************************/
X
Xgray(g)
Xint g;
X{
X    impl.gray = (double)g * impl.dbppr/impl.ubppr;
X}
X
X/************************************************************************/
X/* colour: set the current colour                                       */
X/************************************************************************/
X
Xcolour(r,g,b)
Xint r,g,b;
X{
X    gray((int)((double)(r + g + b) / 3.0));
X}
X
X/************************************************************************/
X/* linemod: change the line generator mask                          */
X/*            this mask should be a string of 1s and 0s. The line       */
X/*            generator (cont) will set the pixels under a "1".     */ 
X/************************************************************************/
X
Xlinemod(str)
Xchar *str;
X{
X    strcpy(impl.linemask,str);
X    impl.lmp = 0;
X}
X
X/************************************************************************/
X/* startp: start filled polygon                                         */
X/************************************************************************/
X
Xstartp()
X{
X    impl.ogray = impl.gray;
X    impl.gray = impl.lgray;
X    impl.bx1 = impl.xc; impl.by1 = impl.yc;
X    impl.bx2 = impl.xc; impl.by2 = impl.yc;
X}
X
X/************************************************************************/
X/* endp: end filled polygon                                         */
X/************************************************************************/
X
Xendp()
X{
X    impl.gray = impl.ogray;
X    pfill(impl.bx1,impl.by1,impl.bx2,impl.by2,impl.lgray);
X}
X
X/************************************************************************/
X/* arc: draw an arc from x1 y1 to x2 y2, with center at xc xy       */
X/************************************************************************/
X
Xarc(xc,yc,x1,y1,x2,y2)
Xint xc,yc,x1,y1,x2,y2;
X{
X    double fabs(), hypot(),acos(), cos(), sin();
X    double dt, a1, a2, theta, rad, pi, pi2, up, dn, bup, bdn;
X    double cx, cy;
X    int catch;
X    
X    pi = acos(-1.0);
X    pi2 = 2.0 * pi;
X
X    /* Algorithm: move to x1 y1. The angle between x1 y1 and the x axis is a1.
X        The angle to x2 y2 is a2. Set theta = a1, and move to x1 y1.
X        Sweep anti-clockwise to a2, incrementing theta by dt. At each step,
X        find the point on the arc at angle theta. Use cont to draw a line
X        to that point.
X    */
X
X    rad = hypot((double)(x1-xc),(double)(y1-yc));
X    
X    /* find the angles a1 and a2 */
X    
X    if (y1 >= yc) a1 = acos((x1-xc)/rad);
X    else a1 = pi + acos((xc-x1)/rad);
X
X    if (y2 >= yc) a2 = acos((x2-xc)/rad);
X    else a2 = pi + acos((xc-x2)/rad);
X
X    dt = 0.1 / rad;
X    theta = a1;
X    up = a2+dt;
X    dn = a2-dt;
X    bup = up + pi2;
X    bdn = dn + pi2;
X    catch = 0; /* safety chain */
X
X    /* step around the arc until within range of a2 */
X    while (!((catch > 1) && (((theta < up) && (theta > dn)) ||
X        ((theta < bup) && (theta > bdn))))) {
X
X        impl.xc = xc + rad * cos(theta);
X        impl.yc = yc + rad * sin(theta);
X
X        if (impl.uhv != impl.dhv) {
X            impl.cc = impl.c1 + (impl.xc - impl.x1) * (impl.cr / impl.xr);
X            impl.rc = impl.r1 + (impl.yc - impl.y1) * (impl.rr / impl.yr);
X        }
X        else {
X            impl.rc = impl.r1 + (impl.xc - impl.x1) * (impl.rr / impl.xr);
X            impl.cc = impl.c1 + (impl.yc - impl.y1) * (impl.cr / impl.yr);
X        }
X
X        if (impl.xc < impl.bx1) impl.bx1 = impl.xc;
X        if (impl.yc < impl.by1) impl.by1 = impl.yc;
X        if (impl.xc > impl.bx2) impl.bx2 = impl.xc;
X        if (impl.yc > impl.by2) impl.by2 = impl.yc;
X        
X        if (impl.linemask[impl.lmp] == '\0') impl.lmp = 0;
X        if (impl.linemask[impl.lmp++] == '1')
X            if ((impl.rc>=0)&&(impl.rc<=GMAX)&&(impl.cc>=0)&&(impl.cc<=GMAX))
X                    impl.grid[impl.rc][impl.cc] = impl.gray;
X        theta+=dt;
X        
X        /* safety check to catch runaway loops */
X        if (catch++ > 1000000) {
X            fprintf(stderr,"arc: runaway loop caught: inform a wizard!\n");
X            fprintf(stderr,"  xc=%lf yc=%lf x1=%lf y1=%lf x1=%lf y1=%lf\n",
X                xc,yc,x1,y1,x2,y2);
X            fprintf(stderr,"  angle1=%lf angle2=%lf dtheta=%lf\n",a1,a2,dt);
X            exit(1);
X        }
X    }
X
X    /* finish up */
X    cont(x2,y2);
X    point(x2,y2);
X}
X
X/************************************************************************/
X/* circle: simple incremental circle generator                      */
X/************************************************************************/
X
Xcircle(x1,y1,r)
Xint x1,y1,r;
X{
X    arc (x1, y1, x1-r, y1, x1-r, y1);
X}
X
X/************************************************************************/
X/* fillpat: set fill pattern                                            */
X/************************************************************************/
X
Xfillpat(n,r,c,str)
Xint n, r, c;
Xchar *str;
X{
X    int i, j, p;
X
X    if (n >= MAXPATS) {
X        fprintf(stderr,"fillpat: pattern number %d > max %d\n",n,MAXPATS-1);
X        exit(1);
X    }
X    
X    impl.patc = n;
X    fpat[n].nr = r;
X    fpat[n].nc = c;
X    p = 0;
X    
X    for (i = 0; i < r; i++)
X        for (j = 0; j < c; j++) {
X            if (str[p++] == '1') fpat[n].grid[i][j] = 1;
X            else fpat[n].grid[i][j] = 0;
X            if (str[p] == '\0') p = 0;
X        }
X}
X
X/************************************************************************/
X/* setpat: set current fill pattern                                     */
X/************************************************************************/
X
Xsetpat(n)
Xint n;
X{
X    impl.patc = n;
X}
X
X/************************************************************************/
X/* pensize: set pensize                                                 */
X/************************************************************************/
X
Xpensize(p)
Xint p;
X{
X/* PENSIZE NOT IMPLEMENTED */
X}
X
X/************************************************************************/
X/* area: fill area from seed point - boundary is non-current value  */
X/************************************************************************/
X
Xarea(x,y)
Xint x, y;
X{
X    int nx, ny, nxm, nym, nxp, nyp, aminx, aminy, amaxx, amaxy, pc;
X    long seedv, mark;
X    
X    pc = impl.patc;
X    
X    /* stack the seed point */
X    move(x,y);
X    seedv = impl.grid[impl.rc][impl.cc];
X    mark = impl.lgray;
X    aminx = impl.rc; aminy = impl.cc;
X    amaxx = aminx; amaxy = aminy;
X    
X    top = 0;
X    if (fpat[pc].grid[impl.rc%fpat[pc].nr][impl.cc%fpat[pc].nc]) 
X        impl.grid[impl.rc][impl.cc] = impl.gray;
X    else impl.grid[impl.rc][impl.cc] = mark;
X    stack[top][0] = impl.rc; stack[top++][1] = impl.cc;
X
X
X    /* stack any 4-connected neighbours of the top of the stack, which
X        have the seed value at that pixel. */
X
X    while (top > 0) {
X        top--;
X        nx = stack[top][0]; ny = stack[top][1];
X        nxm = nx - 1; nym = ny - 1;
X        nxp = nx + 1; nyp = ny + 1;
X
X        if (nx > 0)
X            if (impl.grid[nxm][ny] == seedv) {
X                if (nxm < aminx) aminx = nxm;
X                if (fpat[pc].grid[nxm%fpat[pc].nr][ny%fpat[pc].nc]) 
X                    impl.grid[nxm][ny] = impl.gray;
X                else impl.grid[nxm][ny] = mark;
X                stack[top][0] = nxm; stack[top++][1] = ny;
X            }
X        
X        if (nx < impl.r2)
X            if (impl.grid[nxp][ny] == seedv) {
X                if (nxp > amaxx) amaxx = nxp;
X                if (fpat[pc].grid[nxp%fpat[pc].nr][ny%fpat[pc].nc]) 
X                    impl.grid[nxp][ny] = impl.gray;
X                else impl.grid[nxp][ny] = mark;
X                stack[top][0] = nxp; stack[top++][1] = ny;
X            }
X
X        if (ny > 0)
X            if (impl.grid[nx][nym] == seedv) {
X                if (nym < aminy) aminy = nym;
X                if (fpat[pc].grid[nx%fpat[pc].nr][nym%fpat[pc].nc]) 
X                    impl.grid[nx][nym] = impl.gray;
X                else impl.grid[nx][nym] = mark;
X                stack[top][0] = nx; stack[top++][1] = nym;
X            }
X        
X        if (ny < impl.c2)
X            if (impl.grid[nx][nyp] == seedv) {
X                if (nyp > amaxy) amaxy = nyp;
X                if (fpat[pc].grid[nx%fpat[pc].nr][nyp%fpat[pc].nc]) 
X                    impl.grid[nx][nyp] = impl.gray;
X                else impl.grid[nx][nyp] = mark;
X                stack[top][0] = nx; stack[top++][1] = nyp;
X            }
X    }
X    for (nx = aminx; nx <= amaxx; nx++)
X        for (ny = aminy; ny <= amaxy; ny++)
X            if (impl.grid[nx][ny] == mark) impl.grid[nx][ny] = seedv;
X}
X
X
X/************************************************************************/  
X/* pfill: fill a polygon in the bounding box x1, y1, x2, y2,            */
X/*          the polygon boundary must have been drawn with gray = fill  */
X/*          NOTE: fill cannot be 0.                                     */
X/************************************************************************/  
X
Xpfill(x1,y1,x2,y2,fill)
Xint x1, y1, x2, y2, fill;
X{
X
X    int i, j, r, c, nr, nc, pc;
X    int r1, c1, r2, c2, rt, ct;
X    int negfill;
X
X    pc = impl.patc;
X    
X    /* 
X       Algorithm: 
X       Visit the border of the box. 
X         Set 0 pixels to -fill and stack them. 
X         Set non-fill pixels negative and stack them.
X
X       Run a filling algorithm inside the box and outside the polygon
X         Set 0 pixels to -fill.
X         Set non-fill pixels  negative.
X
X       Scan the box. 
X         Set 0 or positive to fill.
X         Set -fill to 0.
X         Set negatives to positive
X    */
X    
X    if (fill == 0) {
X        fprintf(stderr,"pfill: can't fill a polygon with 0 boundary.\n");
X        return(0);
X    }
X    
X    move(x1,y1); r1 = impl.rc; c1 = impl.cc;
X    move(x2,y2); r2 = impl.rc; c2 = impl.cc;
X    if (r1 > r2) { rt = r1; r1 = r2; r2 = rt; }
X    if (c1 > c2) { ct = c1; c1 = c2; c2 = ct; }
X
X    negfill = -1 * fill;
X    top = 0;
X    
X    /* Visit the border */
X    
X    for (i = r1; i <= r2; i++) {
X        if (impl.grid[i][c1] == 0) {
X            impl.grid[i][c1] = negfill;
X            stack[top][0] = i; stack[top++][1] = c1;
X        };
X        if ((impl.grid[i][c1] != fill) && (impl.grid[i][c1] > 0)) {
X            impl.grid[i][c1] *= -1;
X            stack[top][0] = i; stack[top++][1] = c1;
X        };
X        
X        if (impl.grid[i][c2] == 0) {
X            impl.grid[i][c2] = negfill;
X            stack[top][0] = i; stack[top++][1] = c2;
X        };
X        if ((impl.grid[i][c2] != fill) && (impl.grid[i][c2] > 0)) {
X            impl.grid[i][c2] *= -1;
X            stack[top][0] = i; stack[top++][1] = c2;
X        };
X
X        if (top > STACKSIZE) {
X            fprintf(stderr,"pfill: fill stack overflow\n");
X            exit(1);
X        };
X    };
X
X    for (i = c1; i <= c2; i++) {
X        if (impl.grid[r1][i] == 0) {
X            impl.grid[r1][i] = negfill;
X            stack[top][0] = r1; stack[top++][1] = i;
X        };
X        if ((impl.grid[r1][i] != fill) && (impl.grid[r1][i] > 0)) {
X            impl.grid[r1][i] *= -1;
X            stack[top][0] = r1; stack[top++][1] = i;
X        };
X
X        if (impl.grid[r2][i] == 0) {
X            impl.grid[r2][i] = negfill;
X            stack[top][0] = r2; stack[top++][1] = i;
X        };
X        if ((impl.grid[r2][i] != fill) && (impl.grid[r2][i] > 0)) {
X            impl.grid[r2][i] *= -1;
X            stack[top][0] = r2; stack[top++][1] = i;
X        };
X        if (top > STACKSIZE) {
X            fprintf(stderr,"pfill: fill stack overflow\n");
X            exit(1);
X        };
X    }
X    
X    /* fill the rest of the outside zeros with negfill */
X    
X    while (top > 0) {
X        top--;
X        r = stack[top][0]; c = stack[top][1];
X        
X        nr = r-1;
X        if ((nr >= r1) && (nr <= r2)) {
X            if (impl.grid[nr][c] == 0) {
X                impl.grid[nr][c] = negfill;
X                stack[top][0] = nr; stack[top++][1] = c;
X            };
X            if ((impl.grid[nr][c] > 0) && 
X                (impl.grid[nr][c] != fill)) {
X                impl.grid[nr][c] *= -1;
X                stack[top][0] = nr; stack[top++][1] = c;
X            }
X        }
X        
X        nr = r+1;
X        if ((nr >= r1) && (nr <= r2)) {
X            if (impl.grid[nr][c] == 0) {
X                impl.grid[nr][c] = negfill;
X                stack[top][0] = nr; stack[top++][1] = c;
X            };
X            if ((impl.grid[nr][c] > 0) && 
X                (impl.grid[nr][c] != fill)) {
X                impl.grid[nr][c] *= -1;
X                stack[top][0] = nr; stack[top++][1] = c;
X            }
X        }
X
X        nc = c-1;
X        if ((nc >= c1) && (nc <= c2)) {
X            if (impl.grid[r][nc] == 0) {
X                impl.grid[r][nc] = negfill;
X                stack[top][0] = r; stack[top++][1] = nc;
X            };
X            if ((impl.grid[r][nc] > 0) && 
X                (impl.grid[r][nc] != fill)) {
X                impl.grid[r][nc] *= -1;
X                stack[top][0] = r; stack[top++][1] = nc;
X            }
X        }
X                
X        nc = c+1;
X        if ((nc >= c1) && (nc <= c2)) {
X            if (impl.grid[r][nc] == 0) {
X                impl.grid[r][nc] = negfill;
X                stack[top][0] = r; stack[top++][1] = nc;
X            };
X            if ((impl.grid[r][nc] > 0) && 
X                (impl.grid[r][nc] != fill)) {
X                impl.grid[r][nc] *= -1;
X                stack[top][0] = r; stack[top++][1] = nc;
X            }
X        }
X        if (top > STACKSIZE) {
X            fprintf(stderr,"pfill: fill stack overflow\n");
X            exit(1);
X        }
X    }
X    
X                
X    /* scan the box */
X    for (i = r1; i <= r2; i++)
X        for (j = c1; j <= c2; j++) 
X            if (impl.grid[i][j] >= 0) {
X                if (fpat[pc].grid[i%fpat[pc].nr][j%fpat[pc].nc])
X                    impl.grid[i][j] = impl.gray;
X                else if (impl.grid[i][j] == fill)
X                    impl.grid[i][j] = impl.gray;
X            }
X            else if (impl.grid[i][j] == negfill) impl.grid[i][j] = 0;
X            else if (impl.grid[i][j] < 0) impl.grid[i][j] *= -1;
X}
X
Xcomment(str)
Xchar *str;
X{
X}
X
Xdonelabel()
X{
X}
!FUNKY!STUFF!
echo
echo finished part 6 of 8



More information about the Comp.sources.unix mailing list