Подтвердить что ты не робот

Гладкое сплайн-представление произвольного контура, f (длина) → x, y

Предположим, что у меня есть набор координат x, y, которые отмечают точки вдоль контура. Есть ли способ, которым я могу построить сплайн-представление контура, которое я могу оценить в определенном положении по его длине, и восстановить интерполированные координаты x, y?

Часто бывает не так, что существует соответствие 1:1 между значениями X и Y, поэтому одномерные сплайны мне не подходят. Двумерные сплайны были бы точными, но насколько я могу рассказать обо всех функциях для оценки двумерных сплайнов в scipy.interpolate, возьмем значения x, y и return z, тогда как мне нужно дать z и вернуть x, y (поскольку x, y - точки на линии, причем каждый z сопоставляется с единственным x, y).

Вот эскиз того, что я хотел бы сделать:

import numpy as np
from matplotlib.pyplot import plot

# x,y coordinates of contour points, not monotonically increasing
x = np.array([ 2.,  1.,  1.,  2.,  2.,  4.,  4.,  3.])
y = np.array([ 1.,  2.,  3.,  4.,  2.,  3.,  2.,  1.])

# f: X --> Y might not be a 1:1 correspondence
plot(x,y,'-o')

# get the cumulative distance along the contour
dist = [0]
for ii in xrange(x.size-1):
    dist.append(np.sqrt((x[ii+1]-x[ii])**2 + (y[ii+1]-y[ii])**2))
d = np.array(dist)

# build a spline representation of the contour
spl = ContourSpline(x,y,d)

# resample it at smaller distance intervals
interp_d = np.linspace(d[0],d[-1],1000)
interp_x,interp_y = spl(interp_d)
4b9b3361

Ответ 1

Вы хотите использовать параметрический сплайн, где вместо интерполяции y из значений x вы устанавливаете новый параметр t и интерполируете как y, так и x из значений t, используя одномерные сплайны для обоих. Как вы назначаете значения t для каждой точки, влияет на результат, а использование расстояния, как может показаться на вашем вопросе, может быть хорошей идеей:

from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate

x = np.array([ 2.,  1.,  1.,  2.,  2.,  4.,  4.,  3.])
y = np.array([ 1.,  2.,  3.,  4.,  2.,  3.,  2.,  1.])
plt.plot(x,y, label='poly')

t = np.arange(x.shape[0], dtype=float)
t /= t[-1]
nt = np.linspace(0, 1, 100)
x1 = scipy.interpolate.spline(t, x, nt)
y1 = scipy.interpolate.spline(t, y, nt)
plt.plot(x1, y1, label='range_spline')

t = np.zeros(x.shape)
t[1:] = np.sqrt((x[1:] - x[:-1])**2 + (y[1:] - y[:-1])**2)
t = np.cumsum(t)
t /= t[-1]
x2 = scipy.interpolate.spline(t, x, nt)
y2 = scipy.interpolate.spline(t, y, nt)
plt.plot(x2, y2, label='dist_spline')

plt.legend(loc='best')
plt.show()

enter image description here

Ответ 3

Вот пример использования splprep и splev:

import numpy as np
import scipy.interpolate
from matplotlib.pyplot import plot

# x,y coordinates of contour points, not monotonically increasing
x = np.array([2.,  1.,  1.,  2.,  2.,  4.,  4.,  3.])
y = np.array([1.,  2.,  3.,  4.,  2.,  3.,  2.,  1.])

# f: X --> Y might not be a 1:1 correspondence
plot(x, y, '-o')

# get the cumulative distance along the contour
dist = np.sqrt((x[:-1] - x[1:])**2 + (y[:-1] - y[1:])**2)
dist_along = np.concatenate(([0], dist.cumsum()))

# build a spline representation of the contour
spline, u = scipy.interpolate.splprep([x, y], u=dist_along, s=0)

# resample it at smaller distance intervals
interp_d = np.linspace(dist_along[0], dist_along[-1], 50)
interp_x, interp_y = scipy.interpolate.splev(interp_d, spline)
plot(interp_x, interp_y, '-o')

Параметрический пример сплайна