Length of quadratic Bezier curve

Source: Internet
Author: User

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);     &nbsp         break;          default:               return defwindowproc (hwnd,  Message, wparam, lparam);          }          return 0;     }            //-------------------------------------------------------------------------------------      Int apientry winmain (hinstance hinstance,                             hinstance hprevinstance,                            LPTSTR     lpCmdLine,                            

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.