def test_derivative(self): # testing the parametrization x(t) = [.5*x^3 / ((1-x)^3+.5*x^3), 0] cp = [[0, 0, 1], [0, 0, 0], [0, 0, 0], [.5, 0, .5]] crv = Curve(BSplineBasis(4), cp, rational=True) def expect_derivative(x): return 6 * (1 - x)**2 * x**2 / (x**3 - 6 * x**2 + 6 * x - 2)**2 def expect_derivative_2(x): return -12 * x * (x**5 - 3 * x**4 + 2 * x**3 + 4 * x**2 - 6 * x + 2) / (x**3 - 6 * x**2 + 6 * x - 2)**3 # insert a few more knots to spice things up crv.insert_knot([.2, .71]) self.assertAlmostEqual( crv.derivative(0.32, 1)[0], expect_derivative(0.32)) self.assertAlmostEqual(crv.derivative(0.32, 1)[1], 0) self.assertAlmostEqual( crv.derivative(0.71, 1)[0], expect_derivative(0.71)) self.assertAlmostEqual( crv.derivative(0.22, 2)[0], expect_derivative_2(0.22)) self.assertAlmostEqual(crv.derivative(0.22, 2)[1], 0) self.assertAlmostEqual( crv.derivative(0.86, 2)[0], expect_derivative_2(0.86))
def test_derivative(self): # testing the parametrization x(t) = [.5*x^3 / ((1-x)^3+.5*x^3), 0] cp = [[0,0,1], [0,0,0], [0,0,0], [.5,0,.5]] crv = Curve(BSplineBasis(4), cp, rational=True) def expect_derivative(x): return 6*(1-x)**2*x**2/(x**3 - 6*x**2 + 6*x - 2)**2 def expect_derivative_2(x): return -12*x*(x**5 - 3*x**4 + 2*x**3 + 4*x**2 - 6*x + 2)/(x**3 - 6*x**2 + 6*x - 2)**3 # insert a few more knots to spice things up crv.insert_knot([.2, .71]) self.assertAlmostEqual(crv.tangent(0.32)[0], expect_derivative(0.32)) self.assertAlmostEqual(crv.tangent(0.32)[1], 0) self.assertAlmostEqual(crv.tangent(0.71)[0], expect_derivative(0.71)) self.assertAlmostEqual(crv.derivative(0.22, 2)[0], expect_derivative_2(0.22)) self.assertAlmostEqual(crv.derivative(0.22, 2)[1], 0) self.assertAlmostEqual(crv.derivative(0.86, 2)[0], expect_derivative_2(0.86))
def test_append(self): crv = Curve(BSplineBasis(3), [[0,0], [1,0], [0,1]]) crv2 = Curve(BSplineBasis(4), [[0,1,0], [0,1,1], [0,2,1], [0,2,2]]) crv2.insert_knot(0.5) crv3 = crv.clone() crv3.append(crv2) expected_knot = [0,0,0,0,1,1,1,1.5,2,2,2,2] self.assertEqual(crv3.order(direction=0), 4) self.assertEqual(crv3.rational, False) self.assertEqual(np.linalg.norm(crv3.knots(0, True)-expected_knot), 0.0) t = np.linspace(0,1,11) pt = np.zeros((11,3)) pt[:,:-1] = crv(t) pt2 = crv3(t) self.assertAlmostEqual(np.linalg.norm(pt-pt2), 0.0) pt = crv2(t) pt2 = crv3(t+1.0) self.assertAlmostEqual(np.linalg.norm(pt-pt2), 0.0)
def test_append(self): crv = Curve(BSplineBasis(3), [[0, 0], [1, 0], [0, 1]]) crv2 = Curve(BSplineBasis(4), [[0, 1, 0], [0, 1, 1], [0, 2, 1], [0, 2, 2]]) crv2.insert_knot(0.5) crv3 = crv.clone() crv3.append(crv2) expected_knot = [0, 0, 0, 0, 1, 1, 1, 1.5, 2, 2, 2, 2] self.assertEqual(crv3.order(direction=0), 4) self.assertEqual(crv3.rational, False) self.assertAlmostEqual( np.linalg.norm(crv3.knots(0, True) - expected_knot), 0.0) t = np.linspace(0, 1, 11) pt = np.zeros((11, 3)) pt[:, :-1] = crv(t) pt2 = crv3(t) self.assertAlmostEqual(np.linalg.norm(pt - pt2), 0.0) pt = crv2(t) pt2 = crv3(t + 1.0) self.assertAlmostEqual(np.linalg.norm(pt - pt2), 0.0)
def test_insert_knot(self): # non-uniform knot vector of a squiggly quadratic n=5 curve in 3D controlpoints = [[0, 0, 0], [1, 1, 1], [2, -1, 0], [3, 0, -1], [0, 0, -5]] crv = Curve(BSplineBasis(3, [0, 0, 0, .3, .4, 1, 1, 1]), controlpoints) evaluation_point1 = crv(0.37) crv.insert_knot(.2) crv.insert_knot(.3) crv.insert_knot(.9) evaluation_point2 = crv(0.37) # ensure that curve has not chcanged, by comparing evaluation of it self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0]) self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1]) self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2]) self.assertEqual(len(crv.knots(0, with_multiplicities=True)), 11) # test knot insertion on single knot span crv = Curve(BSplineBasis(5), [[0, 0, 0], [1, 1, 1], [2, -1, 0], [3, 0, -1], [0, 0, -5]]) evaluation_point1 = crv(0.27) crv.insert_knot(.2) evaluation_point2 = crv(0.27) self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0]) self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1]) self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2]) # test knot insertion on first of two-knot span crv = Curve( BSplineBasis(3, [0, 0, 0, .5, 1, 1, 1]), [[0, 0, 0], [2, -1, 0], [3, 0, -1], [0, 0, -5] ]) evaluation_point1 = crv(0.27) crv.insert_knot(.2) evaluation_point2 = crv(0.27) self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0]) self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1]) self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2]) # test knot insertion on last of two-knot span crv = Curve( BSplineBasis(3, [0, 0, 0, .5, 1, 1, 1]), [[0, 0, 0], [2, -1, 0], [3, 0, -1], [0, 0, -5] ]) evaluation_point1 = crv(0.27) crv.insert_knot(.9) evaluation_point2 = crv(0.27) self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0]) self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1]) self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2]) # test knot insertion down to C0 basis crv = Curve(BSplineBasis(3), [[0, 0, 0], [2, -1, 0], [0, 0, -5]]) evaluation_point1 = crv(0.27) crv.insert_knot(.4) crv.insert_knot(.4) evaluation_point2 = crv(0.27) self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0]) self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1]) self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2]) # test rational curves, here a perfect circle represented as n=9, p=2-curve s = 1.0 / sqrt(2) controlpoints = [[1, 0, 1], [s, s, s], [0, 1, 1], [-s, s, s], [-1, 0, 1], [-s, -s, s], [0, -1, 1], [s, -s, s], [1, 0, 1]] crv = Curve(BSplineBasis(3, [-1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5]), controlpoints, True) evaluation_point1 = crv(0.37) crv.insert_knot(.2) crv.insert_knot(.3) crv.insert_knot(.9) evaluation_point2 = crv(0.37) self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0]) self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1]) self.assertEqual(len(crv.knots(0, with_multiplicities=True)), 15) # test errors and exceptions with self.assertRaises(TypeError): crv.insert_knot(1, 2, 3) # too many arguments with self.assertRaises(ValueError): crv.insert_knot(1, 2) # direction=2 is illegal for curves with self.assertRaises(TypeError): crv.insert_knot() # too few arguments with self.assertRaises(ValueError): crv.insert_knot(-0.2) # Outside-domain error with self.assertRaises(ValueError): crv.insert_knot(4.4) # Outside-domain error
def test_insert_knot(self): # non-uniform knot vector of a squiggly quadratic n=5 curve in 3D controlpoints = [[0, 0, 0], [1, 1, 1], [2, -1, 0], [3, 0, -1], [0, 0, -5]] crv = Curve(BSplineBasis(3, [0, 0, 0, .3, .4, 1, 1, 1]), controlpoints) evaluation_point1 = crv(0.37) crv.insert_knot(.2) crv.insert_knot(.3) crv.insert_knot(.9) evaluation_point2 = crv(0.37) # ensure that curve has not chcanged, by comparing evaluation of it self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0]) self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1]) self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2]) self.assertEqual(len(crv.knots(0, with_multiplicities=True)), 11) # test knot insertion on single knot span crv = Curve(BSplineBasis(5), [[0, 0, 0], [1, 1, 1], [2, -1, 0], [3, 0, -1], [0, 0, -5]]) evaluation_point1 = crv(0.27) crv.insert_knot(.2) evaluation_point2 = crv(0.27) self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0]) self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1]) self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2]) # test knot insertion on first of two-knot span crv = Curve(BSplineBasis(3, [0, 0, 0, .5, 1, 1, 1]), [[0, 0, 0], [2, -1, 0], [3, 0, -1], [0, 0, -5]]) evaluation_point1 = crv(0.27) crv.insert_knot(.2) evaluation_point2 = crv(0.27) self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0]) self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1]) self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2]) # test knot insertion on last of two-knot span crv = Curve(BSplineBasis(3, [0, 0, 0, .5, 1, 1, 1]), [[0, 0, 0], [2, -1, 0], [3, 0, -1], [0, 0, -5]]) evaluation_point1 = crv(0.27) crv.insert_knot(.9) evaluation_point2 = crv(0.27) self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0]) self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1]) self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2]) # test knot insertion down to C0 basis crv = Curve(BSplineBasis(3), [[0, 0, 0], [2, -1, 0], [0, 0, -5]]) evaluation_point1 = crv(0.27) crv.insert_knot(.4) crv.insert_knot(.4) evaluation_point2 = crv(0.27) self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0]) self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1]) self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2]) # test rational curves, here a perfect circle represented as n=9, p=2-curve s = 1.0 / sqrt(2) controlpoints = [[1, 0, 1], [s, s, s], [0, 1, 1], [-s, s, s], [-1, 0, 1], [-s, -s, s], [0, -1, 1], [s, -s, s], [1, 0, 1]] crv = Curve(BSplineBasis(3, [-1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5]), controlpoints, True) evaluation_point1 = crv(0.37) crv.insert_knot(.2) crv.insert_knot(.3) crv.insert_knot(.9) evaluation_point2 = crv(0.37) self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0]) self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1]) self.assertEqual(len(crv.knots(0, with_multiplicities=True)), 15) # test errors and exceptions with self.assertRaises(TypeError): crv.insert_knot(1, 2, 3) # too many arguments with self.assertRaises(ValueError): crv.insert_knot(1, 2) # direction=2 is illegal for curves with self.assertRaises(TypeError): crv.insert_knot() # too few arguments with self.assertRaises(ValueError): crv.insert_knot(-0.2) # Outside-domain error with self.assertRaises(ValueError): crv.insert_knot(4.4) # Outside-domain error