def test_kink(self): # Should refuse to differentiate splines with kinks spl2 = insert(0.5, self.spl, m=2) splder(spl2, 2) # Should work assert_raises(ValueError, splder, spl2, 3) spl2 = insert(0.5, self.spl, m=3) splder(spl2, 1) # Should work assert_raises(ValueError, splder, spl2, 2) spl2 = insert(0.5, self.spl, m=4) assert_raises(ValueError, splder, spl2, 1)
def to_bezier(self, match_curves_to_points=False, smooth=True): """Convert the contour into a sequence of cubic Bezier curves. NOTE: There may be fewer Bezier curves than points in the contour, if the contour is sufficiently smooth. To ensure that each point interval in the contour corresponds to a returned curve, set 'match_curves_to_points' to True. Output: A list of cubic Bezier curves. Each Bezier curve is an array of shape (4,2); thus the curve includes the starting point, the two control points, and the endpoint. """ if smooth: size = self.size().max() s = 0.00001 * size else: s = 0 tck, u = self.to_spline(smoothing=s) if match_curves_to_points: #to_insert = numpy.setdiff1d(u, numpy_compat.unique(tck[0]))#-------note wwk------the numpy_compat.py are removed to_insert = numpy.setdiff1d(u, numpy.unique(tck[0])) for i in to_insert: tck = fitpack.insert(i, tck, per=True) return utility_tools.b_spline_to_bezier_series(tck, per=True)
def b_spline_to_bezier_series(tck, per=False): """Convert a parametric b-spline into a sequence of Bezier curves of the same degree. Inputs: tck : (t,c,k) tuple of b-spline knots, coefficients, and degree returned by splprep. per : if tck was created as a periodic spline, per *must* be true, else per *must* be false. Output: A list of Bezier curves of degree k that is equivalent to the input spline. Each Bezier curve is an array of shape (k+1,d) where d is the dimension of the space; thus the curve includes the starting point, the k-1 internal control points, and the endpoint, where each point is of d dimensions. from http://mail.scipy.org/pipermail/scipy-dev/2007-February/006651.html (actually, I got it from http://old.nabble.com/bezier-curve-through-set-of-2D-points-td27158642.html """ from scipy.interpolate.fitpack import insert from numpy import asarray, unique, split, sum, transpose t, c, k = tck t = asarray(t) try: c[0][0] except: # I can't figure out a simple way to convert nonparametric splines to # parametric splines. Oh well. raise TypeError("Only parametric b-splines are supported.") new_tck = tck if per: # ignore the leading and trailing k knots that exist to enforce periodicity knots_to_consider = unique(t[k:-k]) else: # the first and last k+1 knots are identical in the non-periodic case, so # no need to consider them when increasing the knot multiplicities below knots_to_consider = unique(t[k + 1:-k - 1]) # For each unique knot, bring it's multiplicity up to the next multiple of k+1 # This removes all continuity constraints between each of the original knots, # creating a set of independent Bezier curves. desired_multiplicity = k + 1 for x in knots_to_consider: current_multiplicity = sum(t == x) remainder = current_multiplicity % desired_multiplicity if remainder != 0: # add enough knots to bring the current multiplicity up to the desired multiplicity number_to_insert = desired_multiplicity - remainder new_tck = insert(x, new_tck, number_to_insert, per) tt, cc, kk = new_tck # strip off the last k+1 knots, as they are redundant after knot insertion bezier_points = transpose(cc)[:-desired_multiplicity] if per: # again, ignore the leading and trailing k knots bezier_points = bezier_points[k:-k] # group the points into the desired bezier curves return split(bezier_points, len(bezier_points) / desired_multiplicity, axis=0)
def b_spline_to_bezier_series(tck, per=False): """Convert a parametric b-spline into a sequence of Bezier curves of the same degree. By Zachary Pincus, from http://mail.scipy.org/pipermail/scipy-dev/2007-February/006651.html Inputs: tck : (t,c,k) tuple of b-spline knots, coefficients, and degree returned by splprep. per : if tck was created as a periodic spline, per *must* be true, else per *must* be false. Output: A list of Bezier curves of degree k that is equivalent to the input spline. Each Bezier curve is an array of shape (k+1,d) where d is the dimension of the space; thus the curve includes the starting point, the k-1 internal control points, and the endpoint, where each point is of d dimensions. """ t, c, k = tck t = np.asarray(t) try: c[0][0] except: # I can't figure out a simple way to convert nonparametric splines to # parametric splines. Oh well. raise TypeError("Only parametric b-splines are supported.") new_tck = tck if per: # ignore the leading and trailing k knots that exist to enforce periodicity knots_to_consider = np.unique(t[k:-k]) else: # the first and last k+1 knots are identical in the non-periodic case, so # no need to consider them when increasing the knot multiplicities below knots_to_consider = np.unique(t[k + 1:-k - 1]) # For each np.unique knot, bring it's multiplicity up to the next multiple of k+1 # This removes all continuity constraints between each of the original knots, # creating a set of independent Bezier curves. desired_multiplicity = k + 1 for x in knots_to_consider: current_multiplicity = np.sum(t == x) remainder = current_multiplicity % desired_multiplicity if remainder != 0: # add enough knots to bring the current multiplicity up to the desired multiplicity number_to_insert = desired_multiplicity - remainder new_tck = fitpack.insert(x, new_tck, number_to_insert, per) tt, cc, kk = new_tck # strip off the last k+1 knots, as they are redundant after knot insertion # correction: except for short curves -LK bezier_points = np.transpose(cc) if len(bezier_points)>desired_multiplicity: bezier_points = bezier_points[:-desired_multiplicity] if per: # again, ignore the leading and trailing k knots bezier_points = bezier_points[k:-k] # group the points into the desired bezier curves return np.split(bezier_points, len(bezier_points) / desired_multiplicity, axis=0)