def test_cubic_bezier_approximation(): bspline = BSpline.from_fit_points([(0, 0), (10, 20), (30, 10), (40, 10), (50, 0), (60, 20), (70, 50), (80, 70)]) bezier_segments = list(bspline.cubic_bezier_approximation(level=3)) assert len(bezier_segments) == 28 bezier_segments = list(bspline.cubic_bezier_approximation(segments=40)) assert len(bezier_segments) == 40
def test_add_spline_segment(): t = CurvedTrace.from_spline(BSpline.from_fit_points([(1, 0), (3, 1), (5, -1), (6, 0)]), start_width=2, end_width=1, segments=10) assert len(t) == 11
def test_bezier_decomposition(): bspline = BSpline.from_fit_points([ (0, 0), (10, 20), (30, 10), (40, 10), (50, 0), (60, 20), (70, 50), (80, 70), ]) bezier_segments = list(bspline.bezier_decomposition()) assert len(bezier_segments) == 5 # results visually checked to be correct assert close_vectors( bezier_segments[0], [ (0.0, 0.0, 0.0), (2.02070813064438, 39.58989657555839, 0.0), (14.645958536022286, 10.410103424441612, 0.0), (30.0, 10.0, 0.0), ], ) assert close_vectors( bezier_segments[-1], [ (60.0, 20.0, 0.0), (66.33216513897267, 43.20202388489432, 0.0), (69.54617236126121, 50.37880459351478, 0.0), (80.0, 70.0, 0.0), ], )
def construction_tool(self) -> BSpline: """ Returns the construction tool :class:`ezdxf.math.BSpline`. """ if self.control_point_count(): weights = self.weights if len(self.weights) else None knots = self.knots if len(self.knots) else None return BSpline(control_points=self.control_points, order=self.dxf.degree + 1, knots=knots, weights=weights) elif self.fit_point_count(): return BSpline.from_fit_points(self.fit_points, degree=self.dxf.degree) else: raise ValueError( 'Construction tool requires control- or fit points.')
def test_add_spline(): from ezdxf.math import BSpline spline = BSpline.from_fit_points([(2, 0), (4, 1), (6, -1), (8, 0)]) path = Path() tools.add_spline(path, spline) assert path.start == (2, 0) assert path.end == (8, 0) # set start point to end of spline path = Path(start=(8, 0)) # add reversed spline, by default the start of # an empty path is set to the spline start tools.add_spline(path, spline, reset=False) assert path.start == (8, 0) assert path.end == (2, 0) path = Path() # add a line segment from (0, 0) to start of spline tools.add_spline(path, spline, reset=False) assert path.start == (0, 0) assert path.end == (8, 0)
def to_line_edges(spline_edge: SplineEdge): weights = spline_edge.weights if len(spline_edge.control_points): bspline = BSpline( control_points=spline_edge.control_points, order=spline_edge.degree + 1, knots=spline_edge.knot_values, weights=weights if len(weights) else None, ) elif len(spline_edge.fit_points): bspline = BSpline.from_fit_points( spline_edge.fit_points, spline_edge.degree ) else: raise const.DXFStructureError( "SplineEdge() without control points or fit points." ) segment_count = (max(len(bspline.control_points), 3) - 1) * factor vertices = list(bspline.approximate(segment_count)) for v1, v2 in zip(vertices[:-1], vertices[1:]): edge = LineEdge() edge.start = v1.vec2 edge.end = v2.vec2 yield edge
def profile(text, func, *args): t0 = time.perf_counter() func(*args) t1 = time.perf_counter() print(f'{text} {t1 - t0:.3f}s') def export_path(path): doc = ezdxf.new() msp = doc.modelspace() bbox = BoundingBox(path) msp.add_polyline3d(path, dxfattribs={'layer': 'Path', 'color': 2}) spline = msp.add_spline(dxfattribs={'layer': 'B-spline', 'color': 1}) curve = global_bspline_interpolation(path) spline.apply_construction_tool(curve) doc.set_modelspace_vport(center=bbox.center, height=bbox.size[1]) doc.saveas(DIR / 'path1.dxf') path = list(random_3d_path(100, max_step_size=10, max_heading=math.pi * 0.8)) export_path(path) profile('B-spline interpolation 300x: ', profile_bspline_interpolation, 300, path) spline = BSpline.from_fit_points(path, degree=3) profile('calculate 25x 1000 B-spline vertices: ', profile_vertex_calculation, 25, spline, 1000)
def test_flattening(): fitpoints = [(0, 0), (1, 3), (2, 0), (3, 3)] bspline = BSpline.from_fit_points(fitpoints) assert list(bspline.flattening(0.01, segments=4)) == EXPECTED_FLATTENING
def test_flattening(): fitpoints = [(0, 0), (1, 3), (2, 0), (3, 3)] bspline = BSpline.from_fit_points(fitpoints) assert all( a.isclose(b) for a, b in zip(bspline.flattening(0.01, segments=4), EXPECTED_FLATTENING))