Quadratic Bezier curves are usually constructed in the following manner, given a fixed point p0,p1,p2 on a two-dimensional plane, and B (t) is used to represent the curve
With an animation to demonstrate, you can more clearly indicate the construction process of this curve
If the T-variable itself is linear, the generation of this Bezier curve itself is not uniform, usually at both ends of the fast middle slow.
If the T-variable itself is linear, the generation of this Bezier curve itself is not uniform, usually at both ends of the fast middle slow.
How do you want to get a constant Bezier motion? For example, we design a path to a Bezier curve in a game, how to achieve the player at a constant speed in this path movement.
Thinking of this algorithm is quite a bit of a brain, in the meantime also get math cow Charlesgao help, thank him very much (more embarrassing is, I ask the question when I put one of the formula mistaken, laughed at the-_-!).
First, we need to obtain the velocity formula S (t) of B (t) relative to T.
s (t) = Math.sqrt (Bx (t) ^2 + by (t) ^2)
To simplify the formula, we define the following variables:
A = p0-2*p1 + P2 B = 2*p1-2p0
The calculated s (T) can be expressed as:
s (t) =math.sqrt (a*t^2 + b*t + C)
Where a,b,c is a constant calculated according to the P0,P1,P2:
A = 4 * (ax^2 + by^2)
B = 4 * (ax* by + ay* by)
C = bx^2 + by^2
According to this formula, the length formula of the Bezier curve (t) is obtained:
Set T ' is an independent variable that enables L to achieve uniform motion, then obviously l (t ') =l (1.0) *t, namely:
Since the L (t) function is very complex, it is almost impossible to find the expression of the inverse function directly, but fortunately we can know that its derivative is s (t), in practice, we can use Newton tangent method to find the approximate solution. Its iterative algorithm can be expressed as:
I wrote a test program to verify the algorithm, the results are as follows, you can see that this curve has been generated in a uniform manner ^_^:
[CPP] View plain copy #include <stdio.h> #include <math.h> #include <windows.h> //three control points point p0={50,50},p1={500,600},p2={800,200}; int ax = p0.x-2*p1.x+p2.x; int ay = p0.y-2*p1.y+p2.y; int bx = 2*p1.x-2*p0.x; int by = 2*p1.y-2*p0.y; double a = 4* (Ax*ax+ay*ay); double b = 4* (ax*bx+ay*by); double c = bx*bx+by*by; //Curve total length Double total_ length = 0.0; //Curve split number of copies &NBSP;&NBSp const int step = 70; // Array to hold plot point data point pixels[step]; // ------------------------------------------------------------------------------------- / /Speed function /* S (t_) = Sqrt[A*t*t+B*t+C] */ Double s (double t) { Return sqrt (a*t*t+b*t+c); } //----- -------------------------------------------------------------------------------- /Length function /* L (t) = Integrate[s[t], t] & nbsp L (T_) = (2*sqrt[a]* (2*a*t*sqrt[c + t* (b + a*t)]&Nbsp;+ b* (-sqrt[c] + sqrt[c + t* (b + a*t))) + (b^2 - 4*a*c) (log[b + 2*sqrt[a]*sqrt[c]] - log[b + 2*a*t + 2 sqrt[a]*sqrt[c + t* ( B&NBSP;+&NBSP;A*T)]]) /(8* a^ (3/2)); */ double l (double t) { double temp1 = sqrt (c+ t* (b+a*t)); double temp2 = (2*a*t*temp1+b* ( TEMP1-SQRT (C)); double temp3 = log (B+2*sqrt (A) * sqrt (C)); double temp4 = log (b+2*a*t+2*sqrt (A) * Temp1); double temp5 = 2*sqrt (A) *temp2; double temp6 = (b*b-4*a*c) * (temp3-temp4); return (TEMP5+TEMP6)/(8*pow (a,1.5)); } //----------------------------------- -------------------------------------------------- /length function inverse function, using Newton tangent method to solve /* x (n+1) = xn - f (Xn)/F ' (Xn) */ Double invertl (double t, double l) { double t1=t, t2; do { t2 = t1 - (L (T1)-L)/s (T1); if (ABS ( T1-T2) <0.000001) break; t1=t2; }while (True); return t2; } //-------------------- ----------------------------------------------------------------- Lresult callback _wndproc (Hwnd hwnd, uint message, wparam wparam, lparam lparam) { switch (message) { case wm_timer: { static nIndex = 0; if (nindex>=0 & & nindex<=step) { double t = (double) nindex/step; //If you grow linearly, the corresponding curve length double l = t*total_length; //according to the inverse function of l function, l corresponding T value is obtained t = invertl (T, l); //according to the Bessel curve function, obtain the x,y coordinates at this time double x = (1-t) * (1-t) *p0.x +2* (1-t) *t*p1.x + t*t*p2.x; double y = (1-T) * (1-T) * p0.y +2* (1-t) *t*p1.y + t*t*p2.y; //Rounding &NBSP;&NBsp; pixels[nindex].x = (int) (x+0.5); pixels[nIndex].y = (int) (y+0.5); nindex++; invalidaterect (hwnd, 0, 0); } else { killtimer (hwnd, 101); } } break; case WM_PAINT: { paintstruct ps; hdc hdc = beginpaint (hwnd, &ps); ::movetoex (hdc, p0.x, p0.y, 0); lineto (hdc, P1.x, p1.Y); lineto (HDC, &NBSP;P2.X,&NBSP;P2.Y); for (int i=0; i<step; i++) { const point &pt = pixels[i]; if (pt.x==0 && pt.y==0) break; ::movetoex (hdc, pt.x-2, pt.y, 0); ::lineto (HDC,&NBSP;PT.X+2,&NBSP;PT.Y); ::movetoex (hdc, pt.x, pt.y-2, 0); ::lineto (hdc, pt.x, pt.y+2); } endpaint (hWnd, & PS); } break; case wm_ destroy: postquitmessage (0);   break; default: return defwindowproc (hwnd, Message, wparam, lparam); } return 0; } //------------------------------------------------------------------------------------- Int apientry winmain (hinstance hinstance, hinstance hprevinstance, LPTSTR lpCmdLine,