Python 确定两个已知点之间具有给定弧长的抛物线

Python 确定两个已知点之间具有给定弧长的抛物线,python,geometry,curve-fitting,Python,Geometry,Curve Fitting,设(0,0)和(Xo,Yo)是笛卡尔平面上的两点。我们想要确定抛物线,Y=AX^2+BX+C,它从这两点经过,给定的弧长等于S。显然,S>sqrt(Xo^2+Yo^2)。由于曲线必须从(0,0)经过,因此它应该是C=0。因此,曲线方程简化为:Y=AX^2+BX。我如何确定{A,B}知道{Xo,Yo,S}?有两种解决方案,我想要一个>0的 我有一个解析解(复数),对于给定的一组{a,B,Xo,Yo}给出S,虽然这里的问题是相反的。。。我可以通过数值求解一个复杂的方程组。。。但也许有一个数字例程可以

设(0,0)和(Xo,Yo)是笛卡尔平面上的两点。我们想要确定抛物线,Y=AX^2+BX+C,它从这两点经过,给定的弧长等于S。显然,S>sqrt(Xo^2+Yo^2)。由于曲线必须从(0,0)经过,因此它应该是C=0。因此,曲线方程简化为:Y=AX^2+BX。我如何确定{A,B}知道{Xo,Yo,S}?有两种解决方案,我想要一个>0的

我有一个解析解(复数),对于给定的一组{a,B,Xo,Yo}给出S,虽然这里的问题是相反的。。。我可以通过数值求解一个复杂的方程组。。。但也许有一个数字例程可以做到这一点

有没有有用的Python库?其他想法

非常感谢:-)

注意,二次
a*x0^2+b*x0
的弧长(线积分)由
sqrt(1+(2ax+b)^2)
x=0
x=x0
的积分给出。求解积分时,积分值为
0.5*(I(u)-I(l))/a
,其中
u=2ax0+b
<代码>l=b;和
I(t)=0.5*(t*sqrt(1+t^2)+log(t+sqrt(1+t^2))
,是
sqrt(1+t^2)的积分

由于
y0=a*x0^2+b*x0
b=y0/x0-a*x0
。在
u
l
中替换
b
的值,
u=y0/x0+a*x0
l=y0/x0-a*x0
。在线积分(弧长)的解中替换
u
l
,我们得到弧长作为
a
的函数:

s(a) = 0.5 * (I(y0/x0 + a*x0) - I(y0/x0 - a*x0)) / a
现在我们有了弧长作为
a
的函数,我们只需要找到
a
的值,其中
s(a)=s
。这就是我最喜欢的根查找算法,the,再次发挥作用的地方

牛顿-拉斐逊求根法的工作算法如下:

对于要获得根的函数
f(x)
,如果
x(i)
是根的
i
猜测

x(i+1) = x(i) - f(x(i)) / f'(x(i))
其中
f'(x)
f(x)
的导数。这个过程一直持续到两个连续猜测之间的差值非常小为止

在我们的例子中,
f(a)=s(a)-s
f'(a)=s'(a)
。通过简单应用链式规则和商规则

s'(a) = 0.5 * (a*x0 * (I'(u) + I'(l)) + I(l) - I(u)) / (a^2)
其中
I'(t)=sqrt(1+t^2)

剩下的唯一问题是计算一个好的初始猜测。由于函数的性质,该函数是牛顿-拉斐逊法的最佳候选函数,
y0/x0
的初始猜测在大约5-6次迭代中收敛到
1e-10
的公差/ε

一旦找到
a
的值,
b
就是
y0/x0-a*x0

将其转化为代码:

def find_coeff(x0, y0, s0):
    def dI(t):
        return sqrt(1 + t*t)

    def I(t):
        rt = sqrt(1 + t*t)
        return 0.5 * (t * rt + log(t + rt))

    def s(a):
        u = y0/x0 + a*x0
        l = y0/x0 - a*x0
        return 0.5 * (I(u) - I(l)) / a

    def ds(a):
        u = y0/x0 + a*x0
        l = y0/x0 - a*x0
        return 0.5 * (a*x0 * (dI(u) + dI(l)) + I(l) - I(u)) / (a*a)

    N = 1000
    EPSILON = 1e-10
    guess = y0 / x0

    for i in range(N):
        dguess = (s(guess) - s0) / ds(guess)
        guess -= dguess
        if abs(dguess) <= EPSILON:
            print("Break:", abs((s(guess) - s0)))
            break
        print(i+1, ":", guess)

    a = guess
    b = y0/x0 - a*x0

    print(a, b, s(a))
def find_coeff(x0,y0,s0):
def dI(t):
返回sqrt(1+t*t)
定义I(t):
rt=sqrt(1+t*t)
返回0.5*(t*rt+log(t+rt))
def s(a):
u=y0/x0+a*x0
l=y0/x0-a*x0
返回0.5*(I(u)-I(l))/a
def ds(a):
u=y0/x0+a*x0
l=y0/x0-a*x0
返回0.5*(a*x0*(dI(u)+dI(l))+I(l)-I(u))/(a*a)
N=1000
ε=1e-10
猜测=y0/x0
对于范围(N)中的i:
dguess=(s(猜测)-s0)/ds(猜测)
猜测-=dguess

如果abs(dguess)@ReblochonMasque不一定。任何通过原点的多项式都有
x-0
或简单地
x
作为根。因此它不能有一个独立于
x
的常数项。通过
S
弧长,我假设你的意思是
0,0
x0,y0
形成的弧长是
S
?对我来说,这似乎更像是一个数学问题,而不是编程问题。试着先在纸上算出解析解?你读过吗?在那一节的命名法中,你知道s和p,并想计算f,作为第一步。那里的方程对我来说似乎是非常超越的,所以我不希望得到一个精确的公式。不同的numeric方法可能值得尝试。如果你有
(A,B,x0,y0)->S0
,并且不容易反转,这是一个简单的2D最小化问题,你想最小化“abs(S-S0)”,所以你可以尝试一个简单的最小二乘算法……实际上它是1D,因为你有它必须通过的点的限制