v/vlib/math/interpolation_bezier.v

70 lines
2.5 KiB
V

module math
// BezierPoint represents point coordinates as floating point numbers.
// This type is used as the output of the cubic_bezier family of functions.
pub struct BezierPoint {
pub mut:
x f64
y f64
}
// cubic_bezier returns a linear interpolation between the control points,
// specified by their X and Y coordinates in a single array of points `p`, and given the parameter t,
// varying between 0.0 and 1.0 .
// When `t` == 0.0, the output is P[0] .
// When `t` == 1.0, the output is P[3] .
// The points x[1],y[1] and x[2],y[2], serve as attractors.
@[direct_array_access; inline]
pub fn cubic_bezier(t f64, p []BezierPoint) BezierPoint {
if p.len != 4 {
panic('invalid p.len')
}
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)
}
// cubic_bezier_a returns a linear interpolation between the control points,
// specified by their X and Y coordinates in 2 arrays, and given the parameter t,
// varying between 0.0 and 1.0 .
// When `t` == 0.0, the output is x[0],y[0] .
// When `t` == 1.0, the output is x[3],y[3] .
// The points x[1],y[1] and x[2],y[2], serve as attractors.
@[direct_array_access; inline]
pub fn cubic_bezier_a(t f64, x []f64, y []f64) BezierPoint {
if x.len != 4 {
panic('invalid x.len')
}
if y.len != 4 {
panic('invalid y.len')
}
return cubic_bezier_coords(t, x[0], x[1], x[2], x[3], y[0], y[1], y[2], y[3])
}
// cubic_bezier_fa returns a linear interpolation between the control points,
// specified by their X and Y coordinates in 2 fixed arrays, and given the parameter t,
// varying between 0.0 and 1.0 .
// When `t` == 0.0, the output is x[0],y[0] .
// When `t` == 1.0, the output is x[3],y[3] .
// The points x[1],y[1] and x[2],y[2], serve as attractors.
@[direct_array_access; inline]
pub fn cubic_bezier_fa(t f64, x [4]f64, y [4]f64) BezierPoint {
return cubic_bezier_coords(t, x[0], x[1], x[2], x[3], y[0], y[1], y[2], y[3])
}
// cubic_bezier_coords returns a linear interpolation between the control points,
// specified by their X and Y coordinates, and given the parameter t,
// varying between 0.0 and 1.0 .
// When `t` == 0.0, the output is x0,y0 .
// When `t` == 1.0, the output is x3,y3 .
// The points x1,y1 and x2,y2, serve as attractors.
@[inline]
pub fn cubic_bezier_coords(t f64, x0 f64, x1 f64, x2 f64, x3 f64, y0 f64, y1 f64, y2 f64, y3 f64) BezierPoint {
p0 := pow(1 - t, 3)
p1 := 3 * t * pow(1 - t, 2)
p2 := 3 * (1 - t) * pow(t, 2)
p3 := pow(t, 3)
xt := p0 * x0 + p1 * x1 + p2 * x2 + p3 * x3
yt := p0 * y0 + p1 * y1 + p2 * y2 + p3 * y3
return BezierPoint{xt, yt}
}