參考
# -- coding: utf-8 --
"""
@Project: lecture
@Time : 2020/4/29 21:54
@Author : Yang xu
@Site :
@File : parameter equation.py
@IDE: PyCharm
"""
import numpy as np
import matplotlib.pyplot as plt
from pylab import mpl
class SPLINE(object):
def __init__(self, p, p_):
self.p = p # 型值點
self.p_ = p_ # 端點矢切
self.n = len(p) # 型值點數
self.s = self.n - 1 # 線段數
self.t = np.zeros(self.s)
self.m = np.zeros((self.n, self.n))
self.C_y = []
self.A = []
self.B = []
self.C = []
self.D = []
self.samples_t = []
self.samples_s = []
def caculate_t(self):
# 線段數量
# self.s = len(self.p)-1
# self.t = np.zeros(self.s)
for i in range(self.s):
self.t[i] = np.sqrt((self.p[i+1][0]-self.p[i][0])**2 + (self.p[i+1][1]-self.p[i][1])**2)
return self.t
def caculate_matrix(self):
# t = SPLINE.caculate_t(p)
# n = len(p)
# self.m = np.zeros((n, n))
for i in range(self.n):
for j in range(self.n):
if i == 0 and j == 0 or i == self.n-1 and j == self.n-1:
self.m[i][j] = 1
elif i == 0 and j == 1 or i == self.n-1 and j == self.n-2:
self.m[i][j] = 0
elif i == j: # i不可能等於0
self.m[i][j] = 2*(self.t[i]+self.t[i-1])
elif i+1 == j: # i不可能到n-1
self.m[i][j] = self.t[i]
elif i-1 == j: # i不可能等於0
self.m[i][j] = self.t[i-1]
return self.m
def caculate_C_y(self):
# n = len(p)
# C = np.zeros(n)
for i in range(self.n):
if i == 0:
# self.C_y[i] = self.p_[i]
self.C_y.append(self.p_[i])
elif i == self.n-1:
# self.C_y[i] = self.p_[self.n-1]
self.C_y.append(self.p_[self.n-1])
else:
temp = self.t[i-1] * self.t[i] * \
(3 * (self.p[i+1] - self.p[i]) / self.t[i] ** 2 + 3 * (self.p[i] - self.p[i-1]) / self.t[i-1] ** 2)
self.C_y.append(temp)
self.C_y = np.array(self.C_y)
return self.C_y
def caculate_vector_cut(self):
temp = np.linalg.solve(self.m, self.C_y)
self.p_ = np.array(temp)
return temp
def caculate_parameter(self):
for i in range(self.s):
A = 2*(self.p[i] - self.p[i + 1]) / self.t[i] ** 3 + (self.p_[i + 1] + self.p_[i]) / self.t[i] ** 2
self.A.append(A)
B = 3*(self.p[i+1]-self.p[i])/self.t[i]**2 - (2*self.p_[i] + self.p_[i+1])/self.t[i]
self.B.append(B)
C = self.p_[i]
self.C.append(C)
D = self.p[i]
self.D.append(D)
self.A = np.array(self.A)
self.B = np.array(self.B)
self.C = np.array(self.C)
self.D = np.array(self.D)
return self.A, self.B, self.C, self.D
# def caculate_S_t(self, i, t):
# return self.A[i] * t**3 + self.B[i] * t**2 + self.C[i]*t + self.D[i]
def grasp_sample(self):
for i in range(self.s):
sample_t = np.arange(0, self.t[i], 0.01)
sample_s = []
for t in sample_t:
S_t = self.A[i] * t**3 + self.B[i] * t**2 + self.C[i]*t + self.D[i]
sample_s.append(S_t)
# sample_y = calculate(result[(i - 1) * 4:i * 4], sample_x)
self.samples_t.extend(sample_t)
self.samples_s.extend(sample_s)
self.samples_t.append(self.t[-1])
s_t = self.A[-1] * self.t[-1]**3 + self.B[-1] * self.t[-1]**2 + self.C[-1]*self.t[-1] + self.D[-1]
self.samples_s.append(s_t)
self.samples_t = np.array(self.samples_t)
self.samples_s = np.array(self.samples_s)
def show_view(self):
plt.plot(self.samples_s[:,0], self.samples_s[:,1], label="擬合曲線", color="black")
plt.scatter(self.p[:,0], self.p[:,1], label="離散數據", color="red")
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
plt.title("三次樣條函數")
plt.legend(loc="upper left")
plt.show()
def __str__(self):
return "型值點數={}\n線段數={}\n型值點={}\n端點矢切={}\n線段長度={}\n求矢切的矩陣={}\n求矢切的C={}\n" \
"參數A={}\n參數B={}\n參數C={}\n參數D={}\n繪圖t={}\n繪圖點={}\n".format(self.n, self.s, self.p, self.p_,
self.t, self.m, self.C_y, self.A, self.B, self.C, self.D, self.samples_t, self.samples_s)
__repr__ = __str__
if __name__ == '__main__':
p = [[0,0],[0,2],[3,2]]
p_ = [[-1,1],[],[2,-1]] # 維度必須n*2
p = np.array(p)
p_ = np.array(p_)
spline = SPLINE(p, p_)
spline.caculate_t()
spline.caculate_matrix()
spline.caculate_C_y()
spline.caculate_vector_cut()
spline.caculate_parameter()
spline.grasp_sample()
spline.show_view()
print(spline)
一個三次樣條曲線題目(需要設參數方程解)
擬合後的圖形