Bezier curve control with control handle - history, principle, implementation

© 2013-2023 Conmajia
Updated on 9th March, 2023
Initiated on 22nd February, 2015

Abstract This article introduces the history and basic principles of Bezier curves, and takes .NET Frameworks GDI+ as an example to simply implement a curve control with control handles and extensible styles.

1 Introduction

Curves with control handles are often used in drawing software to precisely adjust continuously changing values. Bezier curves are derived from a family of curve parameter equations widely used in engineering CAD and computer graphics. Pierre Étienne Bézier (Pierre Étienne Bézier, 1910-1999) proposed in 1962, and developed the UNISURF modeling system based on it (1968). For details about Bessel functions, please refer to Bessel My book "The Mathematical Foundations of the UNISURF CAD System" (Butterworths, 1986, p. 56).

1.1 Bessel function

Bessel functions are a family of the form

x 2 y ′ ′ + x y ′ + ( x 2 − n 2 ) y = 0 x^2y''+xy'+\left(x^2-n^2\right)y=0 x2 y′′+xy+(x2n2)y=0

function, where nnn is the order. The solution of this family of functions is

y ( x ) = A J n ( x ) + B Y n ( x ) , y(x)=AJ_n(x)+BY_n(x), y(x)=AJn(x)+BYn(x),

Among them J n ( x ) J_n(x)Jn( x ) is calledBessel function of the first kind,Y n ( x ) Y_n(x)Yn( x ) is calleda Bessel function of the second kind.

The Bessel function can be regarded as a family of decaying sine functions, as shown in Figure 1, where J 0 ( 0 ) = 1 J_0(0)=1J0(0)=1Y n ( 0 ) = ∞ Y_n(0)=\inftyYn(0)=.

Figure 1. Graphs of Bessel functions of the first and second kind

Using the Frobenius method to solve, we can get,

J n ( x ) = ∑ k = 0 ∞ ( − 1 ) k k ! ( n + k ) ! ( x 2 ) n + 2 k Y n ( x ) = 2 π J n ( x ) [ ln ⁡ x 2 + γ ] − 1 π ∑ k = 0 n − 1 ( n − k − 1 ) ! k ! ( x 2 ) 2 k − n − 1 π ∑ k = 0 ∞ ( − 1 ) k [ Φ ( k ) + Φ ( n + k ) ] 1 k ! ( n + k ) ! ( x 2 ) 2 k + n , J_n(x)=\sum_{k=0}^\infty\frac{(-1)^k}{k!(n+k)!}\left(\frac{x}{2}\right)^{n+2k}\\ \begin{aligned} Y_n(x)=&\frac{2}{\pi}J_n(x)\left[\ln\frac{x}{2}+\gamma\right]-\frac{1}{\pi}\sum_{k=0}^{n-1}\frac{(n-k-1)!}{k!}\left(\frac{x}{2}\right)^{2k-n}\\ &-\frac{1}{\pi}\sum_{k=0}^\infty(-1)^k\left[\Phi(k)+\Phi(n+k)\right]\frac{1}{k!(n+k)!}\left(\frac{x}{2}\right)^{2k+n}, \end{aligned} Jn(x)=k=0k!(n+k)!(1)k(2x)n + 2k _Yn(x)=Pi2Jn(x)[ln2x+c ]Pi1k=0n1k!(nk1)!(2x)2 k nPi1k=0(1)k[ Φ ( k )+F ( n+k)]k!(n+k)!1(2x)2 k + n,

where γ = .0.577216 \gamma\stackrel{.}{=}0.577216c=.0.577216Φ ( p ) = 1 + 1 2 + 1 3 + ⋯ + 1 p \Phi(p)=1+\dfrac{1}{2}+\dfrac{1}{3}+\cdots+\dfrac{ 1Φ ( p )=1+21+31++p1 p > 0 p>0 p>0Φ(0)=0 \Phi(0)=0Φ ( 0 )=0.

So it can be regarded as x → ∞ x\to\inftyxThe asymptote equation of the Bessel function at ∞ is approximated as

J n ( x ) ∼ 2 π x cos ⁡ ( x − n π 2 − π 4 ) Y n ( x ) ∼ 2 π x sin ⁡ ( x − n π 2 − π 4 ) \begin{aligned} J_n(x)&\sim\sqrt\frac{2}{\pi x}\cos\left(x-\frac{n\pi}{2}-\frac{\pi}{4 }\right)\\ Y_n(x)&\sim\sqrt\frac{2}{\pi x}\sin\left(x-\frac{n\pi}{2}-\frac{\pi}{ 4}\right). \end{aligned}Jn(x)Yn(x)x _2 cos(x24p)x _2 sin(x24p).

In addition, the Hankel function (Hankel), which is commonly used in engineering, is also called the Bessel function of the third kind .

H n ( 1 ) ( x ) ≡ J n ( x ) + j Y n ( x ) H n ( 2 ) ( x ) ≡ J n ( x ) − j Y n ( x ) , \begin{aligned} H_n^{(1)}(x)&\equiv J_n(x)+jY_n(x)\\ H_n^{(2)}(x)&\equiv J_n(x)-jY_n(x), \end{aligned} Hn(1)(x)Hn(2)(x)Jn(x)+j Yn(x)Jn(x)j Yn(x),

where superscript ( 1 ) ^{(1)}(1) ( 2 ) ^{(2)} ( 2 ) for the first and second types of Bessel functions respectively. Whenx → ∞ x\to\inftyx ,

H n ( 1 ) ( x ) ∼ 2 π x e + j ( x − n π 2 − π 4 ) H n ( 2 ) ( x ) ∼ 2 π x e − j ( x − n π 2 − π 4 ) . \begin{aligned} H_n^{(1)}(x)&\sim\sqrt\frac{2}{\pi x}e^{+j\left(x-\frac{n\pi}{2}-\frac{\pi}{4}\right)}\\ H_n^{(2)}(x)&\sim\sqrt\frac{2}{\pi x}e^{-j\left(x-\frac{n\pi}{2}-\frac{\pi}{4}\right)}. \end{aligned} Hn(1)(x)Hn(2)(x)x _2 e+j(x24p)x _2 ej(x24p).

Bessel functions of the third kind are often used to deal with engineering or graphics problems with multiple coordinate systems.

1.2 Bezier curve

The mathematical basis of Bezier curves actually comes from the Bernstein polynomials published in 1912, a family named by the former Soviet mathematician Sergei Natanovich Bernstein (Серге́й Ната́нович Бернште́йн, 1880-1968) Basis polynomials and their linear combinations. The earliest numerical method for computing Bernstein polynomials was proposed by French Citroen engineer Paul de Casteljau (Paul de Casteljau, 1930-2022) in 1959. Because this method was adopted by Citroen Registered as a patent, its main content was not disclosed until the 1980s, so now it looks like B ( t ) = ∑ i = 0 n β ibi , n ( t ) B(t)=\sum_{i=0}^n\beta_i b_{i,n}(t)B(t)=i=0nbibi,nThe Bernstein form curve of ( t ) is named after the first public Bezier, calledBezier curve. Whereβ i \beta_ibifor secondi control points,

b i , n ( t ) = ( n i ) ( 1 − t ) n − i t i , b_{i,n}(t)=\binom{n}{i}(1-t)^{n-i}t^i, bi,n(t)=(in)(1t)niti,

is the Bernstein basis polynomial.

1.2.1 De Castrio's Algorithm

De Castrio's algorithm actually decomposes a single Bernstein function into two Bezier curves, t 0 t_0t0The curve at can be obtained by the following recurrence relation,

β i ( 0 ) ≡ β i ,    i = 0 , 1 , ⋯   , n β i ( j ) ≡ β i ( j − 1 ) ( 1 − t 0 ) + β i + 1 ( j − 1 ) t 0 , \begin{aligned} \beta_i^{(0)}&\equiv\beta_i,\;i=0,1,\cdots,n \\ \beta_i^{(j)}&\equiv\beta_i^{(j-1)}(1-t_0)+\beta_{i+1}^{(j-1)}t_0, \end{aligned} bi(0)bi(j)bi,i=0,1,,nbi(j1)(1t0)+bi+1(j1)t0,

Among them, for β i ( j ) \beta_i^{(j)}bi(j),有 i = 0 , 1 , ⋯   , n − j i=0,1,\cdots,n-j i=0,1,,nj j = 1 , 2 , ⋯   , n j=1,2,\cdots,n j=1,2,,n . At this timet 0 t_0t0The Bezier curve at B ( t 0 ) = β 0 ( n ) B(t_0)=\beta_0^{(n)}B(t0)=b0(n), and can be decomposed into

β 0 ( 0 ) , β 0 ( 1 ) , β 0 ( 2 ) , ⋯ , β 0 ( n ) β 0 ( n ) , β 1 ( n − 1 ) , β 2 ( n − 2 ) , ⋯ , β n ( 0 ) . \begin{aligned} &\beta_0^{(0)},\beta_0^{(1)},\beta_0^{(2)},\cdots,\beta_0^{(n)}\\ &\beta_0^ {(n)},\beta_1^{(n-1)},\beta_2^{(n-2)},\cdots,\beta_n^{(0)}. \end{aligned}b0(0),b0(1),b0(2),,b0(n)b0(n),b1(n1),b2(n2),,bn(0).

The advantage of de castrio's algorithm is that it has the characteristics of numerical stability, and the disadvantage is that it is less efficient than direct calculation. The following is a simple implementation of de castrio's algorithm in Python language, for readers' reference 1 .

def de_casteljau(t, coefs):
    beta = [c for c in coefs] # 此列表中的数据将于后续计算中覆盖
    n = len(beta)
    for j in range(1, n):
        for k in range(n - j):
            beta[k] = beta[k] * (1 - t) + beta[k + 1] * t
    return beta[0]

1.2.2 Bezier curve 2

As mentioned earlier, nnThe general formula of n- order Bezier curve is

B ( t ) = ∑ i = 0 n β i b i , n ( t ) , B(t)=\sum_{i=0}^n\beta_i b_{i,n}(t), B(t)=i=0nbibi,n(t),

where t ∈ [ 0 , 1 ] t\in[0,1]t[0,1 ] . Obviously, whenn = 1 n=1n=1 , a Bezier curve can be obtained

B ( t ) = β 0 + ( β 1 − β 0 ) t = ( 1 − t ) β 0 + t β 1 , \begin{aligned} B(t)&=\beta_0+(\beta_1-\beta_0)t\\ &=(1-t)\beta_0+t\beta_1, \end{aligned} B(t)=b0+( b1b0)t=(1t ) b0+tβ1,

Its graph is endpoint from β 0 \beta_0b0Motion to β 1 \beta_1b1The straight line, as shown in Figure 2, is also called linear Bezier curve. Note that β i \beta_i in the figurebiUse P i P_iPimeans, the same below.

Figure 2. A Bezier curve

n = 2 n=2 n=2 时, B ( t ) = ( 1 − t ) 2 β 0 + 2 t ( 1 − t ) β 1 + t 2 β 2 B(t)=(1-t)^2\beta_0+2t(1-t)\beta_1+t^2\beta_2 B(t)=(1t)2 b0+2t ( 1 _t ) b1+t2 b2is a moving point Q 0 Q_0Q0 Q 1 Q_1 Q1- also known as intermediate point - since β 1 \beta_1b1Movement to β 2 \beta_2b2form, as shown in Figure 3.

Figure 3. Quadratic Bezier curve

The TrueType fonts commonly used in computer systems are implemented using quadratic Bezier curves.

when n = 3 n=3n=3 or higher, for buildnnn times Bezier curve, need to introduce( nn − 1 ) \dbinom{n}{n-1}(n1n) intermediate points. Figure 4 demonstrates the construction process of cubic and quartic Bezier curves.

First
Second

Figure 4. (A) Cubic Bezier curve; (B) Quartic Bezier curve

The above graphics and animations are realized by De Castrio algorithm.

2 Design controls based on Bezier curves

All common graphics operating systems currently on the market have built-in functions for drawing Bezier curves in their graphics systems. Taking Windows as an example, its graphics system GDI/GDI+ implements a four-point Bezier curve as shown in Figure 5. That is, in the cubic Bezier curve, β 1 \beta_1b1and β 2 \beta_2b2respectively used as β 0 \beta_0b0and β 3 \beta_3b3The control hand of . In the curve expression, β 0 \beta_0b0β 1 \beta_1b1β 2 \beta_2b2β 3 \beta_3b3Corresponding to the points "First", "Second", "Third" and "Fourth" on the graph respectively.

Figure 5. Bezier curves in computer graphics

2.1 Drawing a Bezier curve 3

By calling the functions wrapped in GDI+ for drawing cubic Bezier curves DrawBezier,

public void DrawBezier(Pen pen,
                       Point pt1,
                       Point pt2,
                       Point pt3,
                       Point pt4);
public void DrawBezier(Pen pen,
                       PointF pt1,
                       PointF pt2,
                       PointF pt3,
                       PointF pt4);
public void DrawBezier(Pen pen,
                       float x1,
                       float y1,
                       float x2,
                       float y2,
                       float x3,
                       float y3,
                       float x4,
                       float y4);

Users can easily draw the desired Bezier curve on the form. Figure 6 is drawn with the following code.

private void Exercise_Paint(object sender, PaintEventArgs e)
{
    
    
        Pen penCurrent = new Pen(Color.Blue);
        Point pt1 = new Point(20, 12),
                    pt2 = new Point(88, 246),
                    pt3 = new Point(364, 192),
                    pt4 = new Point(250, 48);

        e.Graphics.DrawBezier(penCurrent, pt1, pt2, pt3, pt4);
}

Figure 6. Bezier curve drawn by GDI+

2.2 Define the Bezier curve in the graphical control

In order to realize the graphical interaction function between the user and the control, first manage the control points of the cubic Bezier curve. If expressed in the concept of "Model-View-Control" (MVC), the Bezier curve graphic control here It can be designed according to the following chapters.

2.2.1 Model

It can be seen from the previous chapters that the cubic Bezier curve has 2 endpoints and 2 intermediary points, as shown in Figure 7, which are named anchor points (anchor) and handle points (handler) respectively.

Figure 7. The endpoints on the Bezier curve control, the control points in the figure are the handle points described in the text

Bezier curve endpoints are defined as follows:

// 贝塞尔曲线点
public class BezierPoint {
    
    
	public Point Anchor {
    
     get; set; }
	public Point Handler {
    
     get; set; }
}

The endpoint of each Bezier curve contains an anchor point and the corresponding handle point, that is, ( β 0 , β 1 ) (\beta_0,\beta_1) in the curve expression( b0,b1) or( β 2 , β 3 ) (\beta_2,\beta_3)( b2,b3) . Then a cubic Bezier curve segment can be defined as:

// 贝塞尔曲线段
public class BezierSegment {
    
    
    public BezierPoint Begin;
    public BezierPoint End;
}

By changing the position of the anchor point and the position of the handle point, a Bezier curve of any shape can be realized, and its use effect should be as shown in the animation in Figure 8.

Figure 8. Controllable Bezier curve control appearance and interactive demonstration

2.2.2 Views

The appearance of the curve is independent of the endpoints of the curve, and it can be drawn using an independent scalable renderer, such as the following simple renderer:

public class BezierRenderer {
    
    
    public void DrawSegment(Graphics g, BezierSegment s, Color color) {
    
    
    using (Pen p = new Pen(color)) {
    
    
        g.DrawBezier(
            p,
            s.Begin.Anchor,
            s.Begin.Handler,
            s.End.Anchor,
            s.End.Handler);
    }
    public void DrawHandle(Graphics g, Point pt, bool solid, Color color) {
    
    
        if (solid)
            using (SolidBrush b = new SolidBrush(color))
                g.FillRectangle(b, pt.X - 2, pt.Y - 2, 4, 4);
        else
            using (Pen p = new Pen(color))
                g.DrawRectangle(b, pt.X - 2, pt.Y - 2, 4, 4);
    }
    public void DrawBar(Graphics g, Point pt1, Point pt2, Color color) {
    
    
        using (Pen p = new Pen(color))
            g.DrawLine(p, pt1, pt2);
    }
}

This renderer only provides the ability to customize the color of each point and the color of the connection line from the handle point to the anchor point. Here is an example of using it:

// 画曲线
renderer.DrawSegment(g, s, Color.DimGray);

// 画锚点,灰色
renderer.DrawHandle(g, s.Begin.Anchor, false, Color.DimGray);
renderer.DrawHandle(g, s.End.Anchor, false, Color.DimGray);

// 画手柄点,黑色
renderer.DrawBar(g, s.Begin.Anchor, s.Begin.Handler, Color.Black);
renderer.DrawHandle(g, s.Begin.Handler, false, Color.Black);
renderer.DrawBar(g, s.End.Anchor, s.End.Handler, Color.Black);
renderer.DrawHandle(g, s.End.Handler, false, Color.Black);

// 被选中的手柄点为实心
if (target != null)
    renderer.DrawHandle(g, target.Handler, true, Color.Black);

In this way, a Bezier curve can be drawn, as shown in Figure 9. Note that the anchor point and the handle point coincide at this time, which looks similar to a Bezier curve.

Figure 9. The Bezier curve drawn in the graphics control, the anchor point coincides with the handle point

2.2.3 Control

The above has realized the data storage and appearance expression of the Bezier curve segment. Now add control functions to it, that is, the ability to modify data. Here, the mouse cursor is used to interact. The simple interaction logic can be considered as follows:

  1. Press the mouse button, if the point falls on an endpoint (or within its neighborhood), the point should be marked as selected
  2. Move the mouse cursor, if an endpoint is selected, modify the coordinates of the endpoint according to the cursor position
  3. Lift the mouse button to cancel all endpoint selections

In this way, the control needs to be processed in the MouseDown, MouseMove, and MouseUpevents of the control. A simple implementation is demonstrated below. Note that the part about moving here only considers the handle point, and in fact, the anchor point should be considered in the complete implementation.

First, use the hotspot monitoring area (that is, the neighborhood mentioned in 1) to slightly expand the selection to reduce the difficulty of cursor selection. In addition, define a pointer to point to the selected endpoint.

Rectangle rectBegin, rectEnd;
BezierPoint target = null;

Now start handling mouse interaction events.

// MouseDown,若落点位于某端点邻域内,则将其标记为已选中
if (rectBegin.Contains(e.Location))
    target = s.Begin;
else if (rectEnd.Contains(e.Location))
    target = s.End;

// MouseMove,若有选中状态的端点,则用光标位置更新其坐标
if (target != null) 
	target.ControlPoint = e.Location;

// MouseUp,取消选择
target = null;

In this way, the Bezier curve control shown in Figure 8 can be realized.

2.4 Additional Effects

If you modify the renderer, you can get more image effects, such as the colored curve shown in Figure 10.

Figure 10. Demonstration of the running effect of the control after changing the renderer

Summarize

Bezier curve is a powerful graphical tool. In modern computer operating systems, it is easy to implement interactive and extensible Bezier curve controls by calling system drawing functions. This paper introduces Bezier functions, curves and Related computing and design methods provide a simple implementation based on Windows GDI+, and demonstrate how to change the appearance of controls through the renderer. Users can connect multiple anchor points to achieve complex curve effects of any scale. In addition, they can also use A more efficient drawing method optimizes the control, and adds a custom event handling mechanism to the control so that it can be used in commercial practice.

(over)

© 2013-2023 Conmajia


  1. See De Castrio's Algorithm . ↩︎

  2. See Bézier curves . ↩︎

  3. See GDI+ Shapes: Bezier Curves ↩︎

Guess you like

Origin blog.csdn.net/conmajia/article/details/43907499