Formula derivation and code realization of B-spline curve

This article only briefly describes the derivation of the formula of the B-spline curve, and gives a code implementation. Before reading this article, make sure you have some background knowledge of B-spline curves. Relevant knowledge can be learned through the following courses: MOOC-Computer Graphics-China Agricultural University-Zhao Ming or watch the port version of Station B.

formula definition

Given the following parameters:

  • n + 1 n+1 n+1 control pointP i ( i = 0 , 1 , ⋯ , n ) P_i(i=0,1,\cdots,n)Pi(i=0,1,,n)
  • n + k + 1 ( 2 ⩽ k ⩽ n + 1 ) n+k+1(2\leqslant k\leqslant n+1) n+k+1(2kn+1 ) Numbers:{ ui ∣ i = 0 , 1 , ⋯ , n + k } \{u_i|i=0,1,\cdots,n+k\}{ uii=0,1,,n+k}

Structure polynomial function
P ( u ) = ∑ i = 0 n P i B i , k ( u ) , u ∈ [ uk − 1 , un + 1 ] (1) \mathcal{P}(u)=\sum_{i =0}^{n}P_i B_{i,k}(u), \quad u\in[u_{k-1},u_{n+1}] \tag{1}P(u)=i=0nPiBi,k(u),u[uk1,un+1]( 1 ) to approximate the curve. whereB i , k ( u ) B_{i,k}(u)Bi,k( u ) is calledkkk order (k − 1 k-1k1次)B样条基函数,它是由DeBoor-Cox递推公式来定义的:
B i , 1 ( u ) = { 1 , u i ⩽ u < u i + 1 0 , o t h e r w i s e   , B i , k ( u ) = u − u i u i + k − 1 − u i B i , k − 1 ( u ) + u i + k − u u i + k − u i + 1 B i + 1 , k − 1 ( u )   。 (2) \begin{alignedat}{3} & B_{i,1}(u) = \begin{cases} 1, & u_i\leqslant u < u_{i+1} \\ 0, & otherwise \end{cases} \thinspace, \\ & B_{i,k}(u) = \frac{u-u_i}{u_{i+k-1}-u_i} B_{i,k-1}(u) + \frac{u_{i+k}-u}{u_{i+k}-u_{i+1}} B_{i+1,k-1}(u) \thinspace。 \end{alignedat} \tag{2} Bi,1(u)={ 1,0,uiu<ui+1otherwiseBi,k(u)=ui+k1uiuuiBi,k1(u)+ui+kui+1ui+kuBi+1,k1(u)( 2 ) If 0 0is encountered in the recursive formula0 divided by0 00 , the result of the division is0 00

B i , k ( u ) B_{i,k}(u) Bi,k( u ) can be regarded as the control pointP i P_iPiin uuThe weight under u , because the B-spline basis function has weight:
∑ i = 0 n B i , k ( u ) ≡ 1 , ∀ u . (3) \sum_{i=0}^{n} B_{i,k}(u) \equiv 1, \quad \forall u \thinspace. \tag{3}i=0nBi,k(u)1,u(3)

对于某个u ∈ [ uj , uj + 1 ) u\in [u_j, u_{j+1})u[uj,uj+1) , use formula (2) to deduceB i , k ( u ) B_{i,k}(u)Bi,k( u ) , so that the final result only containsB x , 1 ( u ) B_{x,1}(u)Bx,1( u ) , we can derivex = i , i + 1 , ⋯ , i + k − 1 x=i,i+1,\cdots,i+k-1x=i,i+1,,i+k1 . And according toB x , 1 ( u ) B_{x,1}(u)Bx,1( u ) definition (2), we find that only whenj ∈ { i , i + 1 , ⋯ i + k − 1 } j\in\{i,i+1,\cdots i+k-1\}j{ i,i+1,i+k1},即 i ∈ { j − ( k − 1 ) , ⋯   , j } i\in\{j-(k-1),\cdots,j\} i{ j(k1),,j}时, B i , k ( u ) B_{i,k}(u) Bi,k( u ) may not be 0.

Let me explain with an example. With i = 7 , k = 3 i=7,k=3i=7,k=3 as an example, use formula (2) to deduceB 7 , 3 ( u ) B_{7,3}(u)B7,3(u)
B 7 , 3 ( u ) = c 0 B 7 , 2 ( u ) + c 1 B 8 , 2 ( u ) = c 2 B 7 , 1 ( u ) + c 3 B 8 , 1 ( u ) + c 4 B 9 , 1 ( u ) \begin{aligned} B_{7,3}(u) &= c_0B_{7,2}(u)+c_1B_{8,2}(u) \\ &= c_2B_{7,1}(u)+c_3B_{8,1}(u)+c_4B_{9,1}(u) \end{aligned} B7,3(u)=c0B7,2(u)+c1B8,2(u)=c2B7,1(u)+c3B8,1(u)+c4B9,1(u)(where c 0 , c 1 , ⋯ , c 4 c_0,c_1,\cdots,c_4c0,c1,,c4are coefficients), we found that the final result only contains B 7 , 1 ( u ) , B 8 , 1 ( u ) , B 9 , 1 ( u ) B_{7,1}(u), B_{8, 1}(u),B_{9,1}(u)B7,1(u),B8,1(u),B9,1( u )。对于某个u ∈ [ uj , uj + 1 ) u\in [u_j, u_{j+1})u[uj,uj+1) , only whenj ∈ { 7 , 8 , 9 } j\in\{7,8,9\}j{ 7,8,9} B 7 , 1 ( u ) , B 8 , 1 ( u ) , B 9 , 1 ( u ) B_{7,1}(u), B_{8,1}(u),B_{9,1}(u) B7,1(u),B8,1(u),B9,1( u ) are not all 0, so thatB 7 , 3 ( u ) B_{7,3}(u)B7,3( u ) may not be 0.

Algorithm principle

对于某个u ∈ [ uj , uj + 1 ] u\in [u_j, u_{j+1}]u[uj,uj+1] , we define
di , 0 = P i , i = j − ( k − 1 ) , ⋯ , j , (4) d_{i,0} = P_i,\quad i = j-(k-1),\ cdots,j \thinspace,\tag{4}di,0=Pi,i=j(k1),,j(4) α i , r = u − u i u i + k − r − u i , d i , r = ( 1 − α i , r ) d i − 1 , r − 1 + α i , r d i , r − 1 ( r = 1 , 2 , ⋯   , k − 1 i = j − ( k − 1 ) + r , ⋯   , j )   。 (5) \begin{alignedat}{3} \alpha_{i,r} &= \frac{u-u_i}{u_{i+k-r}-u_i}, \\ d_{i,r} &= (1-\alpha_{i,r})d_{i-1,r-1}+\alpha_{i,r}d_{i,r-1} \end{alignedat} \left(\begin{array}{l} r = 1,2,\cdots,k-1 \\ i = j-(k-1)+r,\cdots,j \end{array}\right) \thinspace。 \tag{5} ai,rdi,r=ui+kruiuui,=(1ai,r)di1,r1+ai,rdi,r1(r=1,2,,k1i=j(k1)+r,,j)(5)

Here, for i = j − ( k − 1 ) + r in formula (5) , ⋯ , ji = j-(k-1)+r,\cdots,ji=j(k1)+r,,j makes an explanation: recursivelydi , r d_{i,r}di,rMake the final result only contain dx , 0 d_{x,0}dx,0,得到 x = i − r , ⋯   , i x=i-r,\cdots,i x=ir,,i . bydx , 0 d_{x,0}dx,0The definition formula (4) knows, ∀ x , x ∈ { j − ( k − 1 ) , ⋯ , j } \forall x, x\in\{j-(k-1),\cdots,j\}x,x{ j(k1),,j}。因此有 i − r ∈ { j − ( k − 1 ) , ⋯   , j } , ⋯   , i ∈ { j − ( k − 1 ) , ⋯   , j } i-r\in\{j-(k-1),\cdots,j\},\cdots,i\in\{j-(k-1),\cdots,j\} ir{ j(k1),,j},,i{ j(k1),,j } , so thati ∈ { j − ( k − 1 ) + r , ⋯ , j } i\in\{j-(k-1)+r,\cdots,j\}i{ j(k1)+r,,j}

It can be proved that
P ( u ) = dj , k − 1 . (6) \mathcal{P}(u) = d_{j,k-1} \thinspace. \tag{6}P(u)=dj,k1(6)

So the logic of the algorithm is as follows (assuming that the input only provides n + 1 n+1n+1 control point, parameterui ( i ∈ { 0 , 1 , ⋯ , n + k } ) u_i(i\in\{0,1,\cdots,n+k\})ui(i{ 0,1,,n+k } ) is selected by us):

  • Take any interval in the real number field, you might as well take [0, 1] [0,1][0,1]
  • will [0, 1] [0,1][0,1 ] evenly spaced asn + k n+kn+k segment (number of control points =n + 1 n+1n+1 , curve order =kkk)。
  • After separation, n + k + 1 n+k+1 is generatedn+k+1 separation point, recorded asu 0 , u 1 , ⋯ , un + k u_0,u_1,\cdots,u_{n+k}u0,u1,,un+k. So uj = j / ( n + k ) u_j=j/(n+k)uj=d / ( n+k)
  • interval [ uk − 1 , un + 1 ] [u_{k-1},u_{n+1}][uk1,un+1] on a large number of samples. For each sampleuuu , computationP ( u ) \mathcal{P}(u)P(u)
  • According to formula (6), we can calculate dj , k − 1 d_{j,k-1}dj,k1To calculate P ( u ) \mathcal{P}(u)P(u)
  • d j , k − 1 d_{j,k-1} dj,k1It can be calculated recursively by formula (5).

Algorithm implementation

def draw_curve(p_list, k: int = 4):
	"""
    :param p_list: (list of list of int: [[x0, y0], [x1, y1], [x2, y2], ...]) 曲线的控制点坐标列表
    :param k: B样条曲线的阶数,默认为4阶,即3次均匀B样条曲线
    :return: (list of list of int: [[x_0, y_0], [x_1, y_1], [x_2, y_2], ...]) 绘制结果的像素点坐标列表
    """
    n = len(p_list) - 1
    if n == 0:
        return p_list
    elif n == 1:
        return draw_line(p_list) # 调用绘制直线的算法
        
    assert 2 <= k <= n + 1
    freq = 500
    result = []
    
    for j in range(k - 1, n + 1):
        seg = n + k
        u_j = j / seg
        for u in range(freq + 1):
            u = u / (freq * seg) + u_j
            tmp = [
                [p_list[i + j - (k-1)][0],
                 p_list[i + j - (k-1)][1]
                ] for i in range(k)
            ]
            for r in range(1, k):
                for i in range(k - 1, r - 1, -1):
                    ii = i + j - (k - 1)
                    u_i = ii / seg
                    alpha = (u - u_i) / ((ii+k-r)/seg - u_i)
                    tmp[i] = [
                        (1-alpha)*tmp[i-1][0] + alpha*tmp[i][0],
                        (1-alpha)*tmp[i-1][1] + alpha*tmp[i][1]
                    ]
            result.append(
                [round(tmp[k-1][0]), round(tmp[k-1][1])]
            )
    return result

Supplement: P ( u ) \mathcal{P}(u)Derivation of P ( u ) Domain

In formula (1), we directly define the variable uuThe value range of u is [ uk − 1 , un + 1 ] [u_{k-1},u_{n+1}][uk1,un+1] . In this section we will explain its principle in detail.

According to the recursive formula (2), we can infer:

  • B i , 1 B_{i,1} Bi,1and 1 interval ( [ ui , ui + 1 ] [u_i,u_{i+1}][ui,ui+1] ) 2 control points (ui u_iuisum ui + 1 u_{i+1}ui+1
  • B i , 2 B_{i,2} Bi,2Reason B i , 1 B_{i,1}Bi,1sum B i + 1 , 1 B_{i+1,1}Bi+1,1Composition, involving 2 intervals and 3 control points
  • B i , 3 B_{i,3} Bi,3Reason B i , 2 B_{i,2}Bi,2Sum B i + 1 , 2 B_{i+1,2}Bi+1,2Composition, involving 3 intervals and 4 control points
  • ⋯ \cdots
  • B i , k B_{i,k} Bi,kinvolving kkk intervalsk + 1 k+1k+1 control point

Thus it is possible to define B i , k B_{i,k}Bi,ksupport interval is [ ui , ui + k ] [u_i,u_{i+k}][ui,ui+k]

control point-support interval
For example, as shown above , where n = 4, k = 4 n=4,k=4n=4,k=4 . According to the definition of the support interval, we have:

  • P 0 B 0 , 4 P_0B_{0,4} P0B0,4Involves node u 0 u_0u0to u 4 u_4u4
  • P 1 B 1 , 4 P_1B_{1,4} P1B1,4Involving node u 1 u_1u1to u 5 u_5u5
  • ⋯ \cdots
  • P 4 B 4 , 4 P_4B_{4,4} P4B4,4Involving node u 4 u_4u4to u 8 u_8u8

For each interval [ ui , ui + 1 ] [u_i,u_{i+1}][ui,ui+1] , which contains at mostkkIn k different support intervals, that is, it is at mostkkK control points are related. The figure belowgraphically demonstrates this relationship.
insert image description here
Our goal is, forP ( u ) \mathcal{P}(u)Each interval in the domain of P ( u ) should be related to as many control points as possible. So we finally chose[ uk − 1 , un + 1 ] [u_{k-1},u_{n+1}][uk1,un+1] . possible,∀ [ ui , ui + 1 ] ⊆ [ uk − 1 , un + 1 ] \forall [u_i,u_{i+1}]\subseteq [u_{k-1},u_{n+1}][ui,ui+1][uk1,un+1] [ u i , u i + 1 ] [u_i,u_{i+1}] [ui,ui+1] both withkkK control points are related.

more details

Due to space limitations, some proofs are not described in detail in this paper. More proof details can be found in the related paper. For example C. DE BOOR, On calculating with B-splines , 1972 , etc.

Guess you like

Origin blog.csdn.net/Qmj2333333/article/details/123528666