Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catmull-Rom splines #4846

Merged
merged 21 commits into from
Dec 31, 2022
Merged

Catmull-Rom splines #4846

merged 21 commits into from
Dec 31, 2022

Conversation

portnov
Copy link
Collaborator

@portnov portnov commented Dec 28, 2022

Screenshot_20221231_011436

Catmull-Rom splines have the following advantages:

  • They are widely used in some areas like game design
  • They are quite fast to compute — about as fast as our "cubic spline" (which is otherwise known as "natural spline", if I understood correctly)
  • They go exactly through specified points (i.e. they are interpolating)
  • They can be easily converted to Bezier segments or Nurbs curves.
  • In some implementations (see below), they allow to control the "degree of smoothness" with additional "tension" parameter

But these splines also have some disadvantages:

  • They have only C1 continuity, i.e. first derivative is continuous, but second is not.
  • As consequence, their curvature can change very fast — they can be "very curvy" at one points and "almost straight" in others. But this property can be useful in some applications, when you want the spline to go almost by straight lines, just rounding the corners a bit.

This node supports two variants of Catmull-Rom spline:

  • Non-uniform spline. See https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline . In this implementation, each spline segment (between two successive points) is assigned with different span of T parameter, which is calculated based on distance between points (several metrics are supported). This has the effect of the curve being more "curvy" in places where control points are far from one another, and more flat where control points are near. This usually gives the feeling of curve being more "natural".
  • Uniform spline. In this implementation, each spline segment is assigned with equal span of T parameter. As effect, it is possible that the curve will be unexpectedly more "curvy" when successive control points are near one another. But this implementation has an option to control the degree of curve "smoothness" by additional "tension" parameter. It is also possible to specify tension value for each curve segment.

Uniform (yellow) vs non-uniform (green) spline:

Screenshot_20221230_220318

Non-uniform splines with Euclidean metric (yellow) and with centripetal metric (green):

Screenshot_20221230_220428

Non-uniform (Euclidean) Catmull-Rom spline (yellow) vs Cubic spline (blue):

Screenshot_20221230_220618

Uniform splines with different tension values: from 0.2 (almost black lines) to 2.0 (white line):

Screenshot_20221230_204317

Screenshot_20221230_203447
Screenshot_20221228_210209

Preflight checklist

Put an x letter in each brackets when you're done this item:

  • Code changes complete.
  • Code documentation complete.
  • Documentation for users complete (or not required, if user never sees these changes).
  • Manual testing done.
  • Unit-tests implemented.
  • Ready for merge.

@mifth
Copy link
Collaborator

mifth commented Dec 29, 2022

Just a question. Did you take math from wiki? https://en.m.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline

Your implementation looks different a bit visually.

@portnov
Copy link
Collaborator Author

portnov commented Dec 29, 2022

Yes, mathematics I took from wiki (evaluate_array method). I just regrouped some operations to minimize the number of calculations — for example, (t2 - t)/(t2 - t1)*B1 + (t - t1)/(t2 - t1)*B2 => ((t2 - t)*B1 - (t1 - t)*B2) / (t2 - t), to minimize the number of divisions; also differences like t2 - t1 are precalculated, as they are used several times.

Mathematics for get_bezier_control_points (used to convert catmull-rom splines to nurbs) I derived myself using maxima :)

@portnov portnov merged commit 2ea51de into master Dec 31, 2022
@portnov portnov deleted the catmull_rom branch December 31, 2022 11:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants