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.