3点からCatmull-Romスプラインを計算するためのライブラリまたは関数がPythonにありますか?
最後に必要なのは、スプラインに沿った点のx、y座標です。ただし、スプラインに沿って指定された量tから常に等距離にある場合(たとえば、スプライン曲線の長さは3単位で、x、y座標が必要です)。スプラインの長さ0、1、2、および3で)
本当にエキサイティングなものはありません。私は自分で書いていますが、何かいいものを見つけたら、テストする(または時間を節約する)のに最適です
3点?Catmull-Romは4つのポイントに対して定義されています。たとえば、p_1 p0p1p2です。三次曲線はp0からp1に移動し、外側の点p_1とp2がp0とp1の傾きを決定します。配列Pのいくつかの点を通る曲線を描くには、次のようにします。
for j in range( 1, len(P)-2 ): # skip the ends
for t in range( 10 ): # t: 0 .1 .2 .. .9
p = spline_4p( t/10, P[j-1], P[j], P[j+1], P[j+2] )
# draw p
def spline_4p( t, p_1, p0, p1, p2 ):
""" Catmull-Rom
(Ps can be numpy vectors or arrays too: colors, curves ...)
"""
# wikipedia Catmull-Rom -> Cubic_Hermite_spline
# 0 -> p0, 1 -> p1, 1/2 -> (- p_1 + 9 p0 + 9 p1 - p2) / 16
# assert 0 <= t <= 1
return (
t*((2-t)*t - 1) * p_1
+ (t*t*(3*t - 5) + 2) * p0
+ t*((4 - 3*t)*t + 1) * p1
+ (t-1)*t*t * p2 ) / 2
3点を通る区分的二次曲線を使用できます。Dodgson 、画像リサンプリングの二次補間を参照してください。本当に何をしたいですか?
これがあります: Pythonにあるように見えるjj_catmull、多分あなたはそこで必要なものを見つけることができます。
前述のように、catmull-romには4ポイントが必要であり、エンドポイントが問題になります。自然な3次スプラインの代わりにこれらを自分で適用することを検討していました(既知のデータ範囲を超える可能性のあるオーバーシュートは、私のアプリケーションでは実用的ではありません)。@denisのコードと同様に、ここに役立つものがあります(いくつかの点に注意してください。1)このコードはランダムにポイントを生成するだけです。コメントアウトされた例を使用して、独自のデータを使用することができます。2)ドメインの1%の任意の距離を使用して、最初と最後の2つのポイント間の勾配を維持しながら拡張エンドポイントを作成します。3)比較のために、均一、求心、および脊索の結び目のパラメーター化を含めます):
# coding: utf-8
# In[1]:
import numpy
import matplotlib.pyplot as plt
get_ipython().magic(u'pylab inline')
# In[2]:
def CatmullRomSpline(P0, P1, P2, P3, a, nPoints=100):
"""
P0, P1, P2, and P3 should be (x,y) point pairs that define the Catmull-Rom spline.
nPoints is the number of points to include in this curve segment.
"""
# Convert the points to numpy so that we can do array multiplication
P0, P1, P2, P3 = map(numpy.array, [P0, P1, P2, P3])
# Calculate t0 to t4
alpha = a
def tj(ti, Pi, Pj):
xi, yi = Pi
xj, yj = Pj
return ( ( (xj-xi)**2 + (yj-yi)**2 )**0.5 )**alpha + ti
t0 = 0
t1 = tj(t0, P0, P1)
t2 = tj(t1, P1, P2)
t3 = tj(t2, P2, P3)
# Only calculate points between P1 and P2
t = numpy.linspace(t1,t2,nPoints)
# Reshape so that we can multiply by the points P0 to P3
# and get a point for each value of t.
t = t.reshape(len(t),1)
A1 = (t1-t)/(t1-t0)*P0 + (t-t0)/(t1-t0)*P1
A2 = (t2-t)/(t2-t1)*P1 + (t-t1)/(t2-t1)*P2
A3 = (t3-t)/(t3-t2)*P2 + (t-t2)/(t3-t2)*P3
B1 = (t2-t)/(t2-t0)*A1 + (t-t0)/(t2-t0)*A2
B2 = (t3-t)/(t3-t1)*A2 + (t-t1)/(t3-t1)*A3
C = (t2-t)/(t2-t1)*B1 + (t-t1)/(t2-t1)*B2
return C
def CatmullRomChain(P,alpha):
"""
Calculate Catmull Rom for a chain of points and return the combined curve.
"""
sz = len(P)
# The curve C will contain an array of (x,y) points.
C = []
for i in range(sz-3):
c = CatmullRomSpline(P[i], P[i+1], P[i+2], P[i+3],alpha)
C.extend(c)
return C
# In[139]:
# Define a set of points for curve to go through
Points = numpy.random.rand(10,2)
#Points=array([array([153.01,722.67]),array([152.73,699.92]),array([152.91,683.04]),array([154.6,643.45]),
# array([158.07,603.97])])
#Points = array([array([0,92.05330318]),
# array([2.39580622,29.76345192]),
# array([10.01564963,16.91470591]),
# array([15.26219886,71.56301997]),
# array([15.51234733,73.76834447]),
# array([24.88468545,50.89432899]),
# array([27.83934153,81.1341789]),
# array([36.80443404,56.55810783]),
# array([43.1404725,16.96946811]),
# array([45.27824599,15.75903418]),
# array([51.58871027,90.63583215])])
x1=Points[0][0]
x2=Points[1][0]
y1=Points[0][1]
y2=Points[1][1]
x3=Points[-2][0]
x4=Points[-1][0]
y3=Points[-2][1]
y4=Points[-1][1]
dom=max(Points[:,0])-min(Points[:,0])
rng=max(Points[:,1])-min(Points[:,1])
pctdom=1
pctdom=float(pctdom)/100
prex=x1+sign(x1-x2)*dom*pctdom
prey=(y1-y2)/(x1-x2)*(prex-x1)+y1
endx=x4+sign(x4-x3)*dom*pctdom
endy=(y4-y3)/(x4-x3)*(endx-x4)+y4
print len(Points)
Points=list(Points)
Points.insert(0,array([prex,prey]))
Points.append(array([endx,endy]))
print len(Points)
# In[140]:
#Define alpha
a=0.
# Calculate the Catmull-Rom splines through the points
c = CatmullRomChain(Points,a)
# Convert the Catmull-Rom curve points into x and y arrays and plot
x,y = zip(*c)
plt.plot(x,y,c='green',zorder=10)
a=0.5
c = CatmullRomChain(Points,a)
x,y = zip(*c)
plt.plot(x,y,c='blue')
a=1.
c = CatmullRomChain(Points,a)
x,y = zip(*c)
plt.plot(x,y,c='red')
# Plot the control points
px, py = zip(*Points)
plt.plot(px,py,'o',c='black')
plt.grid(b=True)
plt.show()
# In[141]:
Points
# In[104]: