Formula derivation and code implementation of Bezier curve

This article only briefly describes the formula derivation of the Bezier curve, and gives a code implementation. Before reading this article, please make sure you have some background knowledge of Bezier 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.

Algorithm principle

Given n + 1 n+1n+1 control pointP i ( i = 0 , 1 , ⋯ , n ) P_i(i=0,1,\cdots,n)Pi(i=0,1,,n ) , structure polynomial function
P ( u ) = ∑ i = 0 n P i ⋅ BEZ i , n ( u ) , 0 ⩽ u ⩽ 1 , (1) \mathcal{P}(u)=\sum_{i= 0}^{n}P_i\cdot BEZ_{i,n}(u), \quad 0\leqslant u\leqslant 1 \thinspace, \tag{1}P(u)=i=0nPiB E Zi,n(u),0u1( 1 )
Approach curve. Among them,BEZ i , n ( u ) BEZ_{i,n}(u)B E Zi,n( u ) callednnn次Bernstein基函数,且有
B E Z i , n ( u ) = C n i u i ( 1 − u ) n − i , ( i = 0 , 1 , ⋯   , n u ∈ [ 0 , 1 ] )   。 (2) BEZ_{i,n}(u)=C_n^i u^i(1-u)^{n-i}, \quad \left(\begin{array}{l} i=0,1,\cdots,n \\ u\in[0,1] \end{array}\right) \thinspace。 \tag{2} B E Zi,n(u)=Cniui(1u)ni,(i=0,1,,nu[0,1])(2)

For formula (1), the function P ( u ) \mathcal{P}(u)P ( u ) converts the real number interval[ 0 , 1 ] [0,1][0,1 ] is mapped to the point set on the real number field, and the points in the point set form the approximate curve sought. BEZ i , n ( u ) BEZ_{i,n}(u)B E Zi,n( u ) can be regarded as the control pointP i P_iPiin uuThe weight under u . BecauseBEZ i , n ( u ) BEZ_{i,n}(u)B E Zi,n(u)具有权性:
∑ i = 0 n B E Z i , n ( u ) ≡ 1 , ∀ u ∈ ( 0 , 1 )   。 (3) \sum_{i=0}^{n} BEZ_{i,n}(u) \equiv 1, \quad \forall u\in(0,1) \thinspace。\tag{3} i=0nB E Zi,n(u)1,u(0,1)(3)

我们定义:
β i ( r ) = { P i , r = 0 ( 1 − u ) β i ( r − 1 ) + u β i + 1 ( r − 1 ) , r = 1 , 2 , ⋯   , n   , (4) \beta_{i}^{(r)} = \begin{cases} P_i, & r = 0 \\ (1-u)\beta_{i}^{(r-1)} + u\beta_{i+1}^{(r-1)}, & r = 1,2,\cdots,n \end{cases} \thinspace, \tag{4} bi(r)={ Pi,(1u ) bi(r1)+uβi+1(r1),r=0r=1,2,,n( 4 )
i = 0 , 1 , ⋯ , n− ri=0,1,\cdots,nri=0,1,,nr

It can be proved (see Wikipedia De Casteljau algorithm for the proof process ):
P ( u ) = ∑ i = 0 n β i ( 0 ) ⋅ BEZ i , n ( u ) = β 0 ( n ) . (5) \mathcal{P}(u) = \sum_{i=0}^{n} \beta_{i}^{(0)}\cdot BEZ_{i,n}(u) = \beta_{0 }^{(n)} \thinspace. \tag{5}P(u)=i=0nbi(0)B E Zi,n(u)=b0(n)(5)

So the algorithm logic is as follows:

  • In the interval of real numbers [ 0 , 1 ] [0,1][0,1 ] over a large number of samples. For each sampleuuu , computationP ( u ) \mathcal{P}(u)P(u)
  • According to formula (5), we can calculate β 0 ( n ) \beta_{0}^{(n)}b0(n)To calculate P ( u ) \mathcal{P}(u)P(u)
  • β 0 ( n ) \beta_{0}^{(n)}b0(n)It can be calculated recursively by formula (4).

Code

def draw_curve(p_list):
	"""
    :param p_list: (list of list of int: [[x0, y0], [x1, y1], [x2, y2], ...]) 曲线的控制点坐标列表
    :return: (list of list of int: [[x_0, y_0], [x_1, y_1], [x_2, y_2], ...]) 绘制结果的像素点坐标列表
    """
    result = []
    n = len(p_list) - 1
    freq = 1000
    for u in range(freq + 1):
        u /= freq
        tmp = [[p[0], p[1]] for p in p_list]
        for r in range(1, n + 1):
            tmp = [
                [(1 - u) * tmp[i][0] + u * tmp[i + 1][0],
                 (1 - u) * tmp[i][1] + u * tmp[i + 1][1]
                 ] for i in range(n - r + 1)
            ]
        result.append([round(tmp[0][0]), round(tmp[0][1])])
    return result

Guess you like

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