add cad_app_bspline(), a try to match SPLINE rendering from fit points of CAD applications
@@ -36,16 +36,34 @@ USE_BANDED_MATRIX_SOLVER_CPYTHON_LIMIT = 15
USE_BANDED_MATRIX_SOLVER_PYPY_LIMIT = 60
-def cad_app_spline(fit_points: Sequence['Vertex'], degree: int, method='chord') -> 'BSpline':
- """ Returns the control frame configuration like common CAD applications. """
+def cad_app_bspline(fit_points: Iterable['Vertex'], degree: int = 3, method='chord',
+ tangents: Iterable['Vertex'] = None) -> 'BSpline':
+ """ Returns the control frame and knot configuration for SPLINE entities
+ defined by fit points as close as possible to common CAD applications
+ like BricsCAD.
+
+ Args:
+ fit_points: the constraint points the spline is passing through
+ degree: degree of spline, default = 3
+ method: knot parametrization method, default = 'chord'
+ tangents: start- and end tangent, default is autodetect
+
+ """
points = Vector.list(fit_points)
- # 5-points is the closest estimation method I found
+ if tangents is None:
+ # 5-points is the closest estimation method I found so far
tangents = estimate_tangents(points, method='5-p')
m1, m2 = estimate_end_tangent_magnitude(points, method='chord')
+ start_tangent = tangents[0].normalize(m1)
+ end_tangent = tangents[-1].normalize(m2)
+ else:
+ tangents = Vector.list(tangents)
+ start_tangent = Vector(tangents[0])
+ end_tangent = Vector(tangents[-1])
control_points, knots = _global_bspline_interpolation_end_tangents(
points,
- start_tangent=tangents[0].normalize(m1),
- end_tangent=tangents[-1].normalize(m2),
+ start_tangent=start_tangent,
+ end_tangent=end_tangent,
degree=degree,
t_vector=list(create_t_vector(points, method=method)),
knot_generation_method='natural' if degree % 2 else 'average',
