``` import sympy class Point: def __init__(self, x, y) -> None: self.x = x self.y = y def __repr__(self): return f'{self.x, self.y}' class Line: def __init__(self, p1, p2) -> None: self.p1 = p1 self.p2 = p2 def __call__(self, t): x = (self.p2.x - self.p1.x) * t + self.p1.x y = (self.p2.y - self.p1.y) * t + self.p1.y return Point(x, y) def segments(points): return [Line(x, y) for x,y in zip(points[:-1], points[1:])] class Bezier: def __init__(self, points): self.t = sympy.Symbol('t') while len(points) > 1: points = [x(self.t) for x in segments(points)] self.eqn = points[0] def __call__(self, t): return Point(self.eqn.x.subs(self.t, t), self.eqn.y.subs(self.t, t)) class BezierPath: def __init__(self, points): self.curves = [] self.pts = [] # every set of 4 points forms a bezier curve through the outer 2 points # so each intermediate point introduces 3 curve "points" for i in range(0, len(points)-2, 3): self.curves.append(Bezier(points[i:i+4])) self.pts.append(points[i]) self.pts.append(points[-1]) def __call__(self, t): if len(self.curves) == 1: return self.curves[0](t) for i in range(len(self.pts)): if self.pts[i].x >= t: break if self.pts[i].x == t: return self.pts[i] frac = (t - self.pts[i-1].x) / (self.pts[i].x - self.pts[i-1].x) return self.curves[i-1](frac) ```