v / vlib / math / interpolation_bezier.v
68 lines · 63 sloc · 2.53 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1module math
2
3// BezierPoint represents point coordinates as floating point numbers.
4// This type is used as the output of the cubic_bezier family of functions.
5pub struct BezierPoint {
6pub mut:
7 x f64
8 y f64
9}
10
11// cubic_bezier returns a linear interpolation between the control points,
12// specified by their X and Y coordinates in a single array of points `p`, and given the parameter t,
13// varying between 0.0 and 1.0 .
14// When `t` == 0.0, the output is P[0] .
15// When `t` == 1.0, the output is P[3] .
16// The points x[1],y[1] and x[2],y[2], serve as attractors.
17@[direct_array_access; inline]
18pub fn cubic_bezier(t f64, p []BezierPoint) BezierPoint {
19 if p.len != 4 {
20 panic('invalid p.len')
21 }
22 return cubic_bezier_coords(t, p[0].x, p[1].x, p[2].x, p[3].x, p[0].y, p[1].y, p[2].y, p[3].y)
23}
24
25// cubic_bezier_a returns a linear interpolation between the control points,
26// specified by their X and Y coordinates in 2 arrays, and given the parameter t,
27// varying between 0.0 and 1.0 .
28// When `t` == 0.0, the output is x[0],y[0] .
29// When `t` == 1.0, the output is x[3],y[3] .
30// The points x[1],y[1] and x[2],y[2], serve as attractors.
31@[direct_array_access; inline]
32pub fn cubic_bezier_a(t f64, x []f64, y []f64) BezierPoint {
33 if x.len != 4 {
34 panic('invalid x.len')
35 }
36 if y.len != 4 {
37 panic('invalid y.len')
38 }
39 return cubic_bezier_coords(t, x[0], x[1], x[2], x[3], y[0], y[1], y[2], y[3])
40}
41
42// cubic_bezier_fa returns a linear interpolation between the control points,
43// specified by their X and Y coordinates in 2 fixed arrays, and given the parameter t,
44// varying between 0.0 and 1.0 .
45// When `t` == 0.0, the output is x[0],y[0] .
46// When `t` == 1.0, the output is x[3],y[3] .
47// The points x[1],y[1] and x[2],y[2], serve as attractors.
48@[direct_array_access; inline]
49pub fn cubic_bezier_fa(t f64, x [4]f64, y [4]f64) BezierPoint {
50 return cubic_bezier_coords(t, x[0], x[1], x[2], x[3], y[0], y[1], y[2], y[3])
51}
52
53// cubic_bezier_coords returns a linear interpolation between the control points,
54// specified by their X and Y coordinates, and given the parameter t,
55// varying between 0.0 and 1.0 .
56// When `t` == 0.0, the output is x0,y0 .
57// When `t` == 1.0, the output is x3,y3 .
58// The points x1,y1 and x2,y2, serve as attractors.
59@[inline]
60pub fn cubic_bezier_coords(t f64, x0 f64, x1 f64, x2 f64, x3 f64, y0 f64, y1 f64, y2 f64, y3 f64) BezierPoint {
61 p0 := pow(1 - t, 3)
62 p1 := 3 * t * pow(1 - t, 2)
63 p2 := 3 * (1 - t) * pow(t, 2)
64 p3 := pow(t, 3)
65 xt := p0 * x0 + p1 * x1 + p2 * x2 + p3 * x3
66 yt := p0 * y0 + p1 * y1 + p2 * y2 + p3 * y3
67 return BezierPoint{xt, yt}
68}
69