2013-01-15 11 views
12

Załóżmy, że mam zestaw współrzędnych x, y, które zaznaczają punkty wzdłuż konturu. Czy istnieje sposób, w jaki mogę zbudować reprezentację konturu krzywej, którą mogę ocenić w określonej pozycji wzdłuż jej długości i odzyskać interpolowane współrzędne X, Y?Gładka reprezentacja splajnu dowolnego konturu, f (długość) -> x, y

Często nie jest tak, że istnieje zgodność 1: 1 między wartościami X i Y, więc jednowymiarowe splajny nie są dla mnie dobre. Warianty dwuwymiarowe byłyby w porządku, ale o ile mogę powiedzieć, wszystkie funkcje do oceny binarnych splajnów w scipy.interpolate pobierają x, y wartości i zwracają z, podczas gdy ja muszę podać z i zwracać x, y (ponieważ x, y to punkty na linii każdy z mapuje na unikalny x, y).

Oto szkic tego, co chciałbym być w stanie to zrobić:

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) 
+0

Nie rozumiem, w jaki sposób '' y' x' i tablice nie mogą mieć w stosunku 1: 1 korespondencja i wciąż definiuj punkty na krzywej ... Czy mógłbyś spróbować wyjaśnić, co masz na myśli na przykładzie? – Jaime

+0

spróbuj naszkicować moje przykładowe współrzędne - w tym przypadku linia zakrzywia się na siebie, więc nie może być unikalnego odwzorowania z X -> Y lub z Y -> X –

Odpowiedz

22

Chcesz używać parametrycznego splajn, gdzie zamiast interpolację y od wartości x, skonfigurować nowy parametr , t i interpoluj zarówno y i x z wartości t, używając jednowymiarowych splajnów dla obu. Jak przypisać t wartości każdego punktu wpływa na wynik, a przy użyciu dystansu, jak Twoje pytanie sugeruje, może być dobrym pomysłem:

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

+1

ZOMG tak łatwe w Pythonie, musiałem napisać własne Implementacja Catmull-Rom w Ruby ...:/good stuff – aledalgrande

+0

@Jaime To bardzo interesująca technika, dziękuję! Jakie mogą być inne rozsądne wartości dla t, oprócz dist_spline? Gdzie mogę przeczytać o tym więcej? Z jakiegoś powodu metoda spline nie jest udokumentowana w scipy: http://docs.scipy.org/doc/scipy-0.16.1/reference/interpolate.html – baltazar

+1

@baltazar Możesz przeczytać o [równaniach parametrycznych] (https: //en.wikipedia.org/wiki/Parametric_equation) krzywych. W kontekście różniczkowej geometrii krzywych parametryzacja przez długość krzywej, która jest podobna do odległości, ma pewne szczególne właściwości, które prowadzą do tego, że jest nazywana [naturalną parametryzacją] (https://en.wikipedia.org/ wiki/Differential_geometry_of_curves # Length_and_natural_parametrization). Inną oczywistą opcją dla parametru jest kąt wokół punktu środkowego, jeśli twój zestaw danych ma odpowiednią geometrię. – Jaime

1

Oto przykład przy użyciu splprep i 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') 

Parametric spline example

Powiązane problemy