full-feed-financial-times/spline.py

70 lines
1.9 KiB
Python

import numpy as np
import scipy.interpolate as si
from scipy.spatial import distance
def bspline(cv, n=100, degree=3, periodic=False):
""" Calculate n samples on a bspline
cv : Array ov control vertices
n : Number of samples to return
degree: Curve degree
periodic: True - Curve is closed
False - Curve is open
"""
# If periodic, extend the point array by count+degree+1
cv = np.asarray(cv)
count = len(cv)
if periodic:
factor, fraction = divmod(count+degree+1, count)
cv = np.concatenate((cv,) * factor + (cv[:fraction],))
count = len(cv)
degree = np.clip(degree,1,degree)
# If opened, prevent degree from exceeding count-1
else:
degree = np.clip(degree,1,count-1)
# Calculate knot vector
kv = None
if periodic:
kv = np.arange(0-degree,count+degree+degree-1,dtype='int')
else:
kv = np.concatenate(([0]*degree, np.arange(count-degree+1), [count-degree]*degree))
# Calculate query range
u = np.linspace(periodic,(count-degree),n)
# Calculate result
return np.array(si.splev(u, (kv,cv.T,degree))).T
#a_d = dist.euclidean(cv[0],v[0])
#b_d = dist.euclidean(v[-1],cv[-1])
#a = np.array(list(zip(
# np.linspace(cv[0][0],v[0][0],a_d*2),
# np.linspace(cv[0][1],v[0][1],a_d*2))))
#b = np.array(list(zip(
# np.linspace(v[-1][0],cv[-1][0],b_d*2),
# np.linspace(v[-1][1],cv[-1][1],b_d*2))))
#return np.concatenate(a,v,b)
def gcv(p1,p2, n):
d = distance.euclidean(p1,p2)
x_lst = np.linspace(p1[0],p2[0],n-2)
y_lst = np.linspace(p1[1],p2[1],n-2)
r = np.random.random_sample((n-2,))
r_ = np.random.random_sample((n-2,))
s = np.array(list(zip(x_lst + d *(r_-0.5),y_lst + d *(r-0.5))))
b = np.concatenate((np.array([[p1[0],p1[1]]]),np.concatenate((s,np.array([[p2[0],p2[1]]])))))
return b