I've been looking up the algorithms and stuff for calculating and drawing splines, and while I can understand some of the explanations, all the images of way too small and incomplete (math) functions, and formulas/equations.
Is there someone here who can explain it for a coder?
Yes. You have a set of points. Your goal is to draw a curve that starts in the first point and ends in the last. You can do that by drawing short straight segments, short enough so that it's not obvious they are straight. So you take a parameter that goes from 0 to 1 with small increments in a for loop. You feed this parameter into some sort of formula to get the next point. You draw a straight line from the previous point to the one you just calculated and move on. When the parameter is 0, the point you get is p0 (the starting points) and when it is 1, the point is your last point. So by the time your for loop ends, you will have drawn a smooth curve between p0 and p3 (if you have 4 points). There are a few different formulas to draw splines for different purposes (you want the line to go through all points or not, the kind of connectivity you want, how changing one point affects the curve, etc.) Bezier is a really simple kind of spline (B-Spline for 4 points). I don't know the equations by heart, but google does...
Thats the issue, I've read a few different explanations that had the equations in them, but I can't read any of them. English and code is fine, pictures of equations I can't do.
In that case I think you should forget about all that stuff...
Here's pseudocode anyway:
Point points[4]; Point p0 = points[0]; for (double p=0.0; p<=1.0; p+=0.01) { Point p1 = some_formula(points, p); draw_line(p0, p1); p0 = p1; }
Yeah, That I can understand, its the some_formula() that I need to understand.
I've already written a nice "arc" drawing routine:
| 1 | void draw_arc(BITMAP *bmp, point p1, point p2, double step) |
| 2 | { |
| 3 | point mp; |
| 4 | |
| 5 | step = M_PI / step; |
| 6 | |
| 7 | mp.x = ( p1.x + p2.x ) / 2.0; |
| 8 | mp.y = ( p1.y + p2.y ) / 2.0; |
| 9 | |
| 10 | double w = fabs(p2.x - p1.x); |
| 11 | double h = fabs(p2.y - p1.y); |
| 12 | double ll = sqrt(w*w + h*h); |
| 13 | double r = ll / 2.0; |
| 14 | |
| 15 | double start = atan2( p1.y - mp.y , p1.x - mp.x ); |
| 16 | double end = start+rad(180); //atan2( p2.y - mp.y , p2.x - mp.x ); |
| 17 | //start + M_PI; |
| 18 | |
| 19 | double rw = ll; |
| 20 | double rh = ll; |
| 21 | |
| 22 | // for testing only, real algo is below |
| 23 | arc(bmp, mp.x, mp.y, ftofix(deg(-start) * 256.0 / 360.0), ftofix(deg(-end) * 256.0 / 360.0), r, makecol(55,55,55)); |
| 24 | |
| 25 | start -= rad(180); |
| 26 | double pheta = start; |
| 27 | end -= rad(180); |
| 28 | |
| 29 | printf("\rstart: %f, end: %f", deg(start), deg(end)); |
| 30 | |
| 31 | double lx = rw/2 * cos( pheta ) + mp.x; |
| 32 | double ly = rh/2 * sin( pheta ) + mp.y; |
| 33 | double fx = lx; |
| 34 | double fy = ly; |
| 35 | |
| 36 | for(; pheta - ( end ) < 0.001; pheta += step) { |
| 37 | double x = rw/2 * cos( pheta ) + mp.x; |
| 38 | double y = rh/2 * sin( pheta ) + mp.y; |
| 39 | |
| 40 | // if(lx && ly) { |
| 41 | line(bmp, lx, ly, x, y, makecol(255, 255, 255)); |
| 42 | putpixel(bmp, lx, ly, makecol(255,0,0)); |
| 43 | putpixel(bmp, x, y, makecol(255,0,0)); |
| 44 | // } |
| 45 | |
| 46 | lx = x; |
| 47 | ly = y; |
| 48 | } |
| 49 | |
| 50 | if(lx != p1.x && ly != p1.y) { |
| 51 | line(bmp, lx, ly, p1.x, p1.y, makecol(100, 255, 100)); |
| 52 | } |
| 53 | |
| 54 | if(fx != p2.x && fy != p2.y) { |
| 55 | line(bmp, fx, fy, p2.x, p2.y, makecol(100, 255, 100)); |
| 56 | } |
| 57 | |
| 58 | |
| 59 | // rect(bmp, p1.x, p1.y, p2.x, p2.y, makecol(100,100,100)); |
| 60 | rect(bmp, mp.x-r, mp.y-r, mp.x+r, mp.y+r, makecol(150,150,150)); |
| 61 | line(bmp, p1.x, p1.y, p2.x, p2.y, makecol(0,0,255)); |
| 62 | putpixel(bmp, mp.x, mp.y, makecol(0,255,0)); |
| 63 | |
| 64 | } |
Hmm, I wouldn't bother with that function... It would work, I wager, but involves extra maths to compute the remaining splines.
This is a very nice spline. I recommend you use it. To start, just go through and interpolate between two points, then you can move into more.
That formula takes input as points (split into an x formula and a y formula). Take two arbitrary points, and for m1 use (1, 0) and for m2 use (-1, 0).
I was looking at a bunch of links, and one that really looked neat was the NURB spline. course it had all kinds of corner cases that it had to take care of using extra nodes and such.
[quote]Hmm, I wouldn't bother with that function...[/quote]If you mean my arc function, its for arcs
and it only does 180° arcs, due to the start + 180
but that was intentional. It wwasn'tintended for use as a spline helper, just something to say that I'm not a complete idiot, just I can't read most of the "theoretical" equations, [b]especially[/b] when the images used are about 2x too small to show any of the smaller var names legibly.
But thank you, I should be able to do something with that one.
NURBs are the most generalized kind of splines. All other kinds of splines are basically NURBs with some parts fixed or simplified or ommited or something...
Good. This is a bump so you can psot back here once you get that sorted, and we can go into using more than 4 control points.
Here's a small test program I wrote when I was studying B-splines. The code is not well organized but the important part is nice and easy to read. The functions you're interested in are make_spline() and N() plus some global variables.