Cubic hermit spline interpolation python

2024/11/14 20:27:58

I would like to calculate a third-degree polynomial that is defined by its function values and derivatives at specified points.

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

I know of scipy's interpolation methods. Specifically

splprep to interpolate a N-dimensional spline and splev to eveluate its derivatives.

Is there a python routine that takes function values f(x) and derivatives f'(x) corresponding to values x and calculates a spline representation that fits the given data.

To give an example:
I have two object positions in space defined by the coordinates x,y,z and I know the velocity x',y',z' of the object at these positions. Can I now interpolate the path that the object takes between the two points over time t. Taking all the given parameters into account.

Answer

Extending ev-br's answer, here some sample code that exemplifies the usage of BPoly.from_derivatives to interpolate between points in n dimensions with prescribed derivatives.

import numpy as np
from scipy import interpolatedef sampleCubicSplinesWithDerivative(points, tangents, resolution):'''Compute and sample the cubic splines for a set of input points withoptional information about the tangent (direction AND magnitude). The splines are parametrized along the traverse line (piecewise linear), withthe resolution being the step size of the parametrization parameter.The resulting samples have NOT an equidistant spacing.Arguments:      points: a list of n-dimensional pointstangents: a list of tangentsresolution: parametrization step sizeReturns:        samplesNotes: Lists points and tangents must have equal length. In case a tangentis 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 pointsdp = np.linalg.norm(dp, axis=1)              # distance between pointsd = np.cumsum(dp)                            # cumsum along the segmentsd = np.hstack([[0],d])                       # add distance from first pointl = d[-1]                                    # length of point sequencenSamples = int(l/resolution)                 # number of sampless,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

To demonstrate the use of this function, we specify the points and tangents. The example further demonstrates the effect if the "magnitude" of the tangents is changed.

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

This results in the following plot: Cubic splines for different tangent magnitudes

Three things to note:

  • The following can also be applied for more than two dimensions.
  • The spacing between the samples is not fixed. One simple way to achieve equidistant sampling is to interpolate linearly between the returned samples, as it has been discussed for instance in this post.
  • The specification of the tangents is optional, however BPoly.from_derivatives does not ensure smooth transitions between the splines at this position. If for example tangents[1] in the above sample is set to None, sampleCubicSplinesWithDerivative(points, tangents, resolution), the result will look like this: Cubic splines with only some tangents being prescribed
https://en.xdnf.cn/q/72119.html

Related Q&A

Increase Accuracy of float division (python)

Im writing a bit of code in PyCharm, and I want the division to be much more accurate than it currently is (40-50 numbers instead of about 15). How Can I accomplish this?Thanks.

Twitter API libraries for desktop apps?

Im looking for a way to fetch recent posts from twitter. Really I just want to be able to grab and store new posts about a certain topic from twitter in a text file. Are there any current programs or l…

How to generate a PDF from an HTML / CSS (including images) source in Python? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, argum…

Modify subclassed string in place

Ive got the following string subclass:class S(str):def conc(self, next_val, delimiter = ):"""Concatenate values to an existing string"""if not next_val is None:self = sel…

sum numpy ndarray with 3d array along a given axis 1

I have an numpy ndarray with shape (2,3,3),for example:array([[[ 1, 2, 3],[ 4, 5, 6],[12, 34, 90]],[[ 4, 5, 6],[ 2, 5, 6],[ 7, 3, 4]]])I am getting lost in np.sum(above ndarray ,axis=1), why …

Get the number of nonzero elements in a numpy array?

Is it possible to get the length of the nonzero elements in a numpy array without iterating over the array or masking the array. Speed is the main goal of calculating the length.Essentially, something…

Pytest on Python Tools for visual studio

Can debug python tests which are using pytest library on visual studio 2010 ? I added the -m pytest on the Interpreter arguments but the breakpoints are not hit, I can only run the test script without…

Python Paramiko directory walk over SFTP

How to do os.walk() but on another computer through SSH? The problem is that os.walk() executes on a local machine and I want to ssh to another host, walk through a directory and generate MD5 hashes f…

Python 2.7 32-bit install on Win 7: No registry keys?

I have downloaded the Python 2.7.2 Windows x86 32-bit MSI from python.org and installed it on a 64-bit Windows 7 system. Everything works (at least the command-line interpreter starts and runs), but t…

i18n with jinja2 + GAE

I googled for a GAE + jinja i18n example but could not find it. Can anyone provide a link or working example?My effort uses the django translations and I dont know if this is the recommend way of doin…