2012-04-26 62 views
0

我有一個參數化的2D曲線找到一個給定電弧距離的位置: (X,Y)= F(T)沿着在python參數化曲線

函數f是任意的,但可微,因此我可以使用標準公式計算任意點沿曲線的微分弧長ds。通過數值積分微分電弧長度公式,我還可以從曲線的起點到曲線上的任意點得到總弧長S(t)。我可以控制計算的準確性。

我想找到找到具有一個總弧長S = d從曲線的開始點(X,Y)。更好的是如果實現是在python中。我會多次這樣做,它是計算應用程序的一部分,我需要嚴格控制準確性和融合的信心。

我不知道發現根是否是最好的方法,但我的問題是g(t)= S(t) - D的根發現問題的等價物,其中函數g(t)未被評估正是因爲S(t)不是。不精確的功能評估混亂不僅與準確性,而且g(t)的單調性。我從一開始就試圖進行緊密的數值積分,但這需要永遠。我非常肯定會收斂到我所要求的容忍度,根發現算法將不得不懶惰地控制整合精度,因爲它一開始就要求潦草的評估,並且隨着根算法的收斂而提高準確性。

是否有這樣的事情現成的?有沒有其他聰明的方法來做到這一點?

欣賞幫助

+0

只是想了解情況:t是時間吧?您的知識是:開始時間,開始位置,結束時間和結束曲線長度(t0,x0,y0,tF,S(tF)= D)。你想找到那個位移的最後位置,(xF,yF)。你能否把曲線寫成一個明確的x函數,即:y = h(x)? – fraxel 2012-04-26 09:58:37

+0

喜fraxel:t只是一個虛擬變量參數化曲線。我不認爲它隨着時間的推移而產生任何傷害。順便說一下,我認爲HYRY通過發佈代碼來幫助我,這些代碼完全說明了我的方法。 – 2012-04-26 16:31:43

+0

但是..你可以消除t並得到一個明確的函數在x中,即:y = h(x)? (可以假設你可以)如果是這樣,我可能有一個很酷的方式來做到這一點。 – fraxel 2012-04-27 06:31:10

回答

2

您可以發佈一些代碼,並告訴我們它有什麼問題嗎?

這裏是我的版本,計算t其中S(T)== d:

from scipy.integrate import quad 
from scipy.optimize import fsolve 
from math import cos, sin, sqrt, pi 

def circle_diff(t): 
    dx = -sin(t) 
    dy = cos(t) 
    return sqrt(dx*dx+dy*dy) 

def sin_diff(t): 
    dx = 1 
    dy = cos(t) 
    return sqrt(dx*dx+dy*dy) 

def curve_length(t0, S, length): 
    return quad(S, 0, t0)[0] - length 

def solve_t(curve_diff, length):  
    return fsolve(curve_length, 0.0, (curve_diff, length))[0] 

print solve_t(circle_diff, 2*pi) 
print solve_t(sin_diff, 7.640395578) 
0

OK,@HYRY,這裏主要是基於你的代碼片段。你給了我成功所需的提示:使用「quad」而不是「quadrature」。所以我至少會爲你的答案投票,但我想補充一點。

首先,你的代碼跑得快,而是五個地方短的精確度我了。我將quadtol和opttol添加到您的示例中,試圖說明正交和根查找精度的相互影響。我還添加了一個基於默認高公差的循環來顯示速度差異。

罪示例比對精度的圓敏感得多。我還添加了一條曲線,曲線的弧長由超幾何函數給出,「brentq」選項註釋掉,因爲在這個例子中,fsolve失敗,甚至在任何brentq中,這個任務都是相等或更好的。

「積分」是緩慢的,但表現出預期的行爲:求根速度,精度和成功的改變與正交寬容。

相比之下,「四邊形」似乎忽略了要求的容差並始終產生更準確的答案。這個未被證實的準確性會令人討厭或者引起一些解釋,除非它對於例子的運行速度如此之快,以至於我不能確定我的問題是否有趣。謝謝!

from scipy.integrate import quad, quadrature 
from scipy.optimize import fsolve, brentq 
from math import cos, sin, sqrt, pi, pow 

def circle_diff(t): 
    dx = -sin(t) 
    dy = cos(t) 
    return sqrt(dx*dx+dy*dy) 

def sin_diff(t): 
    dx = 1 
    dy = cos(t) 
    return sqrt(dx*dx+dy*dy) 

def hypergeom_diff(t): 
    """ y = t^5 x = t^3 """ 
    dx = 3*t*t 
    dy = 5*pow(t,4) 
    return sqrt(dx*dx+dy*dy) 

def curve_length(t0, S, length,quadtol): 
    integral = quad(S, 0, t0,epsabs=quadtol,epsrel=quadtol) 
    #integral = quadrature(S, 0, t0,tol=quadtol,rtol=quadtol, vec_func = False) 
    return integral[0] - length 

def solve_t(curve_diff, length,opttol=1.e-15,quadtol=1e-10): 
    return fsolve(curve_length, 0.0, (curve_diff, length,quadtol), xtol = opttol)[0] 
    #return brentq(curve_length, 0.0, 3.2*pi,(curve_diff, length, quadtol), rtol = opttol) 

for i in range(1000): 
    y = solve_t(circle_diff, 2*pi) 

print 2*pi 
print solve_t(circle_diff, 2*pi) 
print solve_t(sin_diff, 7.640395578) 
print solve_t(circle_diff, 2*pi,opttol=1e-5,quadtol=1e-3) 
print solve_t(sin_diff, 7.640395578,opttol = 1e-12,quadtol=1e-6) 
print "hypergeom" 
print solve_t(hypergeom_diff, 2.0,opttol = 1e-12,quadtol=1e-12) 
print solve_t(hypergeom_diff, 2.0,opttol = 1e-12,quadtol=1e-6)