立方隐士样条插值python

时间:2016-04-15 10:10:03

标签: python scipy interpolation spline hermite

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

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

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

splprep插入一个N维样条曲线 和 splev来贬低其衍生物。

是否有一个python例程,它接受与 x 值对应的函数值 f(x)和衍生词 f'(x)并计算适合给定数据的样条曲线表示。

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

2 个答案:

答案 0 :(得分:3)

扩展ev-br's answer,这里有一些示例代码,用于举例说明使用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

为了演示此功能的使用,我们指定了点和切线。该例子进一步证明了切线的“幅度”改变后的效果。

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

这导致以下情节: Cubic splines for different tangent magnitudes

需要注意三点:

  • 以下内容也适用于两个以上的维度。
  • 样本之间的间距不固定。实现等距采样的一种简单方法是在返回的samples之间进行线性插值,如this post中所述。
  • 切线的规格是可选的,但BPoly.from_derivatives不能确保此位置的样条曲线之间的平滑过渡。如果上例中的tangents[1]设置为NonesampleCubicSplinesWithDerivative(points, tangents, resolution),则结果如下所示: Cubic splines with only some tangents being prescribed

答案 1 :(得分:2)

您可以使用{{1}}。结果是Bernstein基础上的多项式。