def test_004_degree_too_large(self): degree = 3 # integer >= 0, but cubic and higher not yet implemented calc = bp.bspline_basis_manual(self.kv, self.ki, degree) self.assertIsInstance(calc, AssertionError) self.assertTrue( calc.args[0] == "Error: polynomial degree p exceeds maximum of 2" )
def test_002_knot_index_too_low(self): bad_knot_index = -1 calc = bp.bspline_basis_manual(self.kv, bad_knot_index) self.assertIsInstance(calc, AssertionError) self.assertTrue( calc.args[0] == "Error: knot index knot_i must be non-negative." )
def test_003_degree_too_small(self): degree = -1 # integer >= 0, so -1 is out of range for test calc = bp.bspline_basis_manual(self.kv, self.ki, degree) self.assertIsInstance(calc, AssertionError) self.assertTrue( calc.args[0] == "Error: polynomial degree p must be non-negative." )
def test_N03_not_yet_implemented(self): degree = 3 # integer >= 0 calc = bp.bspline_basis_manual(self.kv, self.ki, degree) self.assertIsInstance(calc, AssertionError) self.assertTrue( calc.args[0] == "Error: polynomial degree p exceeds maximum of 2" )
def test_001_knot_vector_minimum_length(self): kv_too_short = (0.0,) calc = bp.bspline_basis_manual(kv_too_short) self.assertIsInstance(calc, AssertionError) self.assertTrue( calc.args[0] == "Error: knot vector length must be two or larger." )
def test_N20(self): knot_index = 2 # integer >= 0 calc = bp.bspline_basis_manual(self.kv, knot_index, self.degree, self.nti) known_t = (0.0, 0.5, 1.0, 1.5, 2.0, 2.25, 2.5, 2.75, 3.0) # nti = 2 known_f_of_t = tuple(map(float, [0, 0, 0, 0, 0, 0, 0, 0, 1])) self.assertTrue(self.same(known_t, calc[0])) self.assertTrue(self.same(known_f_of_t, calc[1]))
def test_008_decreasing_knots(self): # knot vector must be non-decreasing sequence, so test error # checking for a decreasing knot vector sequence bad_knot_vector = (0.0, 2.0, 1.0) with pytest.raises(ValueError) as error: _ = bp.bspline_basis_manual(bad_knot_vector) self.assertTrue(str(error.value) == "Error: knot vector is decreasing.")
def test_N00_and_verbose(self): calc = bp.bspline_basis_manual( self.kv, self.ki, self.degree, self.nti, verbose=True ) known_t = (0.0, 0.5, 1.0, 1.5, 2.0, 2.25, 2.5, 2.75, 3.0) # nti = 2 known_f_of_t = tuple(map(float, [1, 1, 1, 1, 0, 0, 0, 0, 0])) self.assertTrue(self.same(known_t, calc[0])) self.assertTrue(self.same(known_f_of_t, calc[1]))
def test_006_nti_out_of_range_and_verbose(self): bad_number_of_intervals = 0 calc = bp.bspline_basis_manual( self.kv, self.ki, self.degree, bad_number_of_intervals, verbose=True ) self.assertIsInstance(calc, AssertionError) self.assertTrue( calc.args[0] == "Error: number of time intervals nti must be 1 or greater." )
def test_005_number_of_time_intervals(self): bad_number_of_intervals = 0 calc = bp.bspline_basis_manual( self.kv, self.ki, self.degree, bad_number_of_intervals ) self.assertIsInstance(calc, AssertionError) self.assertTrue( calc.args[0] == "Error: number of time intervals nti must be 1 or greater." )
def test_007_knot_index_too_high(self): # Python's zero-based index makes the integer length of the knot_vector # be the first index to be out of range, thus test this bad_knot_index = len(self.kv) calc = bp.bspline_basis_manual(self.kv, bad_knot_index) self.assertIsInstance(calc, AssertionError) self.assertTrue( calc.args[0] == "Error: knot index knot_i exceeds knot vector length minus 1." )
def test_N01(self): knot_vector = tuple(map(float, [0, 1, 2])) degree = 1 # integer >= 0 calc = bp.bspline_basis_manual( knot_vector, self.ki, degree, self.nti, verbose=True ) known_t = (0.0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0) # nti = 2 known_f_of_t = (0.0, 0.25, 0.5, 0.75, 1.0, 0.75, 0.5, 0.25, 0.0) self.assertTrue(self.same(known_t, calc[0])) self.assertTrue(self.same(known_f_of_t, calc[1]))
def test_007b_insufficient_knots_local_support(self): knot_vector = (0.0, 0.0, 1.0, 1.0) knot_i = 3 # the last knot degree = 2 # quadratic calc = bp.bspline_basis_manual( knot_vector_t=knot_vector, knot_i=knot_i, p=degree ) self.assertIsInstance(calc, AssertionError) self.assertTrue( calc.args[0] == "Error: insufficient remaining knots for local support." )
def test_N12(self): knot_vector = tuple(map(float, [0, 1, 2, 3, 4])) knot_index = 1 # integer >= 0 degree = 2 # integer >= 0 calc = bp.bspline_basis_manual( knot_vector, knot_index, degree, self.nti, verbose=True ) # nti = 2 known_t = ( 0.0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, ) known_f_of_t = ( 0.0, 0.0, 0.0, 0.0, 0.0, 0.03125, 0.125, 0.28125, 0.5, 0.6875, 0.75, 0.6875, 0.5, 0.28125, 0.125, 0.03125, 0.0, ) self.assertTrue(self.same(known_t, calc[0])) self.assertTrue(self.same(known_f_of_t, calc[1]))
# number of time intervals per knot # nti = 2 ** 1 # for minimal interpolation # nti = 2 ** 2 # for quarter-unit interpolation nti = 2**5 # for LaTeX figures # knot_vector = [0, 1, 2] knot_vector = [0, 1, 2, 3, 4, 5, 6] print(f"Computing B-spline bases with degree p={DEGREE}") print(f"with knot vector {knot_vector} and ") print(f"with number of time intervals (per knot span) nti={nti}") num_knots = len(knot_vector) for k in np.arange(num_knots - 1 - DEGREE): t, y = bp.bspline_basis_manual(knot_vector, k, DEGREE, nti, VERBOSE) if VERBOSE: print(f"t={t}") print(f"y = {y}") # fig = plt.figure(figsize=plt.figaspect(1.0), dpi=DPI) # fig = plt.figure(dpi=DPI) fig = plt.figure(figsize=plt.figaspect(1.0 / (len(knot_vector) - 1)), dpi=DPI) ax = fig.gca() # ax.grid() ax.grid(True, which="major", linestyle="-") ax.grid(True, which="minor", linestyle=":") # ax.scatter(t, y) ax.plot(t, y, linestyle="None", marker=".")