1D Hermite Cubic Splines with tangents of zero - how to make it look smoother

617 Views Asked by At

I am given 3 values y0, y1, y2. They are supposed to be evenly spaced, say x0 = -0.5, x1 = 0.5, x2 = 1.5. And to be able to draw a spline through all of them, the derivatives at all points are said to be dy/dx = 0.

Now the result of rendering two Catmull-Rom-Splines (which is done via GLSL fragment shader, including a nonlinear transformation) looks pretty rigit. I.e. where the curve bends, it does so smoothly, though, but the bending area is very small. Zooming out makes the bends look too sharp.

I wanted to switch to TCB-Splines (aka. Kochanek-Bartels Splines), as those provide a tension parameter - thus I hoped I could smooth the look. But I realized that all TCB-Parameters applied to a zero tangent won't do any good.

Any ideas how I could get a smoother looking curve?

2

There are 2 best solutions below

0
St0fF On BEST ANSWER

Obviously nobody had a good answer, but as it's my job, I found a solution: The Points are evenly spaced, and the idea is to make transitions smoother. Now it's given, that the tangents are zero at all given Points, so it is most likely that close to the points we get the strongest curvature y''(x). This means, we'd like to stretch these "areas around the points".

Considering that currently we use Catmull-Rom-Splines, sectioned between the points. That makes y(x) => y(t) , t(x) = x-x0.

This t(x) needs to be stretched around the 0- and the 1-areas. So the cosine function jumped into my mind:

Replacing t(x) = x-x0 with t(x) = 0.5 * (1.0 - cos( PI * ( x-x0 ) ) did the job for me.

Short explanation:

  • cosine in the range [0,PI] runs smoothly from 1 to -1.
  • we want to run from 0 to 1, though
  • so flip it: 1-cos() -> now it runs from 0 to 2
  • halve that: 0.5*xxx -> now it runs from 0 to 1

Another problem was to find the correct tangents. Normally, calculating such a spline using Matrix-Vector-Math, you simply derive your t-vector to get the tangents, so deriving [t³ t² t 1] yields [3t² 2t 1 0]. But here, t is not simple. Using this I found the right derived vector:

| 0.375*PI*sin(PI*t)(1-cos(PI*t))² |
| 0.500*PI*sin(PI*t)(1-cos(PI*t))  |
| 0.500*PI*sin(PI*t)               |
| 0                                |
1
fang On

The tangent vector for a 2d parametric curve f(t)=(x(t), y(t)) is defined as f'(t)=(dx(t)/dt, dy(t)/dt). When you require your curve to have dy/dx = 0 at some points, it simply means the tangent vector at those points will go horizontally (i.e., dy/dt = 0). It does not necessarily mean the tangent vector itself is a zero vector. So, you should still be able to use TCB spline to do whatever you want to do.