翻译自网上博客,这里查看原文。
前几天,一个朋友问我一个来自图形应用的问题。他需要以这样一种方式绘制椭圆,使得每秒绘制出的曲线的长度是恒定的。对于圆,这个问题很简单:\((\cos(t),\sin(t))\)将绘制出一个圆,每单位时间划过一个恒定的弧长。而椭圆的类似参数化\((a\cos(t),b\sin(t))\)将在长半轴附近移动得更快,在短半轴附近移动得较慢。
有一个适用于任何曲线的通用解。给定参数化\(p(t)\),其中\(p(t)\)为向量值,则从时间\(0\)到\(t\)覆盖的曲线长度为
$$s(t) = \int_0^t \|p'(\tau)\|\mathrm{d} \tau$$
如果通过计算\(s(t)\)的反函数来更改时间参数化,将\(t\)求解为关于\(s\)的函数,那么\(t\)时间内\(p(t(s))\)划过的曲线总长度为\(s\)。这种方式被称之为单位速度参数化或者弧长参数化。
困难的部分是计算\(s(t)\)的反函数。如果你必须在微积分课上求解一个单位速度参数化,问题会被精心设计所以容易计算\(s(t)\)的反函数。实际应用中没有这么简单。
啰嗦一下椭圆积分与椭圆函数
我给朋友的回答是:可能存在一个单位速度参数化的解析解,但是可能涉及到椭圆函数。他不必要如此大费周章,并决定做点别的事情。
从参数化\((a\cos(t),b\sin(t))\)开始,弧长\(s(t)\)由一个被称之为“第二类不完全椭圆积分”的特殊函数给出。我记得Jacobi 椭圆函数与椭圆积分的反函数有关。所以我的直觉是你可以用Jacobi椭圆函数来做单位速度参数化。也许可以,但是这不是如我想象的那般容易,因为Jacobi椭圆函数与第一类椭圆积分的反函数有关。
椭圆积分之所以如此命名,是因为它们首先在计算椭圆的(部分)弧长问题中被发现。椭圆函数是在计算椭圆积分的反函数时被发现的,但与给出椭圆弧长的椭圆积分不是同一类。(很可能存在某种变换使它们之间的联系更加直接,但我不知道)。
顺便说一句,椭圆曲线与椭圆函数有关,但它们不是椭圆!椭圆和椭圆曲线之间存在联系,但这是历史的和间接的。
如果我们有一条比椭圆更普通的曲线,比如说用三次样条曲线参数化的曲线,该怎么办?三次样条曲线是分段三次多项式,以一阶和二阶导数在整个区间上连续的方式拼接在一起。我们可以通过找到每个多项式片段的长度来找到样条线的长度。
如果\(p(t)\)是二维或三维(或者实际上为任意维)曲线的参数化,并且\(p\)的每个分量都是三次多项式,则\(p\)的每个分量的导数都是二次多项式,因此各分量的平方和是四次多项式。因此,计算弧长需要对四次多项式的平方根进行积分。这使其成为椭圆积分。
不幸的是,知道三次样条的弧长对应于椭圆积分不是那么有用,因为它可以是任何类型的椭圆积分,这取决于其中的参数。你首先必须做一些前期工作才能将其放入可以调用椭圆积分的形式以完成问题。
弧长和单位速度参数化的数值计算
椭圆积分是一条死路。如果你需要高精度,或者你对感兴趣的曲线类别有一些限制,它可能仍然有用。但是通常你需要通过数值积分来计算弧长。
你还可以使用“根查找”法来计算\(s(t)\)上某个特定点的逆,从而找出单位速度参数化。由于\(s(t)\)是关于\(t\)的单调递增函数,所以可以使用二分法来求根,这不是最有效的方法但是非常的鲁棒。
求根需要大量的计算,而且每次函数求值都需要计算数值积分。但这是可行的,并且取决你的上下文,它可能足够有效。
如果你需要更高的效率,比如对于实时嵌入式系统,你可以采用不同的方法。你的样条曲线可能近似于其他事物,因此你的解决方案只需要与样条曲线近似值一样准确。这为您提供了回旋余地,使您可以更高效地执行操作。您可以稍微更改参数设置以简化弧长计算,或者根据你的具体问题和精度要求,想出一种对弧长函数近似取反的方法。
评论前必须登录!
登陆 注册