70 lines
1.9 KiB
Python
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
|
|
|