简体   繁体   中英

Cubic spline interpolation method

I am currently exploring cubic spline interpolation methods and I have come across the following code which interpolates in 3 dimensions, however I am unsure exactly how it works. I've researched cubic spline interpolation however all of the formula seem to only apply in 2 dimensions. Can anyone provide any insight into how this program works?

import numpy as np
import matplotlib as mpl
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from numpy import matrix, average
import scipy.linalg 

# Parameters
pointsInterpolation=False
curveInterpolation=True
'''
    numberOfInterpolation determines the precision of interpolation.
    bigger numberOfInterpolation, more smooth curve
'''
numberOfInterpolation = 100


j=0
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

def cubicSplineInterpolate(x_axis,y_axis,z_axis):
    '''
        prepare right-side vector
    '''
    dx=[]
    dy=[]
    dz=[]
    matrix=[]
    n=2
    while n<len(x_axis):
        dx.append(3*(x_axis[n]-2*x_axis[n-1]+x_axis[n-2]))
        dy.append(3*(y_axis[n]-2*y_axis[n-1]+y_axis[n-2]))
        dz.append(3*(z_axis[n]-2*z_axis[n-1]+z_axis[n-2]))
        n=n+1   
    '''
        produce square matrix looks like :
        [[2.0, 0.5, 0.0, 0.0], [0.5, 2.0, 0.5, 0.0], [0.0, 0.5, 2.0, 0.5], [0.0, 0.0, 2.0, 0.5]]
        the classes of the matrix depends on the length of x_axis(number of nodes)
    '''
    matrix.append([float(2), float(0.5)])
    for m in range(len(x_axis)-4):
        matrix[0].append(float(0))                
    n=2
    while n<len(x_axis)-2:
        matrix.append([])
        for m in range(n-2):
            matrix[n-1].append(float(0)) 

        matrix[n-1].append(float(0.5))
        matrix[n-1].append(float(2))
        matrix[n-1].append(float(0.5))

        for m in range(len(x_axis)-n-3):
            matrix[n-1].append(float(0)) 
        n=n+1

    matrix.append([])
    for m in range(n-2):
        matrix[n-1].append(float(0))    
    matrix[n-1].append(float(0.5))    
    matrix[n-1].append(float(2))
    '''
        LU Factorization may not be optimal method to solve this regular matrix.
        If you guys have better idea to solve the Equation, please contact me.
    '''
    P, L, U = doLUFactorization(matrix)
    u=solveEquations(P,L,U,dx)
    v=solveEquations(P,L,U,dy)
    w=solveEquations(P,L,U,dz)

    '''
        define gradient of start/end point
    '''
    m=0
    U=[0]
    V=[0]
    W=[0]
    while m<len(u):
        U.append(u[m])
        V.append(v[m])
        W.append(w[m])
        m=m+1
    U.append(0)
    V.append(0)
    W.append(0)

    plotCubicSpline(U,V,W,x_axis,y_axis,z_axis)

'''
    calculate each parameters of location.
'''
def func(x1,x2,t,v1,v2,t1,t2):
    ft=((t2-t)**3*v1+(t-t1)**3*v2)/6+(t-t1)*(x2-v2/6)+(t2-t)*(x1-v1/6)
    return ft

'''
    note: 
    too many interpolate points make your computer slack.
    To interpolate large amount of input parameters,
    please switch to ax.plot().
'''
def plotCubicSpline(U,V,W,x_axis,y_axis,z_axis):
    m=1
    xLinespace=[]
    yLinespace=[]
    zLinespace=[]
    while m<len(x_axis):
        for t in np.arange(m-1,m,1/float(numberOfInterpolation)):
            xLinespace.append(func(x_axis[m-1],x_axis[m],t,U[m-1],U[m],m-1,m))
            yLinespace.append(func(y_axis[m-1],y_axis[m],t,V[m-1],V[m],m-1,m))
            zLinespace.append(func(z_axis[m-1],z_axis[m],t,W[m-1],W[m],m-1,m))
        m=m+1
    if pointsInterpolation:
        ax.scatter(xLinespace, yLinespace,zLinespace,color="red",s=0.01)
    if curveInterpolation:
        ax.plot(xLinespace, yLinespace,zLinespace,color="red")
    '''
    matched group, annotate it if unnecessary
    '''
    ax.plot(x_axis,y_axis,z_axis,color="blue")

'''
    matrix·x = y
    P·matrix = L·U
    P·matrix·x = L·U·x = P·y
    L·U·x = y1
    U·x = y2
    x = y3
'''  
def solveEquations(P,L,U,y):
    y1=np.dot(P,y)
    y2=y1
    m=0
    for m in range(0, len(y)):
        for n in range(0, m):
            y2[m] = y2[m] - y2[n] * L[m][n]
        y2[m] = y2[m] / L[m][m]
    y3 = y2
    for m in range(len(y) - 1,-1,-1):
        for n in range(len(y) - 1, m, -1):
            y3[m] = y3[m] - y3[n] * U[m][n]
        y3[m] = y3[m] / U[m][m]
    return y3

'''
    this is the Scipy tool with high complexity.
'''    
def doLUFactorization(matrix):    
    P, L, U=scipy.linalg.lu(matrix)
    return P, L, U   

'''
    input parameters
    each vector contain at least 3 elements
'''
x_axis = [1, 2, 3, 4]
y_axis = [2, 3, 4, 5]
z_axis = [3, 4, 7, 5]

cubicSplineInterpolate(x_axis,y_axis,z_axis)

plt.show()

Your question makes no sense to me. Cubic spline interpolation (or any interpolation) works the same in 2d or 3d. 3d case is just a generalization of the 2d case/1d case. The basic principle of interpolation is to find a way to make an "educated guess" as to what the value between to neighboring point would be.

Cubic spline is just a specific case of a polynomial fit. You derive a polynomial that unites well the neighborhood, and then use that function to guess the missing value. The principle is the same in 1, 2 or 3d - you just have to look at more and more data point (and compute more polynomial).

Whether the code you posted in correct, or whether it is well-implemented is another matter, but that question would better fit code review than SO.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM