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.