Кубический отшельник интерполяционный питон

Я хотел бы вычислить полином третьей степени, который определяется значениями его функций и производными в указанных точках.

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

Я знаю методы интерполяции Сципи. конкретно

splprep для интерполяции N-мерного сплайна и splev для выявления его производных.

Существует ли подпрограмма Python, которая принимает значения функций f(x) и производные f'(x), соответствующие значениям x, и вычисляет представление сплайна, которое соответствует заданным данным.

Чтобы привести пример:
У меня есть две позиции объекта в пространстве, определенные координатами x, y,z, и я знаю скорость x',y',z' объекта в этих позициях. Могу ли я теперь интерполировать путь, по которому объект проходит между двумя точками за время t. С учетом всех заданных параметров.

2 ответа

Решение

Ты можешь использовать BPoly.from_derivatives, Результатом является полином по базису Бернштейна.

Расширяя ответ ev-br, приведу пример кода, который иллюстрирует использование 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()

Это приводит к следующему сюжету: Кубические сплайны для разных касательных величин

Три вещи на заметку:

  • Следующее может также применяться для более чем двух измерений.
  • Расстояние между образцами не фиксировано. Одним из простых способов достижения эквидистантной выборки является линейная интерполяция между samples, как это обсуждалось, например, в этом посте.
  • Спецификация касательных является необязательной, однако BPoly.from_derivatives не обеспечивает плавных переходов между сплайнами в этой позиции. Если например tangents[1] в приведенном выше примере установлено None, sampleCubicSplinesWithDerivative(points, tangents, resolution), результат будет выглядеть так: Кубические сплайны с указанием только некоторых касательных
Другие вопросы по тегам