3

我想计算一个三次多项式,该多项式由其函数值和指定点的导数定义。

https://en.wikipedia.org/wiki/Cubic_Hermite_spline

我知道 scipy 的插值方法。具体来说

splprep插值 N 维样条和 splev来评估其导数。

是否有一个 python 例程接受函数值f(x)和对应于值x的导数f'(x)并计算适合给定数据的样条表示。

举个例子:
我在空间中有两个由坐标x,y,z定义的物体位置,我知道物体在这些位置的速度x',y',z'。我现在可以在时间 t 内插值对象在两点之间的路径吗?考虑所有给定的参数。

4

2 回答 2

10

扩展ev-br 的答案,这里有一些示例代码,举例说明了在具有规定导数的nBPoly.from_derivatives点之间进行插值的用法。

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

为了演示这个函数的使用,我们指定了点和切线。该示例进一步演示了如果切线的“大小”发生更改时的效果。

# 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,正如本文中所讨论的那样
  • 切线的指定是可选的,但BPoly.from_derivatives不能确保该位置的样条线之间的平滑过渡。例如,如果tangents[1]在上面的示例中设置为None, sampleCubicSplinesWithDerivative(points, tangents, resolution),结果将如下所示: 仅规定了一些切线的三次样条
于 2017-12-29T18:15:43.507 回答
3

您可以使用BPoly.from_derivatives. 结果是 Bernstein 基中的多项式。

于 2016-04-15T19:09:43.340 回答