| 1 |
module splines; |
|---|
| 2 |
import std.stdio, qd, tools.base; |
|---|
| 3 |
|
|---|
| 4 |
float blend(float a, float b, float x) { |
|---|
| 5 |
return a*(1f-x) + b*x; |
|---|
| 6 |
} |
|---|
| 7 |
|
|---|
| 8 |
float delegate(float) bezier2(float _v1, float _v2, float _v3, float _v4) { |
|---|
| 9 |
return (float v1, float v2, float v3, float v4, float x) { |
|---|
| 10 |
auto t1 = blend(v1, v2, x), t2 = blend(v2, v3, x), t3 = blend(v3, v4, x); |
|---|
| 11 |
auto u1 = blend(t1, t2, x), u2 = blend(t2, t3, x); |
|---|
| 12 |
return blend(u1, u2, x); |
|---|
| 13 |
} /fix/ stuple(_v1, _v2, _v3, _v4); |
|---|
| 14 |
} |
|---|
| 15 |
|
|---|
| 16 |
float delegate(float) multibezier(float[] values) { |
|---|
| 17 |
float[] controls; |
|---|
| 18 |
auto vals = values; vals ~= vals[$-1]; |
|---|
| 19 |
float prev; bool first = true; |
|---|
| 20 |
while (vals.length > 2) { |
|---|
| 21 |
float nv; |
|---|
| 22 |
if (first) nv = vals[0]; else nv = vals[0] + (vals[0] - prev)*0.5; |
|---|
| 23 |
first = false; |
|---|
| 24 |
prev = nv; controls ~= nv; |
|---|
| 25 |
vals.take(); |
|---|
| 26 |
} |
|---|
| 27 |
float[] controls_2; |
|---|
| 28 |
foreach_reverse (i, val; values) { |
|---|
| 29 |
if (!i) break; |
|---|
| 30 |
float nc2 = values[i] + (values[i] - controls[i-1])*0.5; |
|---|
| 31 |
controls_2 = nc2 ~ controls_2; |
|---|
| 32 |
} |
|---|
| 33 |
controls_2 = values[0] ~ controls_2; |
|---|
| 34 |
controls ~= vals[$-1]; |
|---|
| 35 |
// logln("Off ", values, ": controls ", controls, " - controls2 ", controls_2); |
|---|
| 36 |
return (float[] v, float[] c, float[] c_2, float x) { |
|---|
| 37 |
int i = cast(int) x; |
|---|
| 38 |
auto start = v[i], end = v[i+1]; |
|---|
| 39 |
return bezier2(start, c[i], c_2[i], end)(x-i); |
|---|
| 40 |
} /fix/ stuple(values, controls, controls_2); |
|---|
| 41 |
} |
|---|
| 42 |
|
|---|
| 43 |
/* |
|---|
| 44 |
void main() { |
|---|
| 45 |
screen(640, 480); |
|---|
| 46 |
float[][] points; |
|---|
| 47 |
points ~= [100, 100]; |
|---|
| 48 |
points ~= [200, 100]; |
|---|
| 49 |
points ~= [200, 200]; |
|---|
| 50 |
points ~= [100, 200]; |
|---|
| 51 |
points ~= [0, 200]; |
|---|
| 52 |
points ~= [200, 300]; |
|---|
| 53 |
points ~= [300, 200]; |
|---|
| 54 |
foreach (point; points) point[0]+=200; |
|---|
| 55 |
|
|---|
| 56 |
flip=false; |
|---|
| 57 |
|
|---|
| 58 |
auto cols = [Red, Green, Blue, Red~Green, Green~Blue, Red~Blue, White, Red]; |
|---|
| 59 |
foreach (i, point; points) circle(point[0], point[1], 3, cols[i]); |
|---|
| 60 |
foreach (i, point; points[1..$]) |
|---|
| 61 |
line(points[i][0], points[i][1], point[0], point[1], White); |
|---|
| 62 |
int i; |
|---|
| 63 |
float[] prev_c; |
|---|
| 64 |
float[] xs, ys; |
|---|
| 65 |
foreach (point; points) { xs ~= point[0]; ys ~= point[1]; } |
|---|
| 66 |
auto mbx = multibezier(xs), mby = multibezier(ys); |
|---|
| 67 |
for (float f=0; f<points.length - 1; f += 0.001) { |
|---|
| 68 |
pset(cast(int) mbx(f), cast(int) mby(f), cols[cast(int) f].blend(cols[cast(int) f + 1], f - cast(int) f)); |
|---|
| 69 |
} |
|---|
| 70 |
flip; |
|---|
| 71 |
while (true) events; |
|---|
| 72 |
} |
|---|
| 73 |
*/ |
|---|