实际上,如果使用三次贝塞尔曲线,您将获得更大的灵活性。
这是第一个问题:
import math
import numpy as np
import matplotlib.pyplot as plt
#-----------------------------
def length( vector ): return np.linalg.norm( vector ) # length of a vector
def normalise( vector ): return vector / length(vector) # normalise a vector (numpy array)
#-----------------------------
class Bezier:
'''class for Cubic Bezier curve'''
def __init__( self, q0, q1, q2, q3 ):
self.p0 = np.array( q0 )
self.p1 = np.array( q1 )
self.p2 = np.array( q2 )
self.p3 = np.array( q3 )
def pt( self, t ):
return ( 1.0 - t ) ** 3 * self.p0 + 3.0 * t * ( 1.0 - t ) ** 2 * self.p1 + 3.0 * t ** 2 * ( 1.0 - t ) * self.p2 + t ** 3 * self.p3
def curve( self, n ):
crv = []
for t in np.linspace( 0.0, 1.0, n ):
crv.append( self.pt( t ) )
return crv
#-----------------------------
def drawBezier( x1, y1, heading1, x2, y2, heading2, n ):
'''Turns two points plus headings into cubic Bezier control points [ P0, P1, P2, P3 ] by adding intermediate control points'''
result = []
rad1, rad2 = heading1 * math.pi / 180, heading2 * math.pi / 180
d1 = np.array( [ np.sin( rad1 ), np.cos( rad1 ) ] ) # direction vector at point 1
d2 = np.array( [ np.sin( rad2 ), np.cos( rad2 ) ] )
p0 = np.array( ( x1, y1 ) ) # start point of Bezier curve
p3 = np.array( ( x2, y2 ) ) # end point of Bezier curve
p1 = p0 + d1 * length( p3 - p0 ) / 2.0 # use direction at P0 to get P1
p2 = p3 - d2 * length( p3 - p0 ) / 2.0 # use direction at p3 to get P2
arc = Bezier( p0, p1, p2, p3 ) # define a cubic Bezier object
x = []; y = []
for pt in arc.curve( n ):
x.append( pt[0] )
y.append( pt[1] )
plt.plot( x, y )
#-----------------------------
x1, y1, heading1 = 0.0, 0.0, 0.0
x2, y2, heading2 = 1.0, 1.0, 90.0
drawBezier( x1, y1, heading1, x2, y2, heading2, 100 )
plt.plot( [ x1, x2 ], [ y1, y2 ], 'o' ) # plot original support points
plt.show()
三次贝塞尔曲线的优点是还可以无缝处理两条方向线不交叉等情况。例如
x2, y2, heading2 = 1.0, 1.0, 0.0
有输出