///|
/// 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
}