def s(self, *xy): """ Add smooth cubic Bezier curves to the curve. Parameters ---------- xy : numbers Coordinate pairs. Each set of 2 pairs are interpreted as the control point at the end of the curve and the endpoint of the curve. The control point at the beginning of the curve is assumed to be the reflection of the control point at the end of the last curve relative to the starting point of the curve. If the previous curve is not a cubic Bezier, the control point is coincident with the starting point. All coordinates are relative to the current end point. Returns ------- out : `Curve` This curve. """ self.last_q = None if self.last_c is None: self.last_c = self.points[-1] x0, y0 = self.points[-1] i = 0 while i < len(xy): ctrl = numpy.empty((4, 2)) ctrl[0, 0] = x0 ctrl[0, 1] = y0 ctrl[1] = 2 * ctrl[0] - self.last_c for j in range(2, 4): if isinstance(xy[i], complex): ctrl[j, 0] = x0 + xy[i].real ctrl[j, 1] = y0 + xy[i].imag i += 1 else: ctrl[j, 0] = x0 + xy[i] ctrl[j, 1] = y0 + xy[i + 1] i += 2 f = _func_bezier(ctrl) uu = [0, 0.2, 0.5, 0.8, 1] fu = [f(u) for u in uu] iu = 1 while iu < len(fu): test_u = 0.5 * (uu[iu - 1] + uu[iu]) test_pt = f(test_u) test_err = 0.5 * (fu[iu - 1] + fu[iu]) - test_pt if test_err[0]**2 + test_err[1]**2 > self.tol: uu.insert(iu, test_u) fu.insert(iu, test_pt) else: iu += 1 self.points.extend(xy for xy in fu[1:]) self.last_c = ctrl[2] return self
def T(self, *xy): """ Add smooth quadratic Bezier curves to the curve. Parameters ---------- xy : numbers Coordinates of the endpoints of the curves. The control point is assumed to be the reflection of the control point of the last curve relative to the starting point of the curve. If the previous curve is not a quadratic Bezier, the control point is coincident with the starting point. Returns ------- out : `Curve` This curve. """ self.last_c = None if self.last_q is None: self.last_q = self.points[-1] i = 0 while i < len(xy): ctrl = numpy.empty((3, 2)) ctrl[0] = self.points[-1] ctrl[1] = 2 * ctrl[0] - self.last_q if isinstance(xy[i], complex): ctrl[2, 0] = xy[i].real ctrl[2, 1] = xy[i].imag i += 1 else: ctrl[2, 0] = xy[i] ctrl[2, 1] = xy[i + 1] i += 2 f = _func_bezier(ctrl) uu = [0, 0.2, 0.5, 0.8, 1] fu = [f(u) for u in uu] iu = 1 while iu < len(fu): test_u = 0.5 * (uu[iu - 1] + uu[iu]) test_pt = f(test_u) test_err = 0.5 * (fu[iu - 1] + fu[iu]) - test_pt if test_err[0]**2 + test_err[1]**2 > self.tol: uu.insert(iu, test_u) fu.insert(iu, test_pt) else: iu += 1 self.points.extend(xy for xy in fu[1:]) self.last_q = ctrl[1] return self
def c(self, *xy): """ Add cubic Bezier curves to the curve. Parameters ---------- xy : numbers Coordinate pairs. Each set of 3 pairs are interpreted as the control point at the beginning of the curve, the control point at the end of the curve and the endpoint of the curve. All coordinates are relative to the current end point. Returns ------- out : `Curve` This curve. """ self.last_q = None x0, y0 = self.points[-1] i = 0 while i < len(xy): ctrl = numpy.empty((4, 2)) ctrl[0, 0] = x0 ctrl[0, 1] = y0 for j in range(1, 4): if isinstance(xy[i], complex): ctrl[j, 0] = x0 + xy[i].real ctrl[j, 1] = y0 + xy[i].imag i += 1 else: ctrl[j, 0] = x0 + xy[i] ctrl[j, 1] = y0 + xy[i + 1] i += 2 f = _func_bezier(ctrl) uu = [0, 0.2, 0.5, 0.8, 1] fu = [f(u) for u in uu] iu = 1 while iu < len(fu): test_u = 0.5 * (uu[iu - 1] + uu[iu]) test_pt = f(test_u) test_err = 0.5 * (fu[iu - 1] + fu[iu]) - test_pt if test_err[0]**2 + test_err[1]**2 > self.tol: uu.insert(iu, test_u) fu.insert(iu, test_pt) else: iu += 1 self.points.extend(xy for xy in fu[1:]) self.last_c = ctrl[2] return self
def b(self, *xy): """ Add a general degree Bezier curve. Parameters ---------- xy : numbers Coordinate pairs. The last coordinate is the endpoint of curve and all other are control points. All coordinates are relative to the current end point. Returns ------- out : `Curve` This curve. """ self.last_c = self.last_q = None x0, y0 = self.points[-1] i = 0 ctrl = [self.points[-1]] while i < len(xy): if isinstance(xy[i], complex): ctrl.append((x0 + xy[i].real, y0 + xy[i].imag)) i += 1 else: ctrl.append((x0 + xy[i], y0 + xy[i + 1])) i += 2 ctrl = numpy.array(ctrl) f = _func_bezier(ctrl) uu = numpy.linspace(-1, 1, ctrl.shape[0] + 1) uu = list(0.5 * (1 + numpy.sign(uu) * numpy.abs(uu)**0.8)) fu = [f(u) for u in uu] iu = 1 while iu < len(fu): test_u = 0.5 * (uu[iu - 1] + uu[iu]) test_pt = f(test_u) test_err = 0.5 * (fu[iu - 1] + fu[iu]) - test_pt if test_err[0]**2 + test_err[1]**2 > self.tol: uu.insert(iu, test_u) fu.insert(iu, test_pt) else: iu += 1 self.points.extend(xy for xy in fu[1:]) return self