Sindbad~EG File Manager

Current Path : /home/beeson/cgraph/
Upload File :
Current File : //home/beeson/cgraph/contour.c

/* contour plots */
/*
9.17.92, file created
7.10.96 code last modified
6.14.98 last modified
4.19.00 removed calls to user_interrupt
2.24.24 changed include cgraph. to svgGraph.h, added include rgb,
        changed svgDevice to svgDevice
        removed code for printers
3.25.24  changed color variables to unsigned from unsigned long
*/

#include <math.h>
#include <assert.h>
#include <stdlib.h>
#include "rgb.h"
#include "globals.h"
#include "graphstr.h"
#include "svgGraph.h"
#include "grapher.h"
#include "dcomplex.h"
#include "deval.h"
#include "ceval.h"
#include "heap.h"

#include "wcolors.h"

static int promising(double a,double b,double c, double d,double e, double spacing);

static unsigned colors[] =
   { RED24, LIGHTGRAY24, BLUE24, GREEN24, CYAN24,
     MAGENTA24, YELLOW24, WHITE24, BLACK24
   };

#define NCOLORS  (sizeof(colors)/ sizeof(unsigned)-1)
/* -1 because the last entry is the background */

/*__________________________________________________________*/
static unsigned  colorfunction(double x, double y, double spacing)
/* return the color to use when a 'crossing' of a level line is found */
{ int n,xx,yy;
  if(x == y)
     return colors[NCOLORS];   /* speed up this common call */
  xx = (int)(x/spacing);
  yy = (int)(y/spacing);
  if(xx >= 0)
    ++xx;   /* avoid duplicating a color for small negative and positive values */
  if(yy >= 0)
    ++yy;
  if(xx < yy)
     n = xx;
  else if(yy < xx)
     n = yy;
  else if(x < 0.0 && y >= 0.0)
     n = 0;
  else if(y < 0.0 && x >= 0.0)
     n = 0;
  else
     return colors[NCOLORS];  /* the background color */
  /* Now n show which multiple of 'spacing' we are
     crossing.  It can be negative and/or large. */
  /* return a color depending on n that is one of
     the colors in the colors array and not equal
     to the background color */
  n = n % NCOLORS;
  if(n < 0)
     n += NCOLORS;
  /* Now n is nonnegative and < NCOLORS */
  return colors[n];
}

/*__________________________________________________________*/
void contourplot(term f,   /* relation to be graphed */
                   double *xp, double *yp, /* pointers to values of x,y */
                   double spacing,
                   unsigned background
                  )
/* graph level lines f(x,y)=constant  */
/* The code is a copy of graph_relation, except for the assignment of
color to CROSSING, and 'promising' has one more argument.
It gives different results only because the macro SIGNCHANGE is replaced by CROSSING
and the static function 'promising'
are different in this file than in graphrel.c. */

{ int nx1,nx2,ny1,ny2;  /* pixel coordinates of the viewport */
  int bigstep;
  svgDevice *device = get_device();
  int i,j;   /* loop variables */
  double e;
  double xpixel = device -> xpixel;
  double ypixel = device -> ypixel;
  double square[32][32];  /* for promising rectangles */
  double *col0;   /* dynamic array for one column of numbers */
  double *col1;   /* alternate with col0 to save copying */
  double *col,*othercol;    /* will be col0 and col1 alternately */
  unsigned  color;
  int u,v;
  double savex,savey;
  bigstep = 9;
  assert(bigstep <= 29);
    /* don't ever make it bigger or bounds on 'square' will be exceeded */
    /* bigstep must be odd; for the screen it should be 9; for
       postscript 29 might be a better value */
  if(background != colors[NCOLORS])
     { /* find the background color in the COLORS array
          and swap it into last position, namely colors[NCOLORS] */
       for(i=0;i<NCOLORS;i++)
         { if(colors[i] == background)
               { unsigned temp = colors[NCOLORS];
                 colors[NCOLORS] = colors[i];
                 colors[i] = temp;
                 break;
               }
         }
     }
  nx1 = device->pxmin;
  nx2 = device->pxmax;
  ny1 = device->pymin;
  ny2 = device->pymax;
  assert(ny1 < ny2);
      /* pixel coordinates are smaller at the top */
      /* so ny1 goes with ymax, and ny2 goes with ymin */
  col0 = (double *) callocate(ny2-ny1+bigstep+1,sizeof(double));
  if(col0==NULL)
     nospace();
  col1 = (double *) callocate(ny2-ny1+bigstep+1,sizeof(double));
  if(col1==NULL)
     nospace();
  col0 -= ny1-bigstep;  /* so  legal indices are col[ny1-bigstep]...col[ny2] */
  col1 -= ny1-bigstep;
  *xp = device->xmin + 0.5*device->xpixel;
    /* world coordinates begin half a pixel left of the first pixel */
  for(i=nx1; i<=nx2; i+=bigstep)
     { *yp = device->ymin + 0.5*ypixel;
       if( i & 1 )  /* i is odd */
          { col = col1;
            othercol = col0;
          }
       else  /* i is even */
          { col = col0;
            othercol = col1;
          }
       deval(f,col+ny2);   /* outside loop so don't have to check j > ny2 in loop */
       *yp += bigstep *ypixel;  /* set correct initial value of y */
       for(j=ny2-bigstep; j>ny1-bigstep; j-=bigstep)  /* compute the i-th column */
          { deval(f,col + j);
            savex = *xp;
            savey = *yp;
            *xp -= 0.5 * bigstep * xpixel;
            *yp -= 0.5 * bigstep * ypixel;
            deval(f,&e);
            *xp = savex;
            *yp = savey;
            if(i > nx1 && promising(col[j],col[j+bigstep],othercol[j+bigstep],othercol[j],e,spacing))
            /* then fill in the 'square' array with every-pixel
               values for the 14 by 14-pixel rectangle with (*xp,*yp) at the
               upper right (if bigstep is 11) */
               { *xp -= (bigstep+1) * xpixel;
                 for(u=0;u <= bigstep+2;u++)
                    { *yp = savey - (bigstep+1) *ypixel;
                       for(v=0; v <= bigstep+2;v++)
                          { deval(f,&square[u][v]);
                            if(v > 0)
                               { color = colorfunction(square[u][v],square[u][v-1],spacing);
                                 if(color != background)
                                    { draw_pixel(i-bigstep -1 + u,j+bigstep+1-v,color);
                                      draw_pixel(i-bigstep -1 + u,j+bigstep+2-v,color);
                                      if(u>0)
                                         { color = colorfunction(square[u-1][v],square[u][v],spacing);
                                           if(color != background)
                                              draw_pixel(i-bigstep+u-2,j+bigstep+1-v,color);
                                         }
                                    }
                               }
                            if(u > 0)
                               { color = colorfunction(square[u-1][v],square[u][v],spacing);
                                 if(color != background)
                                    { draw_pixel(i-bigstep+u-1,j+bigstep+1-v,color);
                                      draw_pixel(i-bigstep+u,j+bigstep+1-v,color);
                                    }
                               }
                            *yp += ypixel;
                           }
                       *xp += xpixel;
                    }
                 *xp = savex;
                 *yp = savey;
               }
            *yp += bigstep *ypixel;
          }
       *xp += bigstep * xpixel;
     }
  free2(col0 + ny1-bigstep);
  free2(col1 + ny1-bigstep);
}

/*______________________________________________________________________*/
static int promising(double a,double b,double c, double d,double e,double spacing)
/* a,b,c,d, are function values of f at corners of a rectangle,
in  clockwise order, and e is the value in the middle.
Is there any chance of a zero of f inside the
rectangle?  If so return 1, else return 0. */

{  double laplacian;
   if(colorfunction(a,b,spacing) || colorfunction(b,c,spacing) ||
      colorfunction(c,d,spacing) || colorfunction(d,e,spacing)
     )
      return 1;
   /* Now they all have the same sign */
   /* Compute the Laplacian; does it has the same sign as f?  */
   laplacian = a+b+c+d -4.0*e;
   if (fabs(laplacian) > 0.5 * spacing)
       return 1;   /* too curvy to ignore this square */
   else
       return 0;   /* take the risk of ignoring this square */
}

/*__________________________________________________________*/
void complex_contourplot(term f,   /* relation to be graphed */
                   double *xp, double *yp, /* pointers to values of x,y */
                   double spacing,
                   unsigned background
                  )
/* graph level lines f(x,y)=constant  */
/* f is supposed to be real-valued; actually it can be complex-valued
and the real part is graphed. */
/* code is a copy of that for contourplot except it uses ceval
instead of deval */

{ int nx1,nx2,ny1,ny2;  /* pixel coordinates of the viewport */
  int bigstep;
  dcomplex temp;
  unsigned  color;
  svgDevice *device = get_device();
  int i,j;   /* loop variables */
  double e;
  double xpixel = device -> xpixel;
  double ypixel = device -> ypixel;
  double square[32][32];  /* for promising rectangles */
  double *col0;   /* dynamic array for one column of numbers */
  double *col1;   /* alternate with col0 to save copying */
  double *col,*othercol;    /* will be col0 and col1 alternately */
  int u,v;
  double savex,savey;
  bigstep = 9;
  assert(bigstep <= 29);  /* don't ever make it bigger or bounds on 'square' will be exceeded */

   /* bigstep must be odd; for the screen it should be 9; for
      postscript 29 might be a better value */
  if(background != colors[NCOLORS])
     { /* find the background color in the COLORS array
          and swap it into last position, colors[NCOLORS] */
       for(i=0;i<NCOLORS;i++)
         { if(colors[i] == background)
               { unsigned temp = colors[NCOLORS];
                 colors[NCOLORS] = colors[i];
                 colors[i] = temp;
                 break;
               }
         }
     }
  nx1 = device->pxmin;
  nx2 = device->pxmax;
  ny1 = device->pymin;
  ny2 = device->pymax;
  assert(ny1 < ny2);
      /* pixel coordinates are smaller at the top */
      /* so ny1 goes with ymax, and ny2 goes with ymin */
  col0 = (double *) callocate(ny2-ny1+bigstep+1,sizeof(double));
  if(col0==NULL) nospace();
  col1 = (double *) callocate(ny2-ny1+bigstep+1,sizeof(double));
  if(col1==NULL) nospace();
  col0 -= ny1-bigstep;  /* so  legal indices are col[ny1-bigstep]...col[ny2] */
  col1 -= ny1-bigstep;
  *xp = device->xmin + 0.5 *device->xpixel;
    /* world coordinates begin half a pixel left of the first pixel */
  for(i=nx1; i<=nx2; i+=bigstep)
     { *yp = device->ymin + 0.5 *device->ypixel;
       if( i & 1 )  /* i is odd */
          { col = col1;
            othercol = col0;
          }
       else  /* i is even */
          { col = col0;
            othercol = col1;
          }
       ceval(f,&temp);
       col[ny2] = temp.r;  /* outside loop so don't have to check j > ny2 in loop */
       *yp += bigstep *ypixel;  /* set correct initial value of y */
       for(j=ny2-bigstep; j>ny1-bigstep; j-=bigstep)  /* compute the i-th column */
          { ceval(f,&temp);
            col[j] = temp.r;
            savex = *xp;
            savey = *yp;
            *xp -= 0.5 * bigstep * xpixel;
            *yp -= 0.5 * bigstep * ypixel;
            ceval(f,&temp);
            e = temp.r;
            *xp = savex;
            *yp = savey;
            if(i > nx1 && promising(col[j],col[j+bigstep],othercol[j+bigstep],othercol[j],e,spacing))
                 /* then fill in the 'square' array with every-pixel
                    values for the 14 by 14-pixel rectangle with (*xp,*yp) at the
                    upper right (if bigstep is 11) */

               { *xp -= (bigstep+1) * xpixel;
                 for(u=0;u <= bigstep+2;u++)
                    { *yp = savey - (bigstep+1) *ypixel;
                      for(v=0; v <= bigstep+2;v++)
                         { ceval(f,&temp);
                           square[u][v] = temp.r;
                           if(v > 0)
                              { color = colorfunction(square[u][v],square[u][v-1],spacing);
                                if(color != background)
                                   { draw_pixel(i-bigstep -1 + u,j+bigstep+1-v,color);
                                     draw_pixel(i-bigstep -1 + u,j+bigstep+2-v,color);
                                     if(u>0)
                                        { color = colorfunction(square[u-1][v],square[u][v],spacing);
                                          if(color != background)
                                             draw_pixel(i-bigstep+u-2,j+bigstep+1-v,color);
                                        }
                                   }
                              }
                           if(u > 0)
                              { color = colorfunction(square[u-1][v],square[u][v],spacing);
                                if(color != background)
                                   { draw_pixel(i-bigstep+u-1,j+bigstep+1-v,color);
                                     draw_pixel(i-bigstep+u,j+bigstep+1-v,color);
                                   }
                              }
                           *yp += ypixel;
                         }
                      *xp += xpixel;
                    }
                 *xp = savex;
                 *yp = savey;
               }
            *yp += bigstep *ypixel;
          }
       *xp += bigstep * xpixel;
     }
  free2(col0 + ny1-bigstep);
  free2(col1 + ny1-bigstep);
}

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists