Exemplo n.º 1
0
static void
plccal(PLFLT (*f2eval) (PLINT, PLINT, PLPointer),
       PLPointer f2eval_data,
       PLFLT flev, PLINT ix, PLINT iy,
       PLINT ixg, PLINT iyg, PLFLT *dist)
{
    PLINT ia, ib;
    PLFLT dbot, dtop, fmid;
    PLFLT fxy, fab, fay, fxb, flow;

    ia = ix + ixg;
    ib = iy + iyg;
    fxy = f2eval(ix, iy, f2eval_data);
    fab = f2eval(ia, ib, f2eval_data);
    fxb = f2eval(ix, ib, f2eval_data);
    fay = f2eval(ia, iy, f2eval_data);

    if (ixg == 0 || iyg == 0) {
	dtop = flev - fxy;
	dbot = fab - fxy;
	*dist = 0.0;
	if (dbot != 0.0)
	    *dist = dtop / dbot;
    }
    else {
	fmid = (fxy + fab + fxb + fay) / 4.0;
	*dist = 0.5;

	if ((fxy - flev) * (fab - flev) <= 0.) {

	    if (fmid >= flev) {
		dtop = flev - fxy;
		dbot = fmid - fxy;
		if (dbot != 0.0)
		    *dist = 0.5 * dtop / dbot;
	    }
	    else {
		dtop = flev - fab;
		dbot = fmid - fab;
		if (dbot != 0.0)
		    *dist = 1.0 - 0.5 * dtop / dbot;
	    }
	}
	else {
	    flow = (fxb + fay) / 2.0;
	    dtop = fab - flev;
	    dbot = fab + fxy - 2.0 * flow;
	    if (dbot != 0.0)
		*dist = 1. - dtop / dbot;
	}
    }
    if (*dist > 1.)
	*dist = 1.;
}
Exemplo 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,
	 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++;
	}
      }
    }

}
Exemplo n.º 3
0
static void
plshade_int( PLFLT ( *f2eval )( PLINT, PLINT, PLPointer ),
             PLPointer f2eval_data,
             PLFLT ( * c2eval )( PLINT, PLINT, PLPointer ), // unused, but macro doesn't work
             PLPointer PL_UNUSED( c2eval_data ),
             PLINT ( *defined )( PLFLT, PLFLT ),
             PLINT nx, PLINT ny,
             PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax,
             PLFLT shade_min, PLFLT shade_max,
             PLINT sh_cmap, PLFLT sh_color, PLFLT sh_width,
             PLINT min_color, PLFLT min_width,
             PLINT max_color, PLFLT max_width,
             void ( *fill )( PLINT, const PLFLT *, const PLFLT * ), PLINT rectangular,
             void ( *pltr )( PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer ),
             PLPointer pltr_data )
{
    PLINT n, slope = 0, ix, iy;
    int   count, i, j, nxny;
    PLFLT *a, *a0, *a1, dx, dy;
    PLFLT x[8], y[8], xp[2], tx, ty, init_width;
    int   *c, *c0, *c1;

    (void) c2eval;   // Cast to void to silence compiler warning about unused parameter

    if ( plsc->level < 3 )
    {
        plabort( "plfshade: window must be set up first" );
        return;
    }

    if ( nx <= 0 || ny <= 0 )
    {
        plabort( "plfshade: nx and ny must be positive" );
        return;
    }

    if ( shade_min >= shade_max )
    {
        plabort( "plfshade: shade_max must exceed shade_min" );
        return;
    }

    if ( pltr == NULL && plsc->coordinate_transform == NULL )
        rectangular = 1;

    int_val    = shade_max - shade_min;
    init_width = plsc->width;

    pen_col_min = min_color;
    pen_col_max = max_color;

    pen_wd_min = min_width;
    pen_wd_max = max_width;

    plstyl( (PLINT) 0, NULL, NULL );
    plwidth( sh_width );
    if ( fill != NULL )
    {
        switch ( sh_cmap )
        {
        case 0:
            plcol0( (PLINT) sh_color );
            break;
        case 1:
            plcol1( sh_color );
            break;
        default:
            plabort( "plfshade: invalid color map selection" );
            return;
        }
    }
    // alloc space for value array, and initialize
    // This is only a temporary kludge
    nxny = nx * ny;
    if ( ( a = (PLFLT *) malloc( (size_t) nxny * sizeof ( PLFLT ) ) ) == NULL )
    {
        plabort( "plfshade: unable to allocate memory for value array" );
        return;
    }

    for ( ix = 0; ix < nx; ix++ )
        for ( iy = 0; iy < ny; iy++ )
            a[iy + ix * ny] = f2eval( ix, iy, f2eval_data );

    // alloc space for condition codes

    if ( ( c = (int *) malloc( (size_t) nxny * sizeof ( int ) ) ) == NULL )
    {
        plabort( "plfshade: unable to allocate memory for condition codes" );
        free( a );
        return;
    }

    sh_min = shade_min;
    sh_max = shade_max;

    set_cond( c, a, nxny );
    dx = ( xmax - xmin ) / ( nx - 1 );
    dy = ( ymax - ymin ) / ( ny - 1 );
    a0 = a;
    a1 = a + ny;
    c0 = c;
    c1 = c + ny;

    for ( ix = 0; ix < nx - 1; ix++ )
    {
        for ( iy = 0; iy < ny - 1; iy++ )
        {
            count = c0[iy] + c0[iy + 1] + c1[iy] + c1[iy + 1];

            // No filling needs to be done for these cases

            if ( count >= UNDEF )
                continue;
            if ( count == 4 * POS )
                continue;
            if ( count == 4 * NEG )
                continue;

            // Entire rectangle can be filled

            if ( count == 4 * OK )
            {
                // find biggest rectangle that fits
                if ( rectangular )
                {
                    big_recl( c0 + iy, ny, nx - ix, ny - iy, &i, &j );
                }
                else
                {
                    i = j = 1;
                }
                x[0] = x[1] = ix;
                x[2] = x[3] = ix + i;
                y[0] = y[3] = iy;
                y[1] = y[2] = iy + j;

                if ( pltr )
                {
                    for ( i = 0; i < 4; i++ )
                    {
                        ( *pltr )( x[i], y[i], &tx, &ty, pltr_data );
                        x[i] = tx;
                        y[i] = ty;
                    }
                }
                else
                {
                    for ( i = 0; i < 4; i++ )
                    {
                        x[i] = xmin + x[i] * dx;
                        y[i] = ymin + y[i] * dy;
                    }
                }
                if ( fill != NULL )
                    exfill( fill, defined, (PLINT) 4, x, y );
                iy += j - 1;
                continue;
            }

            // Only part of rectangle can be filled

            n_point = min_points = max_points = 0;
            n       = find_interval( a0[iy], a0[iy + 1], c0[iy], c0[iy + 1], xp );
            for ( j = 0; j < n; j++ )
            {
                x[j] = ix;
                y[j] = iy + xp[j];
            }

            i = find_interval( a0[iy + 1], a1[iy + 1],
                c0[iy + 1], c1[iy + 1], xp );

            for ( j = 0; j < i; j++ )
            {
                x[j + n] = ix + xp[j];
                y[j + n] = iy + 1;
            }
            n += i;

            i = find_interval( a1[iy + 1], a1[iy], c1[iy + 1], c1[iy], xp );
            for ( j = 0; j < i; j++ )
            {
                x[n + j] = ix + 1;
                y[n + j] = iy + 1 - xp[j];
            }
            n += i;

            i = find_interval( a1[iy], a0[iy], c1[iy], c0[iy], xp );
            for ( j = 0; j < i; j++ )
            {
                x[n + j] = ix + 1 - xp[j];
                y[n + j] = iy;
            }
            n += i;

            if ( pltr )
            {
                for ( i = 0; i < n; i++ )
                {
                    ( *pltr )( x[i], y[i], &tx, &ty, pltr_data );
                    x[i] = tx;
                    y[i] = ty;
                }
            }
            else
            {
                for ( i = 0; i < n; i++ )
                {
                    x[i] = xmin + x[i] * dx;
                    y[i] = ymin + y[i] * dy;
                }
            }

            if ( min_points == 4 )
                slope = plctestez( a, nx, ny, ix, iy, shade_min );
            if ( max_points == 4 )
                slope = plctestez( a, nx, ny, ix, iy, shade_max );

            // n = number of end of line segments
            // min_points = number times shade_min meets edge
            // max_points = number times shade_max meets edge

            // special cases: check number of times a contour is in a box

            switch ( ( min_points << 3 ) + max_points )
            {
            case 000:
            case 020:
            case 002:
            case 022:
                if ( fill != NULL && n > 0 )
                    exfill( fill, defined, n, x, y );
                break;
            case 040:   // 2 contour lines in box
            case 004:
                if ( n != 6 )
                    fprintf( stderr, "plfshade err n=%d !6", (int) n );
                if ( slope == 1 && c0[iy] == OK )
                {
                    if ( fill != NULL )
                        exfill( fill, defined, n, x, y );
                }
                else if ( slope == 1 )
                {
                    selected_polygon( fill, defined, x, y, 0, 1, 2, -1 );
                    selected_polygon( fill, defined, x, y, 3, 4, 5, -1 );
                }
                else if ( c0[iy + 1] == OK )
                {
                    if ( fill != NULL )
                        exfill( fill, defined, n, x, y );
                }
                else
                {
                    selected_polygon( fill, defined, x, y, 0, 1, 5, -1 );
                    selected_polygon( fill, defined, x, y, 2, 3, 4, -1 );
                }
                break;
            case 044:
                if ( n != 8 )
                    fprintf( stderr, "plfshade err n=%d !8", (int) n );
                if ( slope == 1 )
                {
                    selected_polygon( fill, defined, x, y, 0, 1, 2, 3 );
                    selected_polygon( fill, defined, x, y, 4, 5, 6, 7 );
                }
                else
                {
                    selected_polygon( fill, defined, x, y, 0, 1, 6, 7 );
                    selected_polygon( fill, defined, x, y, 2, 3, 4, 5 );
                }
                break;
            case 024:
            case 042:
                // 3 contours
                if ( n != 7 )
                    fprintf( stderr, "plfshade err n=%d !7", (int) n );

                if ( ( c0[iy] == OK || c1[iy + 1] == OK ) && slope == 1 )
                {
                    if ( fill != NULL )
                        exfill( fill, defined, n, x, y );
                }
                else if ( ( c0[iy + 1] == OK || c1[iy] == OK ) && slope == 0 )
                {
                    if ( fill != NULL )
                        exfill( fill, defined, n, x, y );
                }

                else if ( c0[iy] == OK )
                {
                    selected_polygon( fill, defined, x, y, 0, 1, 6, -1 );
                    selected_polygon( fill, defined, x, y, 2, 3, 4, 5 );
                }
                else if ( c0[iy + 1] == OK )
                {
                    selected_polygon( fill, defined, x, y, 0, 1, 2, -1 );
                    selected_polygon( fill, defined, x, y, 3, 4, 5, 6 );
                }
                else if ( c1[iy + 1] == OK )
                {
                    selected_polygon( fill, defined, x, y, 0, 1, 5, 6 );
                    selected_polygon( fill, defined, x, y, 2, 3, 4, -1 );
                }
                else if ( c1[iy] == OK )
                {
                    selected_polygon( fill, defined, x, y, 0, 1, 2, 3 );
                    selected_polygon( fill, defined, x, y, 4, 5, 6, -1 );
                }
                else
                {
                    fprintf( stderr, "plfshade err logic case 024:042\n" );
                }
                break;
            default:
                fprintf( stderr, "prog err switch\n" );
                break;
            }
            draw_boundary( slope, x, y );

            if ( fill != NULL )
            {
                plwidth( sh_width );
                if ( sh_cmap == 0 )
                    plcol0( (PLINT) sh_color );
                else if ( sh_cmap == 1 )
                    plcol1( sh_color );
            }
        }

        a0  = a1;
        c0  = c1;
        a1 += ny;
        c1 += ny;
    }

    free( c );
    free( a );
    plwidth( init_width );
}
Exemplo n.º 4
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); */
    }
}