static void plcntr(PLFLT (*f2eval) (PLINT, PLINT, PLPointer), PLPointer f2eval_data, PLINT nx, PLINT ny, PLINT kx, PLINT lx, PLINT ky, PLINT ly, PLFLT flev, PLINT **ipts, void (*pltr) (PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer), PLPointer pltr_data) { PLINT kcol, krow, lastindex; PLFLT distance; PLFLT save_def, save_scale; char flabel[30]; plgchr(&save_def, &save_scale); save_scale = save_scale/save_def; cont_new_store(flev); /* format contour label for plptex and define the font height of the labels */ plfloatlabel(flev, flabel); plschr(0.0, contlabel_size); /* Clear array for traversed squares */ for (kcol = kx; kcol < lx; kcol++) { for (krow = ky; krow < ly; krow++) { ipts[kcol][krow] = 0; } } for (krow = ky; krow < ly; krow++) { for (kcol = kx; kcol < lx; kcol++) { if (ipts[kcol][krow] == 0) { /* Follow and draw a contour */ pldrawcn(f2eval, f2eval_data, nx, ny, kx, lx, ky, ly, flev, flabel, kcol, krow, 0.0, 0.0, -2, ipts, &distance, &lastindex, pltr, pltr_data); if (error) return; } } } plschr(save_def, save_scale); }
static void pldrawcn(PLFLT (*f2eval) (PLINT, PLINT, PLPointer), PLPointer f2eval_data, PLINT nx, PLINT ny, PLINT kx, PLINT lx, PLINT ky, PLINT ly, PLFLT flev, char *flabel, PLINT kcol, PLINT krow, PLFLT lastx, PLFLT lasty, PLINT startedge, PLINT **ipts, PLFLT *distance, PLINT *lastindex, void (*pltr) (PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer), PLPointer pltr_data) { PLFLT f[4]; PLFLT px[4], py[4], locx[4], locy[4]; PLINT iedge[4]; PLINT i, j, k, num, first, inext, kcolnext, krownext; (*pltr) (kcol,krow+1,&px[0],&py[0],pltr_data); (*pltr) (kcol,krow,&px[1],&py[1],pltr_data); (*pltr) (kcol+1,krow,&px[2],&py[2],pltr_data); (*pltr) (kcol+1,krow+1,&px[3],&py[3],pltr_data); f[0] = f2eval(kcol, krow+1, f2eval_data)-flev; f[1] = f2eval(kcol, krow, f2eval_data)-flev; f[2] = f2eval(kcol+1, krow, f2eval_data)-flev; f[3] = f2eval(kcol+1, krow+1, f2eval_data)-flev; for (i=0,j=1;i<4;i++,j = (j+1)%4) { iedge[i] = (f[i]*f[j]>0.0)?-1:((f[i]*f[j] < 0.0)?1:0); } /* Mark this square as done */ ipts[kcol][krow] = 1; /* Check if no contour has been crossed i.e. iedge[i] = -1 */ if ((iedge[0] == -1) && (iedge[1] == -1) && (iedge[2] == -1) && (iedge[3] == -1)) return; /* Check if this is a completely flat square - in which case ignore it */ if ( (f[0] == 0.0) && (f[1] == 0.0) && (f[2] == 0.0) && (f[3] == 0.0) ) return; /* Calculate intersection points */ num = 0; if (startedge < 0) { first = 1; } else { locx[num] = lastx; locy[num] = lasty; num++; first = 0; } for (k=0, i = (startedge<0?0:startedge);k<4;k++,i=(i+1)%4) { if (i == startedge) continue; /* If the contour is an edge check it hasn't already been done */ if (f[i] == 0.0 && f[(i+1)%4] == 0.0) { kcolnext = kcol; krownext = krow; if (i == 0) kcolnext--; if (i == 1) krownext--; if (i == 2) kcolnext++; if (i == 3) krownext++; if ((kcolnext < kx) || (kcolnext >= lx) || (krownext < ky) || (krownext >= ly) || (ipts[kcolnext][krownext] == 1)) continue; } if ((iedge[i] == 1) || (f[i] == 0.0)) { j = (i+1)%4; if (f[i] != 0.0) { locx[num] = (px[i]*fabs(f[j])+px[j]*fabs(f[i]))/fabs(f[j]-f[i]); locy[num] = (py[i]*fabs(f[j])+py[j]*fabs(f[i]))/fabs(f[j]-f[i]); } else { locx[num] = px[i]; locy[num] = py[i]; } /* If this is the start of the contour then move to the point */ if (first == 1) { cont_mv_store(locx[num],locy[num]); first = 0; *distance = 0; *lastindex = 0; } else { /* Link to the next point on the contour */ if (contlabel_active) pl_drawcontlabel(locx[num], locy[num], flabel, distance, lastindex); else cont_xy_store(locx[num],locy[num]); /* Need to follow contour into next grid box */ /* Easy case where contour does not pass through corner */ if (f[i] != 0.0) { kcolnext = kcol; krownext = krow; inext = (i+2)%4; if (i == 0) kcolnext--; if (i == 1) krownext--; if (i == 2) kcolnext++; if (i == 3) krownext++; if ((kcolnext >= kx) && (kcolnext < lx) && (krownext >= ky) && (krownext < ly) && (ipts[kcolnext][krownext] == 0)) { pldrawcn(f2eval, f2eval_data, nx, ny, kx, lx, ky, ly, flev, flabel, kcolnext, krownext, locx[num], locy[num], inext, ipts, distance, lastindex, pltr, pltr_data); } } /* Hard case where contour passes through corner */ /* This is still not perfect - it may lose the contour * which won't upset the contour itself (we can find it * again later) but might upset the labelling */ else { kcolnext = kcol; krownext = krow; inext = (i+2)%4; if (i == 0) {kcolnext--; krownext++;} if (i == 1) {krownext--; kcolnext--;} if (i == 2) {kcolnext++; krownext--;} if (i == 3) {krownext++; kcolnext++;} if ((kcolnext >= kx) && (kcolnext < lx) && (krownext >= ky) && (krownext < ly) && (ipts[kcolnext][krownext] == 0)) { pldrawcn(f2eval, f2eval_data, nx, ny, kx, lx, ky, ly, flev, flabel, kcolnext, krownext, locx[num], locy[num], inext, ipts, distance, lastindex, pltr, pltr_data); } } if (first == 1) { /* Move back to first point */ cont_mv_store(locx[num],locy[num]); first = 0; *distance = 0; *lastindex = 0; first = 0; } else { first = 1; } num++; } } } }
static void plcntr(PLFLT (*f2eval) (PLINT, PLINT, PLPointer), PLPointer f2eval_data, PLINT nx, PLINT ny, PLINT kx, PLINT lx, PLINT ky, PLINT ly, PLFLT flev, PLINT *iscan, PLINT *ixstor, PLINT *iystor, PLINT nstor, void (*pltr) (PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer), PLPointer pltr_data) { PLINT kcol, krow, kstor, kscan, l, ixt, iyt, jstor, next; char flabel[30]; cont_new_store(flev); /* format contour label for plptex and define the font height of the labels */ plfloatlabel(flev, flabel); plschr(0.0, contlabel_size); /* Initialize memory pointers */ kstor = 0; kscan = 0; for (krow = ky; krow <= ly; krow++) { for (kcol = kx + 1; kcol <= lx; kcol++) { /* Follow and draw a contour */ pldrawcn(f2eval, f2eval_data, nx, ny, kx, lx, ky, ly, flev, flabel, kcol, krow, &kscan, &kstor, iscan, ixstor, iystor, nstor, pltr, pltr_data); if (error) return; } /* Search of row complete */ /* Set up memory of next row in iscan and edit ixstor and iystor */ if (krow < ny-1) { jstor = 0; kscan = 0; next = krow + 1; for (l = 1; l <= kstor; l++) { ixt = ixstor[l - 1]; iyt = iystor[l - 1]; /* Memory of next row into iscan */ if (iyt == next) { kscan = kscan + 1; iscan[kscan - 1] = ixt; } /* Retain memory of rows to come, and forget rest */ else if (iyt > next) { jstor = jstor + 1; ixstor[jstor - 1] = ixt; iystor[jstor - 1] = iyt; } } kstor = jstor; } } plschr(0.0, 1.0); }