回答編集履歴

3

整形

2020/07/26 07:05

投稿

Penpen7
Penpen7

スコア698

test CHANGED
@@ -144,13 +144,15 @@
144
144
 
145
145
 
146
146
 
147
+
148
+
147
149
  # 周期3次スプライン曲線のパラメータを求める。
148
150
 
149
151
  def calculatePeriodicSplineParameter(x):
150
152
 
151
153
  # t = 0,1,2,...,x.size-1とする。
152
154
 
153
- n = x.size-1
155
+ n = x.size - 1
154
156
 
155
157
  h = np.ones(n)
156
158
 
@@ -160,125 +162,103 @@
160
162
 
161
163
  # 対角成分
162
164
 
163
- Adiag = np.eye(n)
165
+ Adiag = np.zeros((n, n))
164
-
166
+
165
- Adiag[1:,1:] *= 2*(h[:-1]+h[1:])
167
+ Adiag[1:, 1:] = np.diag(2 * (h[:-1] + h[1:]))
166
-
168
+
167
- Adiag[0][0] *= 2*(h[-1]+h[0])
169
+ Adiag[0][0] = 2 * (h[-1] + h[0])
168
-
169
-
170
-
171
- # 対角成分の一つ下の斜めの成分
170
+
172
-
173
- Alower = np.eye(n, k=-1)
171
+ Alower = np.diag(h[:-1], k=-1)
174
-
175
- Alower[1:,:-1]*=h[:-1]
172
+
176
-
177
-
178
-
179
- # 対角成分の一つ上の斜めの成分
180
-
181
- Aupper = np.eye(n, k=1)
173
+ Aupper = np.diag(h[:-1], k=1)
182
-
183
- Aupper[:-1,1:]*=h[:-1]
174
+
175
+
184
176
 
185
177
  A = Adiag + Alower + Aupper
186
178
 
187
-
188
-
189
179
  A[-1][0] = h[-1]
190
180
 
191
181
  A[0][-1] = h[-1]
192
182
 
193
183
 
194
184
 
195
- # Aの逆行列
196
-
197
- Ainv = np.linalg.inv(A)
198
-
199
-
200
-
201
185
  # 対角成分
202
186
 
203
- Vdiag = np.eye(n)
187
+ Vdiag = np.zeros((n, n))
204
-
188
+
205
- Vdiag[1:,1:] *= -(1/h[:-1]+1/h[1:])
189
+ Vdiag[1:, 1:] = np.diag(-(1 / h[:-1] + 1 / h[1:]))
206
-
190
+
207
- Vdiag[0][0] *= -(1/h[-1]+1/h[0])
191
+ Vdiag[0][0] = -(1 / h[-1] + 1 / h[0])
208
-
209
-
210
-
211
- # 対角成分の一つ下の斜めの成分
192
+
212
-
213
- Vlower = np.eye(n, k=-1)
214
-
215
- Vlower[1:,:-1]*=1/h[:-1]
193
+ Vlower = np.diag(1 / h[:-1], k=-1)
216
-
217
-
218
-
219
- # 対角成分の一つ上の斜めの成分
194
+
220
-
221
- Vupper = np.eye(n, k=1)
222
-
223
- Vupper[:-1,1:]*=1/h[:-1]
195
+ Vupper = np.diag(1 / h[:-1], k=1)
196
+
197
+
224
198
 
225
199
  V = Vdiag + Vlower + Vupper
226
200
 
227
-
228
-
229
201
  V[-1][0] = h[-1]
230
202
 
231
203
  V[0][-1] = h[-1]
232
204
 
233
-
234
-
205
+
206
+
235
- r = 3*np.dot(V,a[:-1])
207
+ r = 3 * np.dot(V, a[:-1])
236
-
237
-
238
-
208
+
209
+
210
+
239
- c = np.dot(Ainv, r)
211
+ c = np.linalg.solve(A, r)
240
-
241
-
212
+
213
+
242
214
 
243
215
  c = np.insert(c, c.size, c[0])
244
216
 
217
+
218
+
245
- d = (c[1:]-c[:-1])/(3*h)
219
+ d = (c[1:] - c[:-1]) / (3 * h)
246
-
220
+
247
- b = (a[1:]-a[:-1])/h-h/3*(2*c[:-1]+c[1:])
221
+ b = (a[1:] - a[:-1]) / h - h / 3 * (2 * c[:-1] + c[1:])
248
222
 
249
223
  a = a[:-1]
250
224
 
251
225
  c = c[:-1]
252
226
 
253
- return [a,b,c,d]
227
+ return [a, b, c, d]
228
+
229
+
254
230
 
255
231
 
256
232
 
257
233
  # 三次関数の係数から, 元の点から間の点を求める。
258
234
 
259
- def calculateInterpolationPoints(splineParameter, interpolationPointsNumber=1000):
235
+ def calculateInterpolationPoints(splineParameter,
236
+
237
+ interpolationPointsNumber=1000):
260
238
 
261
239
  a, b, c, d = splineParameter
262
240
 
263
- assert(a.size==b.size==c.size==d.size)
241
+ assert (a.size == b.size == c.size == d.size)
264
242
 
265
243
  index = np.repeat(np.arange(a.size), interpolationPointsNumber, axis=0)
266
244
 
267
245
  t = np.tile(np.linspace(0, 1, interpolationPointsNumber), a.size)
268
246
 
269
- return a[index] + b[index]*t + c[index]*t**2 + d[index]*t**3
247
+ return a[index] + b[index] * t + c[index] * t**2 + d[index] * t**3
248
+
249
+
270
250
 
271
251
 
272
252
 
273
253
  # 補間したい点の座標
274
254
 
275
- x = np.random.rand(10)
255
+ x = np.random.rand(100)
276
256
 
277
257
  y = np.random.rand(x.size)
278
258
 
279
- x = np.insert(x,x.size,x[0])
259
+ x = np.insert(x, x.size, x[0])
280
-
260
+
281
- y = np.insert(y,y.size,y[0])
261
+ y = np.insert(y, y.size, y[0])
282
262
 
283
263
 
284
264
 
@@ -288,8 +268,6 @@
288
268
 
289
269
 
290
270
 
291
-
292
-
293
271
  X = calculateInterpolationPoints(parameterX)
294
272
 
295
273
  Y = calculateInterpolationPoints(parameterY)
@@ -302,11 +280,9 @@
302
280
 
303
281
  plt.legend()
304
282
 
305
- plt.savefig("graph.png", dpi=200,figsize=(4,3))
283
+ plt.savefig("graph.png", dpi=200, figsize=(4, 3))
306
-
307
-
308
-
309
-
284
+
285
+
310
286
 
311
287
  ```
312
288
 

2

コード修正

2020/07/26 07:05

投稿

Penpen7
Penpen7

スコア698

test CHANGED
@@ -198,7 +198,33 @@
198
198
 
199
199
 
200
200
 
201
+ # 対角成分
202
+
203
+ Vdiag = np.eye(n)
204
+
205
+ Vdiag[1:,1:] *= -(1/h[:-1]+1/h[1:])
206
+
207
+ Vdiag[0][0] *= -(1/h[-1]+1/h[0])
208
+
209
+
210
+
211
+ # 対角成分の一つ下の斜めの成分
212
+
213
+ Vlower = np.eye(n, k=-1)
214
+
215
+ Vlower[1:,:-1]*=1/h[:-1]
216
+
217
+
218
+
219
+ # 対角成分の一つ上の斜めの成分
220
+
201
- V = np.eye(n)*(-2)+np.eye(n, k=1)+np.eye(n, k=-1)
221
+ Vupper = np.eye(n, k=1)
222
+
223
+ Vupper[:-1,1:]*=1/h[:-1]
224
+
225
+ V = Vdiag + Vlower + Vupper
226
+
227
+
202
228
 
203
229
  V[-1][0] = h[-1]
204
230
 
@@ -278,6 +304,10 @@
278
304
 
279
305
  plt.savefig("graph.png", dpi=200,figsize=(4,3))
280
306
 
307
+
308
+
309
+
310
+
281
311
  ```
282
312
 
283
313
  ![イメージ説明](b25297d263933355338c31ffe468e743.png)

1

閉曲線verも追加

2020/07/26 05:56

投稿

Penpen7
Penpen7

スコア698

test CHANGED
@@ -127,3 +127,157 @@
127
127
  ```
128
128
 
129
129
  ![イメージ説明](97c19caa7151c4bbf2485e2189f77066.png)
130
+
131
+
132
+
133
+ 周期3次スプライン曲線を使って閉曲線にしました。
134
+
135
+ [Periodic cubic smoothing splines as a quadratic
136
+
137
+ minimization problem](http://massimozanetti.altervista.org/files/mydocs/periodicCubicSmoothSplines.pdf)
138
+
139
+ ```python
140
+
141
+ import numpy as np
142
+
143
+ import matplotlib.pyplot as plt
144
+
145
+
146
+
147
+ # 周期3次スプライン曲線のパラメータを求める。
148
+
149
+ def calculatePeriodicSplineParameter(x):
150
+
151
+ # t = 0,1,2,...,x.size-1とする。
152
+
153
+ n = x.size-1
154
+
155
+ h = np.ones(n)
156
+
157
+ a = x
158
+
159
+
160
+
161
+ # 対角成分
162
+
163
+ Adiag = np.eye(n)
164
+
165
+ Adiag[1:,1:] *= 2*(h[:-1]+h[1:])
166
+
167
+ Adiag[0][0] *= 2*(h[-1]+h[0])
168
+
169
+
170
+
171
+ # 対角成分の一つ下の斜めの成分
172
+
173
+ Alower = np.eye(n, k=-1)
174
+
175
+ Alower[1:,:-1]*=h[:-1]
176
+
177
+
178
+
179
+ # 対角成分の一つ上の斜めの成分
180
+
181
+ Aupper = np.eye(n, k=1)
182
+
183
+ Aupper[:-1,1:]*=h[:-1]
184
+
185
+ A = Adiag + Alower + Aupper
186
+
187
+
188
+
189
+ A[-1][0] = h[-1]
190
+
191
+ A[0][-1] = h[-1]
192
+
193
+
194
+
195
+ # Aの逆行列
196
+
197
+ Ainv = np.linalg.inv(A)
198
+
199
+
200
+
201
+ V = np.eye(n)*(-2)+np.eye(n, k=1)+np.eye(n, k=-1)
202
+
203
+ V[-1][0] = h[-1]
204
+
205
+ V[0][-1] = h[-1]
206
+
207
+
208
+
209
+ r = 3*np.dot(V,a[:-1])
210
+
211
+
212
+
213
+ c = np.dot(Ainv, r)
214
+
215
+
216
+
217
+ c = np.insert(c, c.size, c[0])
218
+
219
+ d = (c[1:]-c[:-1])/(3*h)
220
+
221
+ b = (a[1:]-a[:-1])/h-h/3*(2*c[:-1]+c[1:])
222
+
223
+ a = a[:-1]
224
+
225
+ c = c[:-1]
226
+
227
+ return [a,b,c,d]
228
+
229
+
230
+
231
+ # 三次関数の係数から, 元の点から間の点を求める。
232
+
233
+ def calculateInterpolationPoints(splineParameter, interpolationPointsNumber=1000):
234
+
235
+ a, b, c, d = splineParameter
236
+
237
+ assert(a.size==b.size==c.size==d.size)
238
+
239
+ index = np.repeat(np.arange(a.size), interpolationPointsNumber, axis=0)
240
+
241
+ t = np.tile(np.linspace(0, 1, interpolationPointsNumber), a.size)
242
+
243
+ return a[index] + b[index]*t + c[index]*t**2 + d[index]*t**3
244
+
245
+
246
+
247
+ # 補間したい点の座標
248
+
249
+ x = np.random.rand(10)
250
+
251
+ y = np.random.rand(x.size)
252
+
253
+ x = np.insert(x,x.size,x[0])
254
+
255
+ y = np.insert(y,y.size,y[0])
256
+
257
+
258
+
259
+ parameterX = calculatePeriodicSplineParameter(x)
260
+
261
+ parameterY = calculatePeriodicSplineParameter(y)
262
+
263
+
264
+
265
+
266
+
267
+ X = calculateInterpolationPoints(parameterX)
268
+
269
+ Y = calculateInterpolationPoints(parameterY)
270
+
271
+
272
+
273
+ plt.plot(X, Y, label="spline curve")
274
+
275
+ plt.plot(x, y, marker='o', linestyle='None', label='original points')
276
+
277
+ plt.legend()
278
+
279
+ plt.savefig("graph.png", dpi=200,figsize=(4,3))
280
+
281
+ ```
282
+
283
+ ![イメージ説明](b25297d263933355338c31ffe468e743.png)