///|
/// Cubic and quadratic curve utilities used by path generators.
pub fn quadratic_point(
start : Vec2,
control : Vec2,
end : Vec2,
t : Double,
) -> Vec2 {
let u = 1.0 - t
start.scale(u * u).add(control.scale(2.0 * u * t)).add(end.scale(t * t))
}
///|
pub fn cubic_point(
start : Vec2,
c1 : Vec2,
c2 : Vec2,
end : Vec2,
t : Double,
) -> Vec2 {
let u = 1.0 - t
start
.scale(u * u * u)
.add(c1.scale(3.0 * u * u * t))
.add(c2.scale(3.0 * u * t * t))
.add(end.scale(t * t * t))
}
///|
pub fn quadratic_tangent(
start : Vec2,
control : Vec2,
end : Vec2,
t : Double,
) -> Vec2 {
control
.sub(start)
.scale(2.0 * (1.0 - t))
.add(end.sub(control).scale(2.0 * t))
.normalized()
}
///|
pub fn cubic_tangent(
start : Vec2,
c1 : Vec2,
c2 : Vec2,
end : Vec2,
t : Double,
) -> Vec2 {
let u = 1.0 - t
c1
.sub(start)
.scale(3.0 * u * u)
.add(c2.sub(c1).scale(6.0 * u * t))
.add(end.sub(c2).scale(3.0 * t * t))
.normalized()
}
///|
pub fn offset_polyline(points : Array[Vec2], distance : Double) -> Array[Vec2] {
let result = []
if points.length() == 0 {
result
} else {
for i in 0.. Array[Vec2] {
let result = []
if points.length() >= 2 && samples_per_segment > 0 {
for i in 0..<(points.length() - 1) {
let p0 = if i == 0 { points[i] } else { points[i - 1] }
let p1 = points[i]
let p2 = points[i + 1]
let p3 = if i + 2 >= points.length() {
points[i + 1]
} else {
points[i + 2]
}
for sample in 0.. Path {
let path = Path::new()
if points.length() > 0 {
let _ = path.move_to(points[0].x, points[0].y)
for point in points[1:] {
let _ = path.line_to(point.x, point.y)
}
if closed {
let _ = path.close()
}
}
path
}