2012-04-26 156 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)