Bezier曲線を用いて経路生成を行おうとしています。コードを実行すると、キャンバスが出てきます。左画面上を左クリックすると1点追加,右クリックで直近の1点削除です。3点追加されると、Bezier曲線が表示されるようにしたいのですが、上手くいきません。Bezier曲線を計算する関数から値が戻ってきているか不明です。Bezier曲線を連続で接続したいです。ある区間の終点とその次の区間の始点が一致し、さらに1階微分まで一致させたいです。
Bezier曲線は各区間の始点(P0)と終点(P2)を通り、その間の点を制御点(P1)とする2次Bezier曲線です。よろしくお願い致します。
Python
1import matplotlib.pyplot as plt 2import numpy as np 3from scipy import interpolate 4 5def main(): 6 fig = plt.figure(figsize=(11.0, 5.0)) 7 ClickAddPoints(fig) 8 9class ClickAddPoints: 10 def __init__(self, fig): 11 self.fig = fig 12 self.ax1 = fig.add_subplot(121) 13 # ax2に曲率を表示 14 self.ax2 = fig.add_subplot(122) 15 self.ax1.figure.canvas.mpl_connect('button_press_event', self.on_click) 16 self.ax1.figure.canvas.mpl_connect('key_press_event', self.on_key) 17 self.x = [] 18 self.y = [] 19 self.r = [] 20 self.update_plot() 21 plt.show() 22 23 def calc_bezier(self, x1, y1, x2, y2, x3, y3): 24 25 P0x = 0 26 P0y = 0 27 bez_x = [] 28 bez_y = [] 29 dt = 100 30 tstep = np.arange(0, 1, dt) 31 for i in tstep: 32 x = P0x 33 y = P0y 34 35 bez_x.append(x) 36 bez_y.append(y) 37 38 #ベジェ計算 39 x = (x3 - 2*x2 + x1)*i**2 + 2*(x2 - x1)*i + x1 40 y = (y3 - 2*y2 + y1)*i**2 + 2*(y2 - y1)*i + y1 41 #1階微分 42 dx = 2*(x3 - 2*x2 + x1)*i + 2*(x2 - x1) 43 dy = 2*(y3 - 2*y2 + y1)*i + 2*(y2 - y1) 44 #2階微分 45 ddx = 2*(x3 - 2*x2 + x1) 46 ddy = 2*(y3 - 2*y2 + y1) 47 48 P1x = P0x + x 49 P1y = P0y + y 50 P0x = P1x 51 P0y = P1y 52 53 return bez_x, bez_y 54 55 def update_plot(self): 56 self.ax1.set_xticks(np.linspace(0, 6, 6)) 57 self.ax1.set_yticks(np.linspace(0, 6, 6)) 58 self.ax1.set_aspect('equal') 59 self.ax1.figure.canvas.draw() 60 self.ax2.set_ylim(0, 40) 61 self.ax2.figure.canvas.draw() 62 63 def on_click(self, event): 64 if event.button == 1: 65 # コントロール点を追加 66 if event.inaxes is not self.ax1: 67 return 68 # 過去の座標と同一座標をクリックした場合は抜ける 69 if event.xdata in self.x and event.ydata in self.y: 70 return 71 self.x.append(event.xdata) 72 self.y.append(event.ydata) 73 self.redraw() 74 print('Added no.{} point at [{} {}]'.format(len(self.x), self.x[-1], self.y[-1])) 75 elif event.button == 3: 76 # 直近のコントロール点を削除 77 if len(self.x) > 0: 78 self.x.pop() 79 self.y.pop() 80 self.redraw() 81 print('Removed no.{0} point'.format(len(self.x)+1)) 82 83 def redraw(self): 84 self.ax1.cla() 85 self.ax2.cla() 86 count = len(self.x) 87 if count > 0: 88 # クリック点の描画 89 self.ax1.plot(self.x, self.y, 'ro') 90 91 elif count >= 3: 92 x1, y1 = [self.calc_bezier(self.x[i-1], self.y[i-1], self.x[i], self.y[i], self.x[i+1], self.y[i+1])for i in range(1, len(self.x)-1, 2)] 93 print(x1) 94 self.ax1.plot(self.x, self.y, 'ro') 95 self.ax1.plot(x1, y1) 96 print() 97 98 else: 99 return 100 101 # 線の描画 102 103 self.ax2.plot(self.r) 104 self.update_plot() 105 106 def on_key(self, event): 107 # qキーで終了 108 if event.key == 'q': 109 print('Finish') 110 return 111 112 # wキーで全削除 113 if event.key == 'w': 114 self.x.clear() 115 self.y.clear() 116 self.redraw() 117 print('All Clear') 118 119main()
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/21 02:32
2020/07/21 04:31 編集
2020/07/21 06:00 編集
2020/07/22 02:56
2020/07/22 03:59
2020/07/22 09:21
2020/07/23 10:10