Blame onefile/splines.c

Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
#include <math.h>
Ivan Mahonin 2ed0d1
#include <helianthus.h>
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
#define COUNT     10
Ivan Mahonin 2ed0d1
#define TL        20
Ivan Mahonin 2ed0d1
#define RADIUS    5
Ivan Mahonin 2ed0d1
#define PRECISION 1e-5
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
typedef struct { double x, y, tx, ty; } Point;
Ivan Mahonin 2ed0d1
typedef struct { double A, B, C, D; } Spline;
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
Point points[COUNT];
Ivan Mahonin 2ed0d1
Point *curPoint;
Ivan Mahonin 2ed0d1
double curPointOffset[2];
Ivan Mahonin 2ed0d1
int curTangent;
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
void splineInit(Spline *s, double a, double b, double ta, double tb) {
Ivan Mahonin 2ed0d1
  double d = b - a;
Ivan Mahonin 2ed0d1
  if (!(fabs(d) > 1e-6))
Ivan Mahonin 2ed0d1
    { s->A = a; s->B = s->C = s->D = 0; return; }
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
  double B = ta;
Ivan Mahonin 2ed0d1
  double C = ((ta*ta - tb*tb)/d - d)*0.5;
Ivan Mahonin 2ed0d1
  double A = a - C;
Ivan Mahonin 2ed0d1
  double x = ta*tb + C*(d + C);
Ivan Mahonin 2ed0d1
  double y = ta*d + C*(ta - tb);
Ivan Mahonin 2ed0d1
  double D = atan2(fabs(y), x);
Ivan Mahonin 2ed0d1
  //if (D < 0) D += PI;
Ivan Mahonin 2ed0d1
  if (d < 0) D = -D;
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
  s->A = A;
Ivan Mahonin 2ed0d1
  s->B = B;
Ivan Mahonin 2ed0d1
  s->C = C;
Ivan Mahonin 2ed0d1
  s->D = D;
Ivan Mahonin 2ed0d1
}
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
double splineValue(const Spline *s, double l) {
Ivan Mahonin 2ed0d1
  l *= s->D;
Ivan Mahonin 2ed0d1
  return s->A + s->B*sin(l) + s->C*cos(l);
Ivan Mahonin 2ed0d1
}
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
double splineTangent(const Spline *s, double l) {
Ivan Mahonin 2ed0d1
  l *= s->D;
Ivan Mahonin 2ed0d1
  return s->B*cos(l) + s->C*sin(l);
Ivan Mahonin 2ed0d1
}
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
void drawSplineSegment(const Point *a, const Point *b) {
Ivan Mahonin 2ed0d1
  Spline sx, sy;
Ivan Mahonin 2ed0d1
  splineInit(&sx, a->x, b->x, a->tx, b->tx);
Ivan Mahonin 2ed0d1
  splineInit(&sy, a->y, b->y, a->ty, b->ty);
Ivan Mahonin 2ed0d1
  int count = 10;
Ivan Mahonin 2ed0d1
  for(int i = 1; i < count; ++i) {
Ivan Mahonin 2ed0d1
    double l = i/(double)count;
Ivan Mahonin 2ed0d1
    double x = splineValue(&sx, l);
Ivan Mahonin 2ed0d1
    double y = splineValue(&sy, l);
Ivan Mahonin 2ed0d1
    lineTo(x, y);
Ivan Mahonin 2ed0d1
  }
Ivan Mahonin 2ed0d1
  lineTo(b->x, b->y);
Ivan Mahonin 2ed0d1
}
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
void drawSpline(const Point *p, int count) {
Ivan Mahonin 2ed0d1
  if (count < 2) return;
Ivan Mahonin 2ed0d1
  moveTo(p->x, p->y);
Ivan Mahonin 2ed0d1
  for(int i = 1; i < count; ++i)
Ivan Mahonin 2ed0d1
    drawSplineSegment(p+i-1, p+i);
Ivan Mahonin 2ed0d1
  strokePath();
Ivan Mahonin 2ed0d1
}
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
void init() {
Ivan Mahonin 2ed0d1
  for(int i = 0; i < COUNT; ++i) {
Ivan Mahonin 2ed0d1
    points[i].x = (i/(COUNT - 1.0) - 0.5)*256;
Ivan Mahonin 2ed0d1
    points[i].tx = 100.0;
Ivan Mahonin 2ed0d1
  }
Ivan Mahonin 2ed0d1
}
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
void draw() {
Ivan Mahonin 2ed0d1
  double w = windowGetWidth();
Ivan Mahonin 2ed0d1
  double h = windowGetHeight();
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
  saveState();
Ivan Mahonin 2ed0d1
  translate(w/2, h/2);
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
  int m = mouseWentDown("left");
Ivan Mahonin 2ed0d1
  double mx = mouseTransformedX();
Ivan Mahonin 2ed0d1
  double my = mouseTransformedY();
Ivan Mahonin 2ed0d1
  if (!mouseDown("left"))
Ivan Mahonin 2ed0d1
    { m = FALSE; curPoint = 0; }
Ivan Mahonin 2ed0d1
  if (curPoint) {
Ivan Mahonin 2ed0d1
    curPoint->x = mx + curPointOffset[0];
Ivan Mahonin 2ed0d1
    curPoint->y = my + curPointOffset[1];
Ivan Mahonin 2ed0d1
  }
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
  strokeWidth(2);
Ivan Mahonin 2ed0d1
  stroke(COLOR_BLUE);
Ivan Mahonin 2ed0d1
  fill(COLOR_WHITE);
Ivan Mahonin 2ed0d1
  drawSpline(points, COUNT);
Ivan Mahonin 2ed0d1
  for(int i = 0; i < COUNT; ++i) {
Ivan Mahonin 2ed0d1
    Point *p = points + i;
Ivan Mahonin 2ed0d1
    circle(p->x, p->y, RADIUS);
Ivan Mahonin 2ed0d1
    double dx = p->x-mx, dy = p->y-my;
Ivan Mahonin 2ed0d1
    if (m && dx*dx + dy*dy <= RADIUS*RADIUS) {
Ivan Mahonin 2ed0d1
      curPoint = p;
Ivan Mahonin 2ed0d1
      curPointOffset[0] = dx;
Ivan Mahonin 2ed0d1
      curPointOffset[1] = dy;
Ivan Mahonin 2ed0d1
    }
Ivan Mahonin 2ed0d1
  }
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
  restoreState();
Ivan Mahonin 2ed0d1
}
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
Ivan Mahonin 2ed0d1
int main() {
Ivan Mahonin 2ed0d1
  windowSetVariableFrameRate();
Ivan Mahonin 2ed0d1
  windowSetResizable(TRUE);
Ivan Mahonin 2ed0d1
  windowSetInit(&init);
Ivan Mahonin 2ed0d1
  windowSetDraw(&draw);
Ivan Mahonin 2ed0d1
  windowRun();
Ivan Mahonin 2ed0d1
  return 0;
Ivan Mahonin 2ed0d1
}