如何使用Python、NumPy和SciPy集成弧长?

3

在另一个帖子中,我看到有人使用Mathematica成功地计算了椭圆弧长。他们写道:

In[1]:= ArcTan[3.05*Tan[5Pi/18]/2.23]
Out[1]= 1.02051
In[2]:= x=3.05 Cos[t];
In[3]:= y=2.23 Sin[t];
In[4]:= NIntegrate[Sqrt[D[x,t]^2+D[y,t]^2],{t,0,1.02051}]
Out[4]= 2.53143

如何利用numpy和scipy的导入将此转换为Python?特别是,我在他的代码第四行卡住了,“NIntegrate”函数。感谢您的帮助!

此外,如果我已经知道弧长和垂直轴长度,如何将程序反向运行以输出原始参数?谢谢!

2个回答

4
如果您更喜欢纯数值方法,可以使用以下简单的解决方案。这对我来说效果很好,因为我有两个输入的numpy.ndarray,即x和y,没有可用的函数形式。
import numpy as np

def arclength(x, y, a, b):
    """
    Computes the arclength of the given curve
    defined by (x0, y0), (x1, y1) ... (xn, yn)
    over the provided bounds, `a` and `b`.

    Parameters
    ----------
    x: numpy.ndarray
        The array of x values

    y: numpy.ndarray
        The array of y values corresponding to each value of x

    a: int
        The lower limit to integrate from

    b: int
        The upper limit to integrate to

    Returns
    -------
    numpy.float64
        The arclength of the curve

    """
    bounds = (x >= a) & (y <= b)

    return np.trapz(
        np.sqrt(
            1 + np.gradient(y[bounds], x[bounds])
        ) ** 2),
        x[bounds]
    )

注意:我将返回变量分开排列,只是为了使操作更易于阅读和理解。
顺便提一下,记得曲线的弧长由以下公式给出:

Arc-length Equation


太好了,谢谢!在我看来(对于我的应用程序),比符号Sympy方法好多了。 - Colton Campbell

4
据我所知,scipy无法进行符号计算(例如符号微分)。你可能需要查看http://www.sympy.org关于符号计算的包。因此,在下面的示例中,我通过解析计算导数(Dx(t)Dy(t)函数)。
>>> from scipy.integrate import quad
>>> import numpy as np
>>> Dx = lambda t: -3.05 * np.sin(t)
>>> Dy = lambda t: 2.23 * np.cos(t)
>>> quad(lambda t: np.sqrt(Dx(t)**2 + Dy(t)**2), 0, 1.02051)
(2.531432761012828, 2.810454936566873e-14)

编辑:问题的第二部分 - 反转问题

通过已知积分(弧)的值,您现在可以解出确定弧的参数之一(半轴、角度等)。假设您想解出角度,则可以使用scipy中的非线性求解器之一来反转方程quad(theta) - arcval == 0。您可以按照以下方式进行:

>>> from scipy.integrate import quad
>>> from scipy.optimize import broyden1
>>> import numpy as np
>>> a = 3.05
>>> b = 2.23
>>> Dx = lambda t: -a * np.sin(t)
>>> Dy = lambda t: b * np.cos(t)
>>> arc = lambda theta: quad(lambda t: np.sqrt(Dx(t)**2 + Dy(t)**2), 0, np.arctan((a / b) * np.tan(np.deg2rad(theta))))[0]
>>> invert = lambda arcval: float(broyden1(lambda x: arc(x) - arcval, np.rad2deg(arcval / np.sqrt((a**2 + b**2) / 2.0))))

然后:

>>> arc(50)
2.531419526553662
>>> invert(arc(50))
50.000031008458365

非常感谢您的回复!对不起,我只有一个关于 quad 函数的问题。如果我已经有了 2.5314327 的弧长,我该如何在代码中反转这个函数呢?谢谢! - Fairly Factual
@FairlyFactual,“reversing”是什么意思?这是一个定积分。我猜你想解方程quad(某些内容)== 2.53...。问题是:你想解决什么? - AGN Gazer
@FairlyFactual 我在我的答案中添加了我尝试解决你的“反向问题”的方式,就我理解的方式。 - AGN Gazer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接