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