1# Copyright (c) 2021, Manfred Moitzi 2# License: MIT License 3 4import pytest 5import math 6from ezdxf.math.bspline import bspline_basis_vector, open_uniform_knot_vector 7from ezdxf.math._bspline import Basis 8from ezdxf.acc import USE_C_EXT 9 10basis_functions = [Basis] 11 12if USE_C_EXT: 13 pass 14 15 16@pytest.fixture(params=basis_functions) 17def basis_cls(request): 18 return request.param 19 20 21def make_knots(count, degree): 22 return tuple(open_uniform_knot_vector(count, order=degree + 1)) 23 24 25def make_basic_func(count, degree, cls): 26 knots = make_knots(count, degree) 27 return cls(knots=knots, order=degree + 1, count=count) 28 29 30def test_property_exists(basis_cls): 31 degree = 3 32 count = 10 33 knots = make_knots(count, degree) 34 basis_func = basis_cls(knots=knots, order=degree + 1, count=count) 35 assert basis_func.degree == degree 36 assert basis_func.order == degree + 1 37 assert basis_func.max_t == max(knots) 38 assert basis_func.knots == knots 39 assert basis_func.weights == tuple() 40 assert basis_func.is_rational is False 41 42 43def test_bspline_basis_vector(basis_cls): 44 degree = 3 45 count = 10 46 knots = make_knots(count, degree) 47 max_t = max(knots) 48 basis_func = basis_cls(knots=knots, order=degree + 1, count=count) 49 for u in (0, 2, 2.5, 3.5, 4, max_t): 50 basis = bspline_basis_vector(u, count=count, degree=degree, knots=knots) 51 basis2 = basis_func.basis_vector(u) 52 assert len(basis) == len(basis2) 53 for v1, v2 in zip(basis, basis2): 54 assert v1 == pytest.approx(v2) 55 56 57def test_find_span(basis_cls): 58 degree = 3 59 basis_func = make_basic_func(10, degree, basis_cls) 60 for u in [0, 2, 2.5, 3.5, 4]: 61 result = basis_func.find_span(u) 62 span = math.floor(u) + degree 63 assert result == span 64 assert basis_func.find_span(basis_func.max_t) == 9 65 66 67if __name__ == '__main__': 68 pytest.main([__file__]) 69