def bspline(self, length: float, segments: int = 10, degree: int = 3, method: str = 'uniform') -> BSpline: """ Approximate euler spiral as B-spline. Args: length: length of euler spiral segments: count of fit points for B-spline calculation degree: degree of BSpline method: calculation method for parameter vector t Returns: :class:`BSpline` """ fit_points = list(self.approximate(length, segments=segments)) spline = global_bspline_interpolation(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 render_as_fit_points(self, layout: 'BaseLayout', degree: int = 3, method: str = 'chord', dxfattribs: dict = None) -> None: """ Render a B-spline as 2D/3D :class:`~ezdxf.entities.Polyline`, where the definition points are fit points. - 2D spline vertices uses: :meth:`~ezdxf.layouts.BaseLayout.add_polyline2d` - 3D spline vertices uses: :meth:`~ezdxf.layouts.BaseLayout.add_polyline3d` Args: layout: :class:`~ezdxf.layouts.BaseLayout` object degree: degree of B-spline (order = `degree` + 1) method: "uniform", "distance"/"chord", "centripetal"/"sqrt_chord" or "arc" calculation method for parameter t dxfattribs: DXF attributes for :class:`~ezdxf.entities.Polyline` """ spline = global_bspline_interpolation(self.points, degree=degree, method=method) 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 test_check_values(): test_points = [(0., 0.), (1., 2.), (3., 1.), (5., 3.)] spline = global_bspline_interpolation(test_points, degree=3, method='distance') result = list(spline.approximate(49)) assert len(result) == 50 for p1, p2 in zip(result, expected): assert isclose(p1[0], p2[0], abs_tol=1e-6) assert isclose(p1[1], p2[1], abs_tol=1e-6)
def test_bspline_interpolation(fit_points): spline = global_bspline_interpolation(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 = global_bspline_interpolation(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 spline_interpolation(vertices: Iterable['Vertex'], degree: int = 3, method: str = 'chord', subdivide: int = 4) -> List[Vector]: """ 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", "chord"/"distance", "centripetal"/"sqrt_chord" or "arc" calculation method for parameter t subdivide: count of sub vertices + 1, e.g. 4 creates 3 sub-vertices Returns: list of vertices """ vertices = list(vertices) spline = global_bspline_interpolation(vertices, degree=degree, method=method) return list(spline.approximate(segments=(len(vertices) - 1) * subdivide))
def bspline( self, length: float, segments: int = 10, degree: int = 3, method: str = "uniform", ) -> BSpline: """Approximate euler spiral as B-spline. Args: length: length of euler spiral segments: count of fit points for B-spline calculation degree: degree of BSpline method: calculation method for parameter vector t Returns: :class:`BSpline` """ length = float(length) fit_points = list(self.approximate(length, segments=segments)) derivatives = [ # Scaling derivatives by chord length (< real length) is suggested # by Piegl & Tiller. self.tangent(t).normalize(length) for t in _params(length, segments) ] spline = global_bspline_interpolation( fit_points, degree, method=method, tangents=derivatives ) return BSpline( spline.control_points, spline.order, # Scale knot values to length: [v * length for v in spline.knots()], )
def test_bspline_interpolation_first_derivatives(fit_points): tangents = estimate_tangents(fit_points) spline = global_bspline_interpolation(fit_points, degree=3, tangents=tangents) assert len(spline.control_points) == 2 * len(fit_points)
def add_spline(degree=2, color=3): spline = global_bspline_interpolation(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})