切线为零的 1D Hermite 三次样条 - 如何使其看起来更平滑
1D Hermite Cubic Splines with tangents of zero - how to make it look smoother
我得到了 3 个值 y0
、y1
、y2
。它们应该均匀分布,比如 x0 = -0.5
、x1 = 0.5
、x2 = 1.5
。为了能够通过所有这些绘制样条曲线,所有点的导数被称为 dy/dx = 0
.
现在渲染两个 Catmull-Rom-Splines 的结果(这是通过 GLSL 片段着色器完成的,包括非线性变换)看起来非常严格。 IE。曲线弯曲的地方,虽然很平滑,但是弯曲的区域很小。缩小会使弯曲看起来太尖锐。
我想切换到 TCB-Splines(又名 Kochanek-Bartels Splines),因为它们提供了张力参数 - 因此我希望我可以使外观平滑。但我意识到所有应用于零切线的 TCB 参数都没有任何用处。
有什么想法可以使曲线看起来更平滑吗?
二维参数曲线的切向量 f(t)=(x(t), y(t)) 定义为 f'(t)=(dx(t)/dt, dy(t) /dt)。当您要求曲线在某些点处具有 dy/dx = 0 时,这仅意味着这些点处的切向量将水平移动(即 dy/dt = 0)。这并不一定意味着切向量本身是零向量。所以,你应该仍然可以使用 TCB spline 做任何你想做的事情。
显然没有人给出好的答案,但由于这是我的工作,我找到了一个解决方案:点均匀分布,其想法是使过渡更平滑。现在已经给出,所有给定点的切线都为零,因此很可能在接近这些点时我们得到最强的曲率 y''(x)。这意味着,我们想扩展这些 "areas around the points".
考虑到目前我们使用 Catmull-Rom-Splines,在点之间进行分段。这使得 y(x) => y(t) , t(x) = x-x0
.
这个 t(x)
需要围绕 0
- 和 1
- 区域拉伸。于是余弦函数跳进了我的脑海:
用 t(x) = 0.5 * (1.0 - cos( PI * ( x-x0 ) )
替换 t(x) = x-x0
对我来说完成了工作。
简短说明:
[0,PI]
运行s 范围内的余弦从 1
到 -1
. 平滑
- 我们想 运行 从
0
到 1
,尽管
- 所以翻转它:
1-cos()
-> 现在 运行s 从 0
到 2
- 减半:
0.5*xxx
-> 现在 运行 从 0
到 1
另一个问题是找到正确的切线。通常,使用 Matrix-Vector-Math 计算这样的样条,您只需导出 t-vector
即可获得切线,因此导出 [t³ t² t 1]
会得到 [3t² 2t 1 0]
。但是在这里,t
并不简单。使用 this 我找到了正确的导出向量:
| 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 |
我得到了 3 个值 y0
、y1
、y2
。它们应该均匀分布,比如 x0 = -0.5
、x1 = 0.5
、x2 = 1.5
。为了能够通过所有这些绘制样条曲线,所有点的导数被称为 dy/dx = 0
.
现在渲染两个 Catmull-Rom-Splines 的结果(这是通过 GLSL 片段着色器完成的,包括非线性变换)看起来非常严格。 IE。曲线弯曲的地方,虽然很平滑,但是弯曲的区域很小。缩小会使弯曲看起来太尖锐。
我想切换到 TCB-Splines(又名 Kochanek-Bartels Splines),因为它们提供了张力参数 - 因此我希望我可以使外观平滑。但我意识到所有应用于零切线的 TCB 参数都没有任何用处。
有什么想法可以使曲线看起来更平滑吗?
二维参数曲线的切向量 f(t)=(x(t), y(t)) 定义为 f'(t)=(dx(t)/dt, dy(t) /dt)。当您要求曲线在某些点处具有 dy/dx = 0 时,这仅意味着这些点处的切向量将水平移动(即 dy/dt = 0)。这并不一定意味着切向量本身是零向量。所以,你应该仍然可以使用 TCB spline 做任何你想做的事情。
显然没有人给出好的答案,但由于这是我的工作,我找到了一个解决方案:点均匀分布,其想法是使过渡更平滑。现在已经给出,所有给定点的切线都为零,因此很可能在接近这些点时我们得到最强的曲率 y''(x)。这意味着,我们想扩展这些 "areas around the points".
考虑到目前我们使用 Catmull-Rom-Splines,在点之间进行分段。这使得 y(x) => y(t) , t(x) = x-x0
.
这个 t(x)
需要围绕 0
- 和 1
- 区域拉伸。于是余弦函数跳进了我的脑海:
用 t(x) = 0.5 * (1.0 - cos( PI * ( x-x0 ) )
替换 t(x) = x-x0
对我来说完成了工作。
简短说明:
[0,PI]
运行s 范围内的余弦从1
到-1
. 平滑
- 我们想 运行 从
0
到1
,尽管 - 所以翻转它:
1-cos()
-> 现在 运行s 从0
到2
- 减半:
0.5*xxx
-> 现在 运行 从0
到1
另一个问题是找到正确的切线。通常,使用 Matrix-Vector-Math 计算这样的样条,您只需导出 t-vector
即可获得切线,因此导出 [t³ t² t 1]
会得到 [3t² 2t 1 0]
。但是在这里,t
并不简单。使用 this 我找到了正确的导出向量:
| 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 |