在任意 X 坐标处确定 B 样条的值

Posted

技术标签:

【中文标题】在任意 X 坐标处确定 B 样条的值【英文标题】:Determining Value of B-Spline at an Arbitrary X Coordinate 【发布时间】:2019-04-03 07:02:27 【问题描述】:

我在数据点 xp 和 yp 的集合上创建了一个开放、钳位、三次、b 样条。

样条曲线由跨越 xp 域的向量 u 参数化。

我的目标是在 xp 域中的给定“x”坐标处确定 b 样条的“y”坐​​标。

正如生成参数曲线时的预期行为,当我在计算 tck 后将值“4”传递给 splev 时,将返回与参数 4 对应的 x 和 y 坐标的值。

我能够使用牛顿法来确定参数 u 在给定“x”坐标处的值;然而,这是间接的,并且需要比我的最终应用程序允许的更多计算时间。

谁能建议一种更直接的方法来确定给定“x”的 b 样条上的“y”坐​​标?

import numpy as np
import matplotlib.pyplot as plt
from scipy import interpolate

xp = [0., 0.71428571, 1.42857143, 2.14285714, 2.85714286, 3.57142857, 4.28571429, 5.]
yp = [0., -0.86217009, -2.4457478, -2.19354839, -2.32844575, -0.48680352, -0.41055718, -3.]

length = len(xp)
t = np.linspace(0., xp[-1], length - 2, endpoint=True)
t = np.append([0, 0, 0], t)
t = np.append(t, [xp[-1], xp[-1], xp[-1]])

tck = [t, [xp, yp], 3]
u = np.linspace(0, 5., 1000, endpoint=True)
out = interpolate.splev(u, tck)

x_value_in_xp_domain = 4.
y_value_out = interpolate.splev(x_value_in_xp_domain, tck)

plt.plot(xp, yp, linestyle='--', marker='o', color='purple')
plt.plot(out[0], out[1], color = 'teal')
plt.plot(x_value_in_xp_domain, y_value_out[1], marker='o', color = 'orangered')
plt.plot(y_value_out[0], y_value_out[1], marker='o', color = 'black')
plt.axvline(x=x_value_in_xp_domain, color = 'orangered')
plt.show()

下图显示了上述代码生成的引导多边形和 b 样条。 x=4 处的橙色点对应于我希望直接确定 b 样条的 y 值的点。黑点是当 4 的值作为参数传递时 b 样条的值。

提供一些有用的参考:

Fast b-spline algorithm with numpy/scipy

https://github.com/kawache/Python-B-spline-examples

https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/bspline-curve.html

http://web.mit.edu/hyperbook/Patrikalakis-Maekawa-Cho/node17.html

【问题讨论】:

一般来说,样条曲线对于给定的 X 可能有多个 Y 值,这会使直接计算变得复杂。有没有更好的方式来表示你的曲线? @MartinStone 非常正确。幸运的是,在这个应用程序中,样条对于给定的 X 值保证是单值的。关于应用程序的更多上下文,一组样条将用于表示解决方案,然后将其传递给优化器。端点在这个解空间中是固定的,因此一个开放的、钳位的、三次的、b 样条曲线似乎是表示任意函数同时规避龙格现象的好方法。不反对其他近似任意函数的方法的提议,但仍然对原始问题的解决方案感兴趣。 【参考方案1】:

PPoly 类的roots 方法可能是您问题的解决方案。这将比牛顿更快,并且它会为您提供所有解决方案,以防有多个解决方案。

sx = interpolate.BSpline(t, xp, 3)
sy = interpolate.BSpline(t, yp, 3)

x0 = 4
u0 = interpolate.PPoly.from_spline((sx.t, sx.c - x0, 3)).roots()
sy(u0)

plt.plot(xp, yp, linestyle='--', marker='o', color='purple')
plt.plot(out[0], out[1], color = 'teal')
plt.plot(sx(u0), sy(u0), 'o')
plt.show()

【讨论】:

以上是关于在任意 X 坐标处确定 B 样条的值的主要内容,如果未能解决你的问题,请参考以下文章

三次样条插值法

使用导数拉直样条曲线以确定每个点的旋转

非均匀有理B样条的目录

已知一个圆经过三点,怎样求圆心坐标啊?

(5)三次样条和B样条

确定一个点是不是位于任意形状内?