Sindbad~EG File Manager

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

/* M. Beeson, for Mathpert.
   Implement the Spot for parametric graphs
*/
/* Original date 8.10.95
   last modified 1.29.98
   2.24.24  removed windows.h etc.
   2.25.24 removed get_aspect() call
   2.28.24  modified place_spot to use double coordinates
   7.22.24  commented out some lines so it can compile with WebMathXpert
   even though it isn't yet used. 
*/
#include <assert.h>
#include <math.h>   /* fabs */
#include "globals.h"
#include "graphstr.h"
#include "deval.h"
#include "svgGraph.h"
#define ROUNDOFF(x)   (int)((x)+0.5)
/*___________________________________________________________________*/
static void place_spot(graph *g, double x, double y)
/* draw the "spot" at(x,y), and record the upper left coordinates
for the spot in g->root_xcoords[0] and g->root_ycoords[0].
Here j starts from 1, not 0.
*/
{
  static double aspect = 1.0;
  int hradius,vradius;
  // int k,hdistance,vdistance;
  svgDevice *device = get_device();
  double radius;
  double *pleft = g->root_xcoords;
  double *ptop =  g->root_ycoords;
        /* space to record where the roots are written by putimage */
  hradius = (int) g->linewidth * 3;
  vradius = ROUNDOFF( hradius * device->numypixels/(device->numxpixels * aspect));
         /* vertical radius of filled circle in device coordinates */
  radius = device -> xpixel * hradius; /* world coord horiz radius */
  filled_circle(x,y,radius);
  world_to_pixel(x,y,pleft,ptop);
}

/*______________________________________________________________*/
void draw_spot(graph *g)
/* It is assumed that g is a parametric graph or a space curve.
Draw the Spot at location given by g->tselected.
*/

{ double t = g->tselected;
  double x,y,z;
  int mainchoice = g->graphtype;
  assert(mainchoice == PARAMETRIC || mainchoice == SPACECURVE);
  /* Compute the coordinate values for the Spot */
  SETVALUE(g->independent_variable,t);
  deval(g->xfunction,&x);
  if(x == BADVAL || x < g->xmin || x > g->xmax)
     return;
  deval(g->yfunction,&y);
  if(y == BADVAL || y < g->ymin || y > g->ymax)
     return;
  if(mainchoice == SPACECURVE)
     { deval(g->zfunction,&z);
       if(z == BADVAL  || z < g->zmin || z > g->zmax)
          return;
       return;   /* FINISH THIS: convert x,y,z to pixel coords and
                    draw the bitmap */
     }
  if(mainchoice == PARAMETRIC)
     { place_spot(g,x,y);
     }
}

/*______________________________________________________________*/
void erase_spot(graph *g)
/* It is assumed that g is a parametric graph or a space curve.
  Erase the Spot at location given by g->tselected by filling
the Spot's rectangle with the color given by g->background,
and then redrawing a portion of the graph line near g->tselected.
*/

{ double t = g->tselected;
  double x,y,z,u,v,tgap,lo,hi;
  double *tp;
  svgDevice *device;
  int stoploop, count;
  term xf, yf;
  static int pwidth, pheight;
  double dwidth, dheight;
  int mainchoice = g->graphtype;
  assert(mainchoice == PARAMETRIC || mainchoice == SPACECURVE);
  /* Compute the coordinate values for the Spot */
  SETVALUE(g->independent_variable,t);
  deval(g->xfunction,&x);
  if(x == BADVAL || x < g->xmin || x > g->xmax)
     return;
  deval(g->yfunction,&y);
  if(y == BADVAL || y < g->ymin || y > g->ymax)
     return;
//  if(pwidth == 0)
//     get_image_size(g->spot,&pwidth,&pheight);

  if(mainchoice == SPACECURVE)
     { deval(g->zfunction,&z);
       if(z == BADVAL  || z < g->zmin || z > g->zmax)
          return;
       return;   /* FINISH THIS: convert x,y,z to pixel coords and
                    proceed */
     }
  if(mainchoice == PARAMETRIC)
     { device = get_device();
       dwidth = device->xpixel * pwidth;
       dheight = device->ypixel * pheight;
       set_graphbackgroundcolor(g->background);
       filled_rect(x-dwidth/2,y-dheight/2,x+dwidth/2, y+dheight/2);
       /* 'black out' the old spot with background color */
       set_graphpencolor(g->graphcolor);
       /* If the rectangle covers part of the axes, we must repaint
          the axes over that part. */
       if(x-dwidth <= 0.0 && x+dwidth >= 0.0)
          { /* repaint part of the y-axis */
            set_linewidth(THIN);
            set_graphpencolor(g->axescolor);
            move_to(0.0, y-dheight);
            line_to(0.0, y+dheight);
            set_graphpencolor(g->graphcolor);
            set_linewidth(THICK);
          }
       if(y-dheight <= 0.0 && y+dheight >= 0.0)
          { /* repaint part of the x-axis */
            set_linewidth(THIN);
            set_graphpencolor(g->axescolor);
            move_to(x-dwidth,0.0);
            line_to(x+dwidth,0.0);
            set_graphpencolor(g->graphcolor);
            set_linewidth(THICK);
          }

       /* Now draw the portion of the graph line over this rectangle */
       tp = (double *) (ARGPTR(g->independent_variable));
       xf = g->xfunction;
       yf = g->yfunction;
       /* Now, how big a t-interval is required? */
       tgap = (g->tmax - g->tmin)/200.0;
       count = 1;
       for(stoploop = 0; count == 1 && stoploop < 5; ++stoploop)
          { u = x;
            v = y;
            *tp = t;
            for(count = 0; fabs(u-x) < dwidth && fabs(v-y) < dheight && count < 20; ++count)
               { /* while (u,v) is inside the rectangle increase the gap */
                 /*  But don't die here--if 20 increments isn't enough give up. */
                 *tp -= tgap;
                 deval(xf,&u);
                 if(u == BADVAL)
                    break;
                 deval(yf,&v);
                 if(v == BADVAL)
                    break;
               }
            if(count == 1)  /* out of the rectangle in one step */
               tgap /= 2.0;  /* and try again */
            if(u == BADVAL || v == BADVAL)
               { count = 1;
                 tgap /= 2.0;  /* and try again */
               }
            if(count == 20)
               { count = 1;
                 tgap *= 2.0;  /* and try again */
               }
          }
       if(stoploop == 5)
          return;  /* Failed */
       lo = *tp;
       if(lo < g->tmin)
          lo = g->tmin;
       *tp = t;
       u = x;
       v = y;
       for(count = 0; count < 20 && fabs(u-x) < dwidth && fabs(v-y) < dheight;++count)
          { /* while (u,v) is inside the rectangle increase the gap */
            *tp += tgap;
            deval(xf,&u);

          }
       hi = *tp;
       if(hi > g->tmax)
          hi = g->tmax;
       *tp = t;
       /* Now divide the interval into five steps and go for it. */
       tgap = (hi-lo)/5.0;
       if(tgap == 0.0)
          return;   /* BADVAL's immediately on both sides */
       *tp = lo;
       deval(xf,&u);
       deval(yf,&v);
       move_to(u,v);
       for(count = 1;count < 5; ++count)
          { *tp = lo + tgap *count;
            deval(xf,&u);
            deval(yf,&v);
            if(u != BADVAL && v != BADVAL)
               line_to(u,v);
          }
       *tp = t;
     }
}

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