Ejemplo n.º 1
0
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++;
	}
      }
    }

}
Ejemplo n.º 2
0
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,
	 PLINT *p_kscan, PLINT *p_kstor, PLINT *iscan,
	 PLINT *ixstor, PLINT *iystor, PLINT nstor,
	 void (*pltr) (PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer),
	 PLPointer pltr_data)
{
    PLINT iwbeg, ixbeg, iybeg, izbeg;
    PLINT iboun, iw, ix, iy, iz, ifirst, istep, ixgo, iygo;
    PLINT l, ixg, iyg, ia, ib;

    PLFLT dist, dx, dy, xnew, ynew, fxl, fxr;
    PLFLT xlas = 0., ylas = 0., tpx, tpy, xt, yt;
    PLFLT f1, f2, f3, f4, fcheck;

    PLINT lastindex = 0;
    PLFLT distance = 0.0;

/* Check if a contour has been crossed */

    fxl = f2eval(kcol-1, krow, f2eval_data);
    fxr = f2eval(kcol, krow, f2eval_data);

    if (fxl < flev && fxr >= flev) {
	ixbeg = kcol - 1;
	iwbeg = kcol;
    }
    else if (fxr < flev && fxl > flev) {
	ixbeg = kcol;
	iwbeg = kcol - 1;
    }
    else
	return;

    iybeg = krow;
    izbeg = krow;

/* A contour has been crossed. */
/* Check to see if it is a new one. */

    for (l = 0; l < *p_kscan; l++) {
	if (ixbeg == iscan[l])
	    return;
    }

    for (iboun = 1; iboun >= -1; iboun -= 2) {

    /* Set up starting point and initial search directions */

	ix = ixbeg;
	iy = iybeg;
	iw = iwbeg;
	iz = izbeg;
	ifirst = 1;
	istep = 0;
	ixgo = iw - ix;
	iygo = iz - iy;

	for (;;) {
	    plccal(f2eval, f2eval_data,
		   flev, ix, iy, ixgo, iygo, &dist);

	    dx = dist * ixgo;
	    dy = dist * iygo;
	    xnew = ix + dx;
	    ynew = iy + dy;

	/* Has a step occured in search? */

	    if (istep != 0) {
		if (ixgo * iygo == 0) {

		/* This was a diagonal step, so interpolate missed point. */
		/* Rotating 45 degrees to get it */

		    ixg = ixgo;
		    iyg = iygo;
		    plr45(&ixg, &iyg, iboun);
		    ia = iw - ixg;
		    ib = iz - iyg;
		    plccal(f2eval, f2eval_data,
			   flev, ia, ib, ixg, iyg, &dist);

		    (*pltr) (xlas, ylas, &tpx, &tpy, pltr_data);

		    if (contlabel_active)
		      pl_drawcontlabel(tpx, tpy, flabel, &distance, &lastindex);
		    else
		      cont_xy_store(tpx,tpy); /* plP_drawor(tpx, tpy); */

		    dx = dist * ixg;
		    dy = dist * iyg;
		    xlas = ia + dx;
		    ylas = ib + dy;
		}
		else {
		    if (dist > 0.5) {
			xt = xlas;
			xlas = xnew;
			xnew = xt;
			yt = ylas;
			ylas = ynew;
			ynew = yt;
		    }
		}
	    }
	    if (ifirst != 1) {
		(*pltr) (xlas, ylas, &tpx, &tpy, pltr_data);
		if (contlabel_active)
		  pl_drawcontlabel(tpx, tpy, flabel, &distance, &lastindex);
		else
		  cont_xy_store(tpx,tpy); /* plP_drawor(tpx, tpy); */
	    }
	    else {
		(*pltr) (xnew, ynew, &tpx, &tpy, pltr_data);
		cont_mv_store(tpx,tpy); /* plP_movwor(tpx, tpy); */
	    }
	    xlas = xnew;
	    ylas = ynew;

	/* Check if the contour is closed */

	    if (ifirst != 1 &&
		ix == ixbeg && iy == iybeg && iw == iwbeg && iz == izbeg) {
		(*pltr) (xlas, ylas, &tpx, &tpy, pltr_data);
		if (contlabel_active)
		  pl_drawcontlabel(tpx, tpy, flabel, &distance, &lastindex);
		else
		  cont_xy_store(tpx,tpy); /* plP_drawor(tpx, tpy); */
		return;
	    }
	    ifirst = 0;

	/* Now the rotation */

	    istep = 0;
	    plr45(&ixgo, &iygo, iboun);
	    iw = ix + ixgo;
	    iz = iy + iygo;

	/* Check if out of bounds */

	    if (iw < kx || iw > lx || iz < ky || iz > ly)
		break;

	/* Has contact been lost with the contour? */

	    if (ixgo * iygo == 0)
		fcheck = f2eval(iw, iz, f2eval_data);
	    else {
		f1 = f2eval(ix, iy, f2eval_data);
		f2 = f2eval(iw, iz, f2eval_data);
		f3 = f2eval(ix, iz, f2eval_data);
		f4 = f2eval(iw, iy, f2eval_data);

		fcheck = MAX(f2, (f1 + f2 + f3 + f4) / 4.);
	    }

	    if (fcheck < flev) {

	    /* Yes, lost contact => step to new center */

		istep = 1;
		ix = iw;
		iy = iz;
		plr135(&ixgo, &iygo, iboun);
		iw = ix + ixgo;
		iz = iy + iygo;

	    /* And do the contour memory */

		if (iy == krow) {
		    *p_kscan = *p_kscan + 1;
		    iscan[*p_kscan - 1] = ix;
		}
		else if (iy > krow) {
		    *p_kstor = *p_kstor + 1;
		    if (*p_kstor > nstor) {
			plabort("plfcont: heap exhausted");
			error = 1;
			return;
		    }
		    ixstor[*p_kstor - 1] = ix;
		    iystor[*p_kstor - 1] = iy;
		}
	    }
	}
	/* Reach here only if boundary encountered - Draw last bit */

	(*pltr) (xnew, ynew, &tpx, &tpy, pltr_data);
        /* distance = 0.0; */

	cont_xy_store(tpx,tpy); /* plP_drawor(tpx, tpy); */
    }
}