ftp.nice.ch/pub/next/unix/developer/plplot.3.0.s.tar.gz#/plplot/src/plfill.c

This is plfill.c in view mode; [Download] [Up]

#include "plplot.h"
#include <math.h>
#if	defined(PLSTDC) && defined(STDLIB)
#include <stdlib.h>
#else
extern char *malloc();
extern char *realloc();
extern void free();
#endif

#define BETW(ix,ia,ib)  (((ix)<=(ia)&&(ix)>=(ib)) || ((ix)>=(ia)&&(ix)<=(ib)))
#define SSQR(a,b)       sqrt((a)*(a)+(b)*(b))
#define SIGN(a)         ((a)<0 ? -1 : 1)
#define DTOR            0.0174533
#define BINC            50

struct point {
   short x, y;
};

static short bufferleng, buffersize, *buffer;

void plfill(n,x,y)
int n;
FLOAT *x, *y;
{
   int i,level;
   int xmin, ymin, x1, y1, x2, y2, x3, y3;
   int k, dinc;
   int nlin, *inc, *del;
   double ci, si, thetd, xpmm, ypmm;
   short swap;
   int compare();
   void buildlist(), qsort(), tran();

   glev(&level);
   if (level<3) plexit("Please set up window before calling plfill.");
   if (n<3) plexit("Not enough points in plfill object!");

   buffersize = 2*BINC;
   buffer = (short *)malloc(buffersize*sizeof(short));
   if(!buffer)
      plexit("Out of memory in plfill.");

   gpat(&inc, &del, &nlin);
   gpixmm(&xpmm, &ypmm);

   for(k=0; k<nlin; k++) {
      bufferleng = 0;

      if(ABS(inc[k]) <= 450) {
         thetd = atan(tan(DTOR*inc[k]/10.)*ypmm/xpmm);
         swap = 0;
      }
      else {
         thetd = atan(tan(DTOR*SIGN(inc[k])*
                          (ABS(inc[k])-900)/10.)*xpmm/ypmm);
         swap = 1;
      }
      ci = cos(thetd);
      si = sin(thetd);
      if(swap)
         dinc = del[k]*SSQR(xpmm*ABS(ci),ypmm*ABS(si))/1000.;
      else
         dinc = del[k]*SSQR(ypmm*ABS(ci),xpmm*ABS(si))/1000.;

      xmin = wcpcx(x[0]); ymin = wcpcy(y[0]);
      for(i=1; i<n; i++) {
         xmin = MIN(xmin,wcpcx(x[i]));
         ymin = MIN(ymin,wcpcy(y[i]));
      }

      x1 = wcpcx(x[0]) - xmin;
      y1 = wcpcy(y[0]) - ymin;
      tran(&x1,&y1,ci,si);
      x2 = wcpcx(x[1]) - xmin;
      y2 = wcpcy(y[1]) - ymin;
      tran(&x2,&y2,ci,si);
      for(i=2; i<n; i++) {
         x3 = wcpcx(x[i]) - xmin;
         y3 = wcpcy(y[i]) - ymin;
         tran(&x3,&y3,ci,si);
         if(swap)
            buildlist(y1,x1,y2,x2,y3,x3,dinc);
         else
            buildlist(x1,y1,x2,y2,x3,y3,dinc);
         x1 = x2; y1 = y2;
         x2 = x3; y2 = y3;
      }
      x3 = wcpcx(x[0]) - xmin;
      y3 = wcpcy(y[0]) - ymin;
      tran(&x3,&y3,ci,si);
      if(swap)
         buildlist(y1,x1,y2,x2,y3,x3,dinc);
      else
         buildlist(x1,y1,x2,y2,x3,y3,dinc);

      x1 = x2; y1 = y2;
      x2 = x3; y2 = y3;
      x3 = wcpcx(x[1]) - xmin;
      y3 = wcpcy(y[1]) - ymin;
      tran(&x3,&y3,ci,si);
      if(swap)
         buildlist(y1,x1,y2,x2,y3,x3,dinc);
      else
         buildlist(x1,y1,x2,y2,x3,y3,dinc);

      /* Sort list by y then x */
      qsort((char *)buffer,bufferleng/2,sizeof(struct point),compare);

      /* OK, now do the hatching */
      i = 0;
      while(i<bufferleng) {
         if(swap) {
            x1 = buffer[i+1]; y1 = buffer[i];
         }
         else {
            x1 = buffer[i]; y1 = buffer[i+1];
         }
         i += 2;
         x2 = x1; y2 = y1;
         tran(&x1,&y1,ci,-si);
         movphy(x1+xmin,y1+ymin);
         if(swap) {
            x1 = buffer[i+1]; y1 = buffer[i];
         }
         else {
            x1 = buffer[i]; y1 = buffer[i+1];
         }
         i += 2;
         if((swap && x2 != x1) || (!swap && y2 != y1))
            continue;          /* Uh oh we're lost */
         tran(&x1,&y1,ci,-si);
         draphy(x1+xmin,y1+ymin);
      }

   }
   free((VOID *)buffer);
}

void tran(a,b,c,d)
int *a, *b;
double c, d;
{
   int ta, tb;

   ta = *a;
   tb = *b;

   *a = round(ta*c + tb*d);
   *b = round(tb*c - ta*d);
}

void buildlist(x1,y1,x2,y2,x3,y3,dinc)
int x1, y1, x2, y2, x3, y3;
{
   int i;
   int dx, dy, cstep, nstep, lines, ploty, plotx;
   void addcoord();

   dx = x2 - x1; dy = y2 - y1;

   if(dy == 0) return;

   cstep = (y2>y1 ? 1 : -1);
   nstep = (y3>y2 ? 1 : -1);
   if(y3 == y2) nstep = 0;

   /* Build coordinate list */
   lines = ABS(dy)/dinc + 1;
   if(cstep == 1  && y1 > 0)
      ploty = (y1/dinc + 1)*dinc;
   else if (cstep == -1 && y1 < 0)
      ploty = (y1/dinc - 1)*dinc;
   else
      ploty = (y1/dinc)*dinc;

   for(i=0; i<lines; i++) {
      if(!BETW(ploty,y1,y2)) break;
      plotx = x1 + round(((float)(ploty-y1)*dx)/dy + .5);
      /* Check for extremum at end point, otherwise add to coord list */
      if(!((ploty == y1) || (ploty == y2 && nstep != cstep)))
         addcoord(plotx,ploty);
      ploty += cstep*dinc;
   }
}

void addcoord(x1, y1)
int x1, y1;
{
   short *temp;

   if(bufferleng + 2 > buffersize) {
      buffersize += 2*BINC;
      temp = (short *)realloc((VOID *)buffer,buffersize*sizeof(short));
      if(!temp) {
         free((VOID *)buffer);
         plexit("Out of memory in plfill!");
      }
      buffer = temp;
   }

   buffer[bufferleng++] = x1;
   buffer[bufferleng++] = y1;
}

int compare(pnum1, pnum2)
char *pnum1, *pnum2;
{
   struct point *pnt1, *pnt2;

   pnt1 = (struct point *)pnum1;
   pnt2 = (struct point *)pnum2;

   if(pnt1->y < pnt2->y)
      return(-1);
   else if(pnt1->y > pnt2->y)
      return(1);

   /* Only reach here if y coords are equal, so sort by x */
   if(pnt1->x < pnt2->x)
      return(-1);
   else if(pnt1->x > pnt2->x)
      return(1);

   return(0);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.