matplotlibのキャンバス上に手入力で制御点を打ち,その点をスプライン補間しています。スプライン曲線の算出にはScipyのsplprepを用いています。しかし打ち込む点が多くなると,曲線が滑らかさを失い、がたつきがある線になってしまいます。原因はなんでしょうか。
また、算出した曲線の曲率を算出したいのですが、近接した3点を取る方法がわかりません。ご教授願います。よろしくお願いします。
python
1import matplotlib.pyplot as plt 2import numpy as np 3from scipy import interpolate 4 5 6def main(): 7 fig = plt.figure(figsize=(11.0, 5.0)) 8 ClickAddPoints(fig) 9 10 11class ClickAddPoints: 12 def __init__(self, fig): 13 self.fig = fig 14 self.ax1 = fig.add_subplot(121) 15 # ax2に曲率を表示 16 self.ax2 = fig.add_subplot(122) 17 self.ax1.figure.canvas.mpl_connect('button_press_event', self.on_click) 18 self.ax1.figure.canvas.mpl_connect('key_press_event', self.on_key) 19 self.x = [] 20 self.y = [] 21 self.r = [] 22 self.s = [] 23 self.x2 = [] 24 self.y2 = [] 25 self.update_plot() 26 self.div = 1000 # スプラインの分割数。多いほどなめらかに描画。 27 plt.show() 28 29 def calc_spline(self, x, y, point, deg): 30 tck, u = interpolate.splprep([x, y], k=deg, s=0) 31 u = np.linspace(0, 1, num=point, endpoint=True) 32 spline = interpolate.splev(u, tck, der=0) 33 return spline[0], spline[1] 34 35 def cal_curveture(self, x1, y1, x2, y2, x3, y3): 36 r = 1/(abs(x1*y2-x2*y1+x2*y3-x3*y2+x3*y1-x1*y3)/( 37 ((x1-x2)**2+(y1-y2)**2)*((x2-x3)**2+(y2-y3)**2)*((x3-x1)**2+(y3-y1)**2))**(1/2)) 38 return r 39 40 def cal_curve_length(self, x1, y1, x2, y2): 41 s = np.sqrt((x2-x1)**2+(y2-y1)**2) 42 return s 43 44 def cal_clothoid(self, T, dt, V, R, _P0x, _P0y, _dθ): 45 #クロソイドの計算 46 v = (V*1000)/3600 47 L = v*T 48 A = np.sqrt(L*R) 49 dL = v*dt 50 P0x = _P0x 51 P0y = _P0y 52 Lt = 0 53 dθ = _dθ 54 dLt = dL 55 A2 = A**2 56 tsteps = np.arange(0, T, dt) 57 58 for i in tsteps: 59 x2 = P0x 60 y2 = P0y 61 62 self.x2.append(x2) 63 self.y2.append(y2) 64 65 Lt = Lt + dLt 66 Rt = A2 / Lt 67 k = 1 / Rt 68 dθ = dθ + dLt / Rt 69 dx = dL * np.cos(dθ) 70 dy = dL * np.sin(dθ) 71 P1x = P0x + dx 72 P1y = P0y + dy 73 P0x = P1x 74 P0y = P1y 75 76 return self.x2, self.y2 77 78 def update_plot(self): 79 self.ax1.set_xticks(np.linspace(0, 10, 5)) 80 self.ax1.set_yticks(np.linspace(0, 10, 5)) 81 self.ax1.set_aspect('equal') 82 self.ax1.figure.canvas.draw() 83 self.ax2.set_ylim(0, 40) 84 self.ax2.figure.canvas.draw() 85 86 def on_key(self, event): 87 # qキーで終了 88 if event.key == 'q': 89 print('Finish') 90 return 91 92 # wキーで全削除 93 if event.key == 'w': 94 self.x.clear() 95 self.y.clear() 96 self.redraw() 97 print('All Clear') 98 99 # pキーでスプライン 100 if event.key == 'p': 101 print('spline') 102 103 # cキーでクロソイド 104 elif event.key == 'c': 105 print('clothoid') 106 107 # tキーで直線 108 elif event.key == 't': 109 print('straight line') 110 111 else: 112 return 113 114 def on_click(self, event): 115 if event.button == 1: 116 # コントロール点を追加 117 if event.inaxes is not self.ax1: 118 return 119 # 過去の座標と同一座標をクリックした場合は抜ける 120 if event.xdata in self.x and event.ydata in self.y: 121 return 122 self.x.append(event.xdata) 123 self.y.append(event.ydata) 124 self.redraw() 125 print('Added no.{} point at [{} {}]'.format(len(self.x), self.x[-1], self.y[-1])) 126 elif event.button == 3: 127 # 直近のコントロール点を削除 128 if len(self.x) > 0: 129 self.x.pop() 130 self.y.pop() 131 self.redraw() 132 print('Removed no.{0} point'.format(len(self.x)+1)) 133 134 def redraw(self): 135 self.ax1.cla() 136 self.ax2.cla() 137 count = len(self.x) 138 if count > 0: 139 # クリック点の描画 140 self.ax1.plot(self.x, self.y, 'ro') 141 if count <= 1: 142 self.update_plot() 143 return 144 if count == 2: 145 deg = 1 146 elif count == 3: 147 deg = 2 148 elif count > 3: 149 deg = 3 150 else: 151 return 152 153 x1, y1 = self.calc_spline(self.x, self.y, self.div, deg) 154 #曲線長 155 if len(self.x) >= 2: 156 self.s = [self.cal_curve_length(x1[i],y1[i], 157 x1[i+1],y1[i+1]) 158 for i in range(0, len(x1)-1)] 159 160 # 曲率データの更新 161 if len(self.x) > 2: 162 self.r = [self.cal_curveture(x1[i-1], y1[i-1], 163 x1[i], y1[i], 164 x1[i+1], y1[i+1]) 165 for i in range(1, len(x1)-1)] 166 167 # 線の描画 168 self.ax1.plot(x1, y1) 169 self.ax2.plot(self.r) 170 self.update_plot() 171 172 173main()
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/02 06:41
2020/07/02 07:37 編集
2020/07/02 08:46
2020/07/02 09:46
2020/07/02 10:16
2020/07/02 12:00 編集
2020/07/03 03:14
2020/07/03 17:25
2020/07/04 04:08
2024/04/22 12:14 編集
2020/07/04 12:12