简体   繁体   English

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

[英]Determining Value of B-Spline at an Arbitrary X Coordinate

I have created an open, clamped, cubic, b-spline on the set of data points xp and yp.我在数据点 xp 和 yp 的集合上创建了一个开放的、夹紧的、三次的、b 样条曲线。

The spline is parametarized by the vector u which spans the domain of xp.样条由跨越 xp 域的向量 u 参数化。

My goal is to determine the "y" coordinate of the b-spline at a given "x" coordinate in the domain of xp.我的目标是确定 xp 域中给定“x”坐标处的 b 样条的“y”坐标。

As is expected behavior when generating parametric curves, when I pass the value "4" into splev after calculating tck, the value for both the x and y coordinate corresponding to the parameter 4 is returned.正如生成参数曲线时的预期行为,当我在计算 tck 后将值“4”传递给 splev 时,返回对应于参数 4 的 x 和 y 坐标值。

I am able to use Newton's method to determine the value of the parameter u at a given "x" coordinate;我能够使用牛顿法来确定给定“x”坐标处的参数 u 的值; This is however indirect and requires more computation time than my final application can permit.然而,这是间接的,需要比我的最终应用程序允许的更多的计算时间。

Can anyone suggest a more direct way to determine the "y" coordinate on the b-spline for a given "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()

The below image shows the guide polygon and the b-spline generated by the above code.下图显示了由上述代码生成的引导多边形和 b 样条曲线。 The orange point at x=4 corresponds the point I wish to directly determine the y value of the b-spline at. x=4 处的橙色点对应于我希望直接确定 b 样条的 y 值的点。 The black point is the value of the b-spline when the value of 4 is passed as a parameter.黑点是将4的值作为参数传递时b样条的值。

从上面的脚本中绘制

providing a few useful references:提供一些有用的参考:

Fast b-spline algorithm with numpy/scipy 使用 numpy/scipy 的快速 b 样条算法

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

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

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

The roots method of the PPoly class may be the solution for your problem. PPoly类的roots方法可能是您的问题的解决方案。 This will be faster than Newton, and it will give you all the solutions in case there is more than one. 这将比牛顿更快,如果有多个解决方案,它将为您提供所有解决方案。

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()

Let me suggest a frame change.让我建议更改框架。 As you know, there are two ways to create a spline in the plane: as a function and as a parametric curve .如您所知,有两种方法可以在平面中创建样条曲线:作为function和作为参数曲线 You have chosen the latter but nowhere in the question do I see any compelling reason to do so;您选择了后者,但在问题中的任何地方我都看不到这样做的任何令人信服的理由; whereas taking the former would make a solution to your question almost trivial.而采用前者会使您的问题的解决方案几乎微不足道。

We start with some input data.我们从一些输入数据开始。

xdata  = [0.,  0.60626102,  1.36904762,  2.14285714,  2.85714286,  3.63095238,  4.39373898,  5.]
ydata  = [0., -0.82509685, -2.00782014, -2.25806452, -1.99902249, -0.77468231, -1.19975743, -3.]

Note that unlike your xp and yp , which are called control points in my circles, I collect a few points xdata , ydata that we will interpolate .请注意,与您在我的圈子中称为控制点xpyp不同,我收集了一些我们将插值的点xdataydata I did that by sampling your function at the Greville abscissae to have something similar to your input.我通过在Greville 横坐标上对您的 function 进行采样来获得与您的输入类似的内容来做到这一点。 However, the exact type of input depends on your application;但是,确切的输入类型取决于您的应用程序; you have mentioned function approximation in one of the comments, so I guess this might be a way.您在其中一条评论中提到了 function 近似值,所以我想这可能是一种方法。

Now, we can use UnivariateSpline to create the spline function interpolating the data:现在,我们可以使用UnivariateSpline创建插值数据的样条function

spline = interpolate.InterpolatedUnivariateSpline(xdata, ydata)

There are some alternatives;有一些选择; I recommend having a look at the interpolation tutorial and the references therein.我建议查看插值教程及其中的参考资料。

And this is more or less it.这或多或少就是这样。 You can now sample the values at a lot of points to plot spline :您现在可以在很多点对 plot spline的值进行采样:

xfunc  = np.linspace(0, 5., 1000, endpoint=True)
yfunc  = spline(xfunc)
plt.plot(xfunc, yfunc,  color = 'green')

However, the reason we go through all this is to answer your question: how to find the y -coordinate corresponding to a given x -coordinate?然而,我们 go 之所以通过这一切是为了回答您的问题:如何找到给定x坐标对应的y坐标? This is quite simple:这很简单:

x_value_in_xp_domain = 4.
y_value_out = spline(x_value_in_xp_domain)

Here is a picture showing my input data (blue; again, they are not identical to your inputs), the interpolating spline function (green), x_value_in_xp_domain (orange curve) and y_value_out (orange point).这是一张显示我的输入数据(蓝色;同样,它们与您的输入不相同)、插值样条function (绿色)、 x_value_in_xp_domain (橙色曲线)和y_value_out (橙色点)的图片。

样条函数的绘图。

Finally, here is the complete source code.最后,这是完整的源代码。

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

xdata  = [0.,  0.60626102,  1.36904762,  2.14285714,  2.85714286,  3.63095238,  4.39373898,  5.]
ydata  = [0., -0.82509685, -2.00782014, -2.25806452, -1.99902249, -0.77468231, -1.19975743, -3.]

spline = interpolate.InterpolatedUnivariateSpline(xdata, ydata)
xfunc  = np.linspace(0, 5., 1000, endpoint=True)
yfunc  = spline(xfunc)

x_value_in_xp_domain = 4.
y_value_out = spline(x_value_in_xp_domain)

plt.plot(xfunc, yfunc,  color = 'green')
plt.plot(xdata, ydata, 'o', color = 'blue')
plt.plot(x_value_in_xp_domain, y_value_out, marker='o', color = 'orangered')
plt.axvline(x=x_value_in_xp_domain, color = 'orangered')
plt.show()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM