|
|
2ed0d1 |
|
|
|
2ed0d1 |
#include <helianthus.h></helianthus.h>
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
#define COUNT 5
|
|
|
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 |
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
double calcCurveValue(double *curve, int count, double x) {
|
|
|
2ed0d1 |
if (count <= 0) return 0;
|
|
|
2ed0d1 |
if (count == 1) return curve[1];
|
|
|
2ed0d1 |
if (x <= curve[0]) return curve[1];
|
|
|
2ed0d1 |
if (x >= curve[(count-1)*2]) return curve[(count-1)*2 + 1];
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
int i = 0;
|
|
|
2ed0d1 |
while(i+1 < count && curve[(i+1)*2] < x)
|
|
|
2ed0d1 |
++i;
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
double *p1 = &curve[i*2];
|
|
|
2ed0d1 |
double *p0 = i > 0 ? p1-2 : p1;
|
|
|
2ed0d1 |
double *p2 = i+1 < count ? p1+2 : p1;
|
|
|
2ed0d1 |
double *p3 = i+2 < count ? p2+2 : p2;
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
double dx = p2[0] - p1[0];
|
|
|
2ed0d1 |
if (dx <= PRECISION) return p1[1];
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
double a = p1[1];
|
|
|
2ed0d1 |
double b = p2[1];
|
|
|
2ed0d1 |
double ta = p2[0]-p0[0]; ta = ta > PRECISION ? (p2[1]-p0[1])/ta*dx : 0;
|
|
|
2ed0d1 |
double tb = p3[0]-p1[0]; tb = tb > PRECISION ? (p3[1]-p1[1])/tb*dx : 0;
|
|
|
2ed0d1 |
double l = (x - p1[0])/dx;
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
return a + (ta + (3*(b-a)-ta-ta-tb + (2*(a-b)+ta+tb)*l)*l)*l;
|
|
|
2ed0d1 |
}
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
void init() {
|
|
|
2ed0d1 |
for(int i = 0; i < COUNT; ++i)
|
|
|
2ed0d1 |
points[i][0] = points[i][1] = i/(COUNT - 1.0);
|
|
|
2ed0d1 |
calcCurveValue(points[0], COUNT, 0.3);
|
|
|
2ed0d1 |
}
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
void draw() {
|
|
|
2ed0d1 |
double w = windowGetWidth();
|
|
|
2ed0d1 |
double h = windowGetHeight();
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
saveState();
|
|
|
2ed0d1 |
translate(0, h);
|
|
|
2ed0d1 |
scale(1, -1);
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
noFill();
|
|
|
2ed0d1 |
stroke(colorByRGBA(0.75, 0.75, 0.75, 1));
|
|
|
2ed0d1 |
strokeWidth(2);
|
|
|
2ed0d1 |
rect(0, 0, w, h);
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
strokeWidth(2);
|
|
|
2ed0d1 |
line(0, 0, w, h);
|
|
|
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])/w;
|
|
|
2ed0d1 |
curPoint[1] = (my + curPointOffset[1])/h;
|
|
|
2ed0d1 |
}
|
|
|
2ed0d1 |
|
|
|
2ed0d1 |
stroke(COLOR_BLUE);
|
|
|
2ed0d1 |
fill(COLOR_WHITE);
|
|
|
2ed0d1 |
for(int i = 0; i < w+1; ++i)
|
|
|
2ed0d1 |
lineTo(i, calcCurveValue(points[0], COUNT, i/w)*h);
|
|
|
2ed0d1 |
strokePath();
|
|
|
2ed0d1 |
for(int i = 0; i < COUNT; ++i) {
|
|
|
2ed0d1 |
double x = points[i][0]*w, y = points[i][1]*h;
|
|
|
2ed0d1 |
circle(x, y, RADIUS);
|
|
|
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 |
}
|