Created and optimized Bézier splitting functions such as partial_bezier_points()
in manim.utils.bezier
#3766
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Overview: What does this pull request change?
Related PR: #3281
The original algorithm in
partial_bezier_points()
made a lot of calls tobezier()
, making multiple redundant intermediate calculations that could've been reused for the other Béziers.Instead, in the n-th degree case I calculate all of the necessary points in a single pass, improving from O(n³) to O(n²) time:
Even more, the process can be encoded as a matrix multiplication, which is what I did for the simple cases (up to cubic curves), giving around 10x speedup:
This rewritten function can now replace
partial_quadratic_bezier_points()
.I applied the exact same process for creating
split_bezier()
andsubdivide_bezier()
, which are very similar and use essentially the same algorithm, and can also be encoded as matrix multiplications. Moreover,subdivide_bezier()
creates memos for each generated matrix, to reuse them in future calls to the function. Currentlysplit_bezier()
isn't being used anywhere (originallysubdivide_quadratic_bezier()
usedsplit_quadratic_bezier()
), but I still leave it there because its docstring is useful and it might be used in the future for something else.I also created
bezier_remap()
, based onquadratic_bezier_remap()
, which usessubdivide_bezier()
. I noticed thatVMobject.insert_n_curves_to_point_list()
uses an algorithm that could've been a call tobezier_remap()
, so I used that instead.All of this is thoroughly documented in docstrings, being the most important one the
split_bezier()
docstring, where the algorithm is explained in depth. The other docstrings are based on this explanation.I also added many tests for many different cases.
Reviewer Checklist