Blame onefile/curves.c

2ed0d1
2ed0d1
#include <helianthus.h></helianthus.h>
2ed0d1
#include <math.h></math.h>
2ed0d1
2ed0d1
2ed0d1
#define COUNT     16
2ed0d1
#define SIZE      17
2ed0d1
#define RADIUS    5
2ed0d1
#define PRECISION 1e-5
2ed0d1
2ed0d1
2ed0d1
double points[COUNT][2];
2ed0d1
double *curPoint;
2ed0d1
double curPointOffset[2];
2ed0d1
2ed0d1
int graphs[10];
2ed0d1
2ed0d1
2ed0d1
double value(int ix)
2ed0d1
  { return points[ ((ix + COUNT/2)%COUNT + COUNT)%COUNT ][1]; }
2ed0d1
2ed0d1
double nearest(double x)
2ed0d1
  { return value(floor(x)); }
2ed0d1
2ed0d1
double linear(double x) {
2ed0d1
  x -= 0.5;
2ed0d1
  int ix = floor(x);
2ed0d1
  x -= ix;
2ed0d1
  return value(ix)*(1-x) + value(ix+1)*x;
2ed0d1
}
2ed0d1
2ed0d1
double cubic(double x) {
2ed0d1
  x -= 0.5;
2ed0d1
  int ix = floor(x);
2ed0d1
  x -= ix;
2ed0d1
2ed0d1
  double a = value(ix-1);
2ed0d1
  double b = value(ix+0);
2ed0d1
  double c = value(ix+1);
2ed0d1
  double d = value(ix+2);
2ed0d1
2ed0d1
  return a*( -0.5*x*x*x +     x*x - 0.5*x )
2ed0d1
			 + b*(  1.5*x*x*x - 2.5*x*x + 1.0   )
2ed0d1
			 + c*( -1.5*x*x*x + 2.0*x*x + 0.5*x )
2ed0d1
			 + d*(  0.5*x*x*x - 0.5*x*x         );
2ed0d1
}
2ed0d1
2ed0d1
double bspline(double x) {
2ed0d1
  x -= 0.5;
2ed0d1
  int ix = floor(x);
2ed0d1
  x -= ix;
2ed0d1
2ed0d1
  double a = value(ix-1);
2ed0d1
  double b = value(ix+0);
2ed0d1
  double c = value(ix+1);
2ed0d1
  double d = value(ix+2);
2ed0d1
2ed0d1
  return a*(  -x*x*x + 3*x*x - 3*x + 1)/6
2ed0d1
			 + b*( 3*x*x*x - 6*x*x + 4      )/6
2ed0d1
			 + c*(-3*x*x*x + 3*x*x + 3*x + 1)/6
2ed0d1
			 + d*(   x*x*x                  )/6;
2ed0d1
}
2ed0d1
2ed0d1
2ed0d1
void graph(double kx, double ky, double (*func)(double), unsigned int color) {
2ed0d1
  saveState();
2ed0d1
  strokeWidth(2);
2ed0d1
  stroke(color);
2ed0d1
  int hs = (int)ceil(SIZE*kx/2);
2ed0d1
  for(int x = -hs; x <= hs; ++x)
2ed0d1
    lineTo(x, func(x/kx)*ky);
2ed0d1
  strokePath();
2ed0d1
  restoreState();
2ed0d1
}
2ed0d1
2ed0d1
2ed0d1
void grid(double kx, double ky) {
2ed0d1
  saveState();
2ed0d1
  strokeWidth(1);
2ed0d1
  stroke(colorByRGBA(0, 0, 1, 0.125));
2ed0d1
  double hs = 0.5*SIZE;
2ed0d1
  for(int step = 16; step; step >>= 1) {
2ed0d1
    for(int i = 0; i <= SIZE/2; i += step) {
2ed0d1
      line(-hs*kx,  i*ky, hs*kx,  i*ky);
2ed0d1
      line(-hs*kx, -i*ky, hs*kx, -i*ky);
2ed0d1
      line( i*kx, -hs*ky,  i*kx, hs*ky);
2ed0d1
      line(-i*kx, -hs*ky, -i*kx, hs*ky);
2ed0d1
    }
2ed0d1
  }
2ed0d1
  restoreState();
2ed0d1
}
2ed0d1
2ed0d1
void randomize() {
2ed0d1
  for(int i = 0; i < COUNT; ++i)
2ed0d1
    points[i][1] = randomFloat()*SIZE - SIZE/2.0;
2ed0d1
}
2ed0d1
2ed0d1
void zero() {
2ed0d1
  for(int i = 0; i < COUNT; ++i)
2ed0d1
    points[i][1] = 0;
2ed0d1
}
2ed0d1
2ed0d1
void init() {
2ed0d1
  for(int i = 0; i < COUNT; ++i)
2ed0d1
    points[i][0] = i - COUNT/2 + 0.5;
2ed0d1
  randomize();
2ed0d1
}
2ed0d1
2ed0d1
2ed0d1
void draw() {
2ed0d1
  double w = windowGetWidth();
2ed0d1
  double h = windowGetHeight();
2ed0d1
  double kx = w/SIZE;
2ed0d1
  double ky = h/SIZE;
2ed0d1
2ed0d1
  saveState();
2ed0d1
  translate(w/2, h/2);
2ed0d1
  scale(1, -1);
2ed0d1
2ed0d1
  if (keyWentDown("r")) { randomize(); curPoint = 0; }
2ed0d1
  if (keyWentDown("z")) { zero(); curPoint = 0; }
2ed0d1
  char key[] = "0";
2ed0d1
  for(int i = 0; i < 10; ++i, ++*key)
2ed0d1
    if (keyWentDown(key)) graphs[i] = !graphs[i];
2ed0d1
2ed0d1
  int m = mouseWentDown("left");
2ed0d1
  double mx = mouseTransformedX();
2ed0d1
  double my = mouseTransformedY();
2ed0d1
  if (!mouseDown("left"))
2ed0d1
    { m = FALSE; curPoint = 0; }
2ed0d1
  if (curPoint) {
2ed0d1
    //curPoint[0] = (mx + curPointOffset[0])/kx;
2ed0d1
    curPoint[1] = (my + curPointOffset[1])/ky;
2ed0d1
  }
2ed0d1
2ed0d1
  grid(kx, ky);
2ed0d1
  if (graphs[0]) graph(kx, ky, nearest, colorByRGBA(0, 0, 0, 0.5));
2ed0d1
  if (graphs[1]) graph(kx, ky, linear , colorByRGBA(0, 1, 0, 0.5));
2ed0d1
  if (graphs[2]) graph(kx, ky, cubic  , colorByRGBA(0, 0, 1, 0.5));
2ed0d1
  if (graphs[3]) graph(kx, ky, bspline, colorByRGBA(1, 0, 0, 0.5));
2ed0d1
2ed0d1
  strokeWidth(2);
2ed0d1
  stroke(COLOR_BLUE);
2ed0d1
  fill(COLOR_WHITE);
2ed0d1
  for(int i = 0; i < COUNT; ++i) {
2ed0d1
    double x = points[i][0]*kx, y = points[i][1]*ky;
2ed0d1
    line(x, 0, x, y);
2ed0d1
    circle(x, y, RADIUS);
2ed0d1
    if (i == COUNT/2)
2ed0d1
      circle(x, y, RADIUS + 1);
2ed0d1
    double dx = x-mx, dy = y-my;
2ed0d1
    if (m && dx*dx + dy*dy <= RADIUS*RADIUS) {
2ed0d1
      curPoint = points[i];
2ed0d1
      curPointOffset[0] = dx;
2ed0d1
      curPointOffset[1] = dy;
2ed0d1
    }
2ed0d1
  }
2ed0d1
2ed0d1
  restoreState();
2ed0d1
}
2ed0d1
2ed0d1
2ed0d1
int main() {
2ed0d1
  windowSetVariableFrameRate();
2ed0d1
  windowSetResizable(TRUE);
2ed0d1
  windowSetInit(&init);
2ed0d1
  windowSetDraw(&draw);
2ed0d1
  windowRun();
2ed0d1
  return 0;
2ed0d1
}