三次 hermite 样条插值 python
Cubic hermit spline interpolation python
我想计算一个三次多项式,它由函数值和指定点的导数定义。
https://en.wikipedia.org/wiki/Cubic_Hermite_spline
我知道scipy的插值方法。具体
有没有python例程取函数值f(x)和导数f'(x)对应到值 x 并计算适合给定数据的样条表示。
举个例子:
我在 space 中有两个对象位置由坐标 x,y,z 定义,我知道速度 x',y',z' 在这些位置的对象。我现在可以插入对象随时间 t 在两点之间所走的路径吗?考虑所有给定的参数。
您可以使用 BPoly.from_derivatives
。结果是伯恩斯坦基的多项式。
扩展 , here some sample code that exemplifies the usage of BPoly.from_derivatives
以在具有规定导数的 n 维度中的点之间进行插值。
import numpy as np
from scipy import interpolate
def sampleCubicSplinesWithDerivative(points, tangents, resolution):
'''
Compute and sample the cubic splines for a set of input points with
optional information about the tangent (direction AND magnitude). The
splines are parametrized along the traverse line (piecewise linear), with
the resolution being the step size of the parametrization parameter.
The resulting samples have NOT an equidistant spacing.
Arguments: points: a list of n-dimensional points
tangents: a list of tangents
resolution: parametrization step size
Returns: samples
Notes: Lists points and tangents must have equal length. In case a tangent
is not specified for a point, just pass None. For example:
points = [[0,0], [1,1], [2,0]]
tangents = [[1,1], None, [1,-1]]
'''
resolution = float(resolution)
points = np.asarray(points)
nPoints, dim = points.shape
# Parametrization parameter s.
dp = np.diff(points, axis=0) # difference between points
dp = np.linalg.norm(dp, axis=1) # distance between points
d = np.cumsum(dp) # cumsum along the segments
d = np.hstack([[0],d]) # add distance from first point
l = d[-1] # length of point sequence
nSamples = int(l/resolution) # number of samples
s,r = np.linspace(0,l,nSamples,retstep=True) # sample parameter and step
# Bring points and (optional) tangent information into correct format.
assert(len(points) == len(tangents))
data = np.empty([nPoints, dim], dtype=object)
for i,p in enumerate(points):
t = tangents[i]
# Either tangent is None or has the same
# number of dimensions as the point p.
assert(t is None or len(t)==dim)
fuse = list(zip(p,t) if t is not None else zip(p,))
data[i,:] = fuse
# Compute splines per dimension separately.
samples = np.zeros([nSamples, dim])
for i in range(dim):
poly = interpolate.BPoly.from_derivatives(d, data[:,i])
samples[:,i] = poly(s)
return samples
为了演示这个函数的用法,我们指定点和切线。该示例进一步演示了如果更改切线的 "magnitude" 的效果。
# Input.
points = []
tangents = []
resolution = 0.2
points.append([0.,0.]); tangents.append([1,1])
points.append([3.,4.]); tangents.append([1,0])
points.append([5.,2.]); tangents.append([0,-1])
points.append([3.,0.]); tangents.append([-1,-1])
points = np.asarray(points)
tangents = np.asarray(tangents)
# Interpolate with different tangent lengths, but equal direction.
scale = 1.
tangents1 = np.dot(tangents, scale*np.eye(2))
samples1 = sampleCubicSplinesWithDerivative(points, tangents1, resolution)
scale = 2.
tangents2 = np.dot(tangents, scale*np.eye(2))
samples2 = sampleCubicSplinesWithDerivative(points, tangents2, resolution)
scale = 0.1
tangents3 = np.dot(tangents, scale*np.eye(2))
samples3 = sampleCubicSplinesWithDerivative(points, tangents3, resolution)
# Plot.
import matplotlib.pyplot as plt
plt.scatter(samples1[:,0], samples1[:,1], marker='o', label='samples1')
plt.scatter(samples2[:,0], samples2[:,1], marker='o', label='samples2')
plt.scatter(samples3[:,0], samples3[:,1], marker='o', label='samples3')
plt.scatter(points[:,0], points[:,1], s=100, c='k', label='input')
plt.axis('equal')
plt.title('Interpolation')
plt.legend()
plt.show()
结果如下图:
三点注意事项:
- 以下也可以应用于二维以上
- 样本之间的间距不固定。实现等距采样的一种简单方法是在返回的
samples
之间进行线性插值,例如在 this post. 中已经讨论过。
- 切线的指定是可选的,但是
BPoly.from_derivatives
不能确保此位置样条曲线之间的平滑过渡。例如,如果将上述示例中的 tangents[1]
设置为 None
、sampleCubicSplinesWithDerivative(points, tangents, resolution)
,结果将如下所示:
我想计算一个三次多项式,它由函数值和指定点的导数定义。
https://en.wikipedia.org/wiki/Cubic_Hermite_spline
我知道scipy的插值方法。具体
有没有python例程取函数值f(x)和导数f'(x)对应到值 x 并计算适合给定数据的样条表示。
举个例子:
我在 space 中有两个对象位置由坐标 x,y,z 定义,我知道速度 x',y',z' 在这些位置的对象。我现在可以插入对象随时间 t 在两点之间所走的路径吗?考虑所有给定的参数。
您可以使用 BPoly.from_derivatives
。结果是伯恩斯坦基的多项式。
扩展 BPoly.from_derivatives
以在具有规定导数的 n 维度中的点之间进行插值。
import numpy as np
from scipy import interpolate
def sampleCubicSplinesWithDerivative(points, tangents, resolution):
'''
Compute and sample the cubic splines for a set of input points with
optional information about the tangent (direction AND magnitude). The
splines are parametrized along the traverse line (piecewise linear), with
the resolution being the step size of the parametrization parameter.
The resulting samples have NOT an equidistant spacing.
Arguments: points: a list of n-dimensional points
tangents: a list of tangents
resolution: parametrization step size
Returns: samples
Notes: Lists points and tangents must have equal length. In case a tangent
is not specified for a point, just pass None. For example:
points = [[0,0], [1,1], [2,0]]
tangents = [[1,1], None, [1,-1]]
'''
resolution = float(resolution)
points = np.asarray(points)
nPoints, dim = points.shape
# Parametrization parameter s.
dp = np.diff(points, axis=0) # difference between points
dp = np.linalg.norm(dp, axis=1) # distance between points
d = np.cumsum(dp) # cumsum along the segments
d = np.hstack([[0],d]) # add distance from first point
l = d[-1] # length of point sequence
nSamples = int(l/resolution) # number of samples
s,r = np.linspace(0,l,nSamples,retstep=True) # sample parameter and step
# Bring points and (optional) tangent information into correct format.
assert(len(points) == len(tangents))
data = np.empty([nPoints, dim], dtype=object)
for i,p in enumerate(points):
t = tangents[i]
# Either tangent is None or has the same
# number of dimensions as the point p.
assert(t is None or len(t)==dim)
fuse = list(zip(p,t) if t is not None else zip(p,))
data[i,:] = fuse
# Compute splines per dimension separately.
samples = np.zeros([nSamples, dim])
for i in range(dim):
poly = interpolate.BPoly.from_derivatives(d, data[:,i])
samples[:,i] = poly(s)
return samples
为了演示这个函数的用法,我们指定点和切线。该示例进一步演示了如果更改切线的 "magnitude" 的效果。
# Input.
points = []
tangents = []
resolution = 0.2
points.append([0.,0.]); tangents.append([1,1])
points.append([3.,4.]); tangents.append([1,0])
points.append([5.,2.]); tangents.append([0,-1])
points.append([3.,0.]); tangents.append([-1,-1])
points = np.asarray(points)
tangents = np.asarray(tangents)
# Interpolate with different tangent lengths, but equal direction.
scale = 1.
tangents1 = np.dot(tangents, scale*np.eye(2))
samples1 = sampleCubicSplinesWithDerivative(points, tangents1, resolution)
scale = 2.
tangents2 = np.dot(tangents, scale*np.eye(2))
samples2 = sampleCubicSplinesWithDerivative(points, tangents2, resolution)
scale = 0.1
tangents3 = np.dot(tangents, scale*np.eye(2))
samples3 = sampleCubicSplinesWithDerivative(points, tangents3, resolution)
# Plot.
import matplotlib.pyplot as plt
plt.scatter(samples1[:,0], samples1[:,1], marker='o', label='samples1')
plt.scatter(samples2[:,0], samples2[:,1], marker='o', label='samples2')
plt.scatter(samples3[:,0], samples3[:,1], marker='o', label='samples3')
plt.scatter(points[:,0], points[:,1], s=100, c='k', label='input')
plt.axis('equal')
plt.title('Interpolation')
plt.legend()
plt.show()
结果如下图:
三点注意事项:
- 以下也可以应用于二维以上
- 样本之间的间距不固定。实现等距采样的一种简单方法是在返回的
samples
之间进行线性插值,例如在 this post. 中已经讨论过。
- 切线的指定是可选的,但是
BPoly.from_derivatives
不能确保此位置样条曲线之间的平滑过渡。例如,如果将上述示例中的tangents[1]
设置为None
、sampleCubicSplinesWithDerivative(points, tangents, resolution)
,结果将如下所示: