Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/cgraph/
Upload File :
Current File : /usr/home/beeson/MathXpert/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.
   2.16.25 removed unused variables vradius and aspect
   3.10.25, added fourth argument to filled_circle
*/
#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.
*/
{
  int hradius;
  // 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 */
     /* But in SVG, filled_circle attends to the aspect ratio. */
  radius = device -> xpixel * hradius; /* world coord horiz radius */
  filled_circle(x,y,radius,1);   // 3.10.25, added fourth argument
  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