def render_as_fit_points(self, layout, degree=3, method='distance', power=.5, dxfattribs=None): """ Render a B-spline as 2d/3d polyline, where the definition points are fit points. - 2d points in -> add_polyline2d() - 3d points in -> add_polyline3d() To get vertices at fit points, use method='uniform' and use Spline.subdivide(count), where count is the sub-segment count, count=4, means 4 line segments between two definition points. Args: layout: ezdxf layout degree: degree of B-spline method: 'uniform', 'distance' or 'centripetal', calculation method for parameter t power: power for 'centripetal', default is distance ^ .5 dxfattribs: DXF attributes for POLYLINE """ spline = bspline_control_frame(self.points, degree=degree, method=method, power=power) vertices = list(spline.approximate(self.segments)) if any(vertex.z != 0. for vertex in vertices): layout.add_polyline3d(vertices, dxfattribs=dxfattribs) else: layout.add_polyline2d(vertices, dxfattribs=dxfattribs)
def spline_interpolation(vertices, degree=3, method='uniform', power=.5, subdivide=4): """ B-spline interpolation, vertices are fit points for the spline definition. Only method 'uniform', yields vertices at fit points. Args: vertices: fit points degree: degree of B-spline method: 'uniform', 'distance' or 'centripetal', calculation method for parameter t power: power for 'centripetal', default is distance ^ .5 subdivide: count of sub vertices + 1, e.g. 4 creates 3 sub-vertices Returns: list of vertices """ spline = bspline_control_frame(vertices, degree=degree, method=method, power=power) return list(spline.approximate(segments=(len(vertices) - 1) * subdivide))
def bspline(self, length, segments=10, degree=3, method='uniform'): fit_points = list(self.approximate(length, segments=segments)) spline = bspline_control_frame(fit_points, degree, method=method) knots = [v * length for v in spline.knot_values()] # scale knot values to length spline.basis.knots = knots return spline
def test_check_values(): test_points = [(0., 0.), (1., 2.), (3., 1.), (5., 3.)] spline = bspline_control_frame(test_points, degree=3, method='distance') result = list(spline.approximate(49)) assert len(result) == 50 for p1, p2 in zip(result, expected): assert equals_almost(p1[0], p2[0], 4) assert equals_almost(p1[1], p2[1], 4)
def test_control_frame(fit_points): spline = bspline_control_frame(fit_points, degree=3) assert len(spline.control_points) == len(fit_points) assert spline.t_array[0] == 0. assert spline.t_array[-1] == 1. assert len(spline.t_array) == len(fit_points) t_points = [spline.point(t) for t in spline.t_array] for p1, p2 in zip(t_points, fit_points): assert p1 == p2
def add_spline(degree=2, color=3): spline = bspline_control_frame(fit_points, degree=degree, method='distance') msp.add_polyline2d(spline.control_points, dxfattribs={ 'color': color, 'linetype': 'DASHED' }) msp.add_open_spline(spline.control_points, degree=spline.degree, dxfattribs={'color': color})
def add_spline_control_frame(self, fit_points, degree=3, method='distance', power=.5): bspline = bspline_control_frame(fit_points=fit_points, degree=degree, method=method, power=power) return self.add_spline( fit_points=fit_points, control_points=bspline.control_points, knot_values=bspline.knot_values(), )