使用De Boor算法的B样条导数

时间:2019-08-15 09:37:01

标签: python algorithm interpolation bspline

Wikipedia为我们提供了De Boor算法的Python实现:

public class App {
    public static void main(String[] args) throws Exception {
        /** I write the code when 2019-8-15 */
        LocalDate now = LocalDate.now();
        LocalDate startWork = LocalDate.parse("2019-06-17");
        /** get all days */
        long allDays = Duration.between(startWork.atStartOfDay(), now.atStartOfDay()).toDays() + 1;
        System.out.println("This is the " + allDays + "th day you enter the company.");
        /** variable to store day except sunday and saturday */
        long workDays = allDays;

        for (int i = 0; i < allDays; i++) {

            if (startWork.getDayOfWeek() == DayOfWeek.SATURDAY || startWork.getDayOfWeek() == DayOfWeek.SUNDAY) {
                workDays--;
            }

            startWork = startWork.plusDays(1);
        }

        System.out.println("You actually work for a total of " + workDays + " days.");

    }
}
/**
This is the 60th day you enter the company.
You actually work for a total of 44 days.
*/

是否存在类似的算法来计算B样条曲线插值曲线的导数(甚至是n阶导数)?

我知道从数学上讲,它可以简化为使用低阶样条,但不能将其应用于de Boor算法。

2 个答案:

答案 0 :(得分:1)

如果要同时计算值和它的导数,则用元组 x 的值 v 是合理的>(v,dv / dx)

然后,当您对它们求和和乘积规则相加或相乘时,就可以应用它们:https://en.wikipedia.org/wiki/Product_rule

您提供的功能将变成这样,例如:

def deBoorWithDerivative(k, x, t, c, p):
    """
    Evaluates (S(x), dS(x)/dx).

    Args
    ----
    k: index of knot interval that contains x
    x: position
    t: array of knot positions, needs to be padded as described above
    c: array of control points
    p: degree of B-spline
    """
    d = [(c[j + k - p],0) for j in range(0, p+1)]

    for r in range(1, p+1):
        for j in range(p, r-1, -1):
            dalpha = 1.0/(t[j+1+k-r] - t[j+k-p])
            alpha = (x - t[j+k-p]) * dalpha
            d[j] = ( (1.0 - alpha) * d[j-1][0] + alpha * d[j][0],
              -dalpha * d[j-1][0] + (1.0 - alpha) * d[j-1][1]
              +dalpha * d[j][0] + alpha*d[j][1] )

    return d[p]

答案 1 :(得分:1)

我认为我找到了重新使用de Boor算法进行曲线导数的正确方法。

首先,我们考虑B样条曲线的定义。它是控制点的线性组合: curve(1)

因此,导数是基函数导数的线性组合

curve(2)

基函数的导数定义如下:

curve(3)

我们将(3)插入(2),然后经过http://public.vrac.iastate.edu/~oliver/courses/me625/week5b.pdf这里描述的一些代数功夫,我们得到:

curve(4), curve

B样条曲线的导数不过是在新控制点Q之上建立的(p-1)度的新B样条曲线。 现在,使用de Boor算法,我们计算出新的控制点集并将样条曲线度p降低1:

def deBoorDerivative(k, x, t, c, p):
    """
    Evaluates S(x).

    Args
    ----
    k: index of knot interval that contains x
    x: position
    t: array of knot positions, needs to be padded as described above
    c: array of control points
    p: degree of B-spline
    """
    q = [p * (c[j+k-p+1] - c[j+k-p]) / (t[j+k+1] - t[j+k-p+1]) for j in range(0, p)]

    for r in range(1, p):
        for j in range(p-1, r-1, -1):
            right = j+1+k-r
            left = j+k-(p-1)
            alpha = (x - t[left]) / (t[right] - t[left])
            q[j] = (1.0 - alpha) * q[j-1] + alpha * q[j]

    return q[p-1]

测试:

import numpy as np
import math as m

points = np.array([[i, m.sin(i / 3.0), m.cos(i / 2)] for i in range(0, 11)])
knots = np.array([0, 0, 0, 0, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.0, 1.0, 1.0, 1.0])


def finiteDifferenceDerivative(k, x, t, c, p):
    """ Third order finite difference derivative """

    f = lambda xx : deBoor(k, xx, t, c, p)

    dx = 1e-7

    return (- f(x + 2 * dx) \
            + 8 * f(x + dx) \
            - 8 * f(x - dx) \
            + f(x - 2 * dx)) / ( 12 * dx )


print "Derivatives: "·
print "De Boor:\t", deBoorDerivative(7, 0.44, knots, points, 3)
print "Finite Difference:\t", finiteDifferenceDerivative(7, 0.44, knots, points, 3)

输出:

Derivatives: 
De Boor:              [10. 0.36134438  2.63969004]
Finite Difference:    [9.99999999 0.36134438 2.63969004]