Quadratic Bézier Curve: Calculate Points

后端 未结 5 1555
别那么骄傲
别那么骄傲 2020-11-28 01:57

I\'d like to calculate a point on a quadratic curve. To use it with the canvas element of HTML5.

When I use the quadraticCurveTo() function in JavaScript, I have a s

相关标签:
5条回答
  • 2020-11-28 02:29

    I edited talkhabis answer (cubic curve) so the curve is displayed with the right coordinates. (Couldn't comment) The Y-coordinates needed to be changed (-p[].y+150). (A new variable for that might be a nicer and more efficient solution, but you get the idea)

    // Apply points to SVG and create the curve and controllers :
    
    var path  =  document.getElementById('path'),
        ctrl1 =  document.getElementById('ctrl1'),
        ctrl2 =  document.getElementById('ctrl2'),
        D = 'M ' + p0.x + ' ' + (-p0.y+150) +
        'C ' + c0.x + ' ' + (-c0.y+150) +', ' + c1.x + ' ' + (-c1.y+150) + ', ' + p1.x + ' ' + (-p1.y+150);
    
    path.setAttribute('d',D);
    ctrl1.setAttribute('d','M'+p0.x+','+(-p0.y+150)+'L'+c0.x+','+(-c0.y+150));
    ctrl2.setAttribute('d','M'+p1.x+','+(-p1.y+150)+'L'+c1.x+','+(-c1.y+150));
    
    // Lets test the "Bezier Function" 
    
    var t = 0, point = document.getElementById('point');
    
    setInterval(function(){
    
      var p = Bezier(p0,c0,c1,p1,t);
      point.setAttribute('cx',p.x);
      point.setAttribute('cy',-p.y+150);
    
      t += 0.01;
      if(t>=1) t=0;
    
    },50);
    
    
    // OK ... Now tring to get "y" on cruve based on mouse "x" : 
    
    var svg = document.getElementById('svg'),
        point2 = document.getElementById('point2');
    
    svg.onmousemove = function(e){
    
        var x = (e.pageX - 50)/2,  
            y = (e.pageY - 50)/2;
       // "-50" because of "50px margin" on the left side 
       // and "/2" because the svg width is 300 units and 600 px => 300 = 600/2    
    
      // Get the x,y by mouse x
      var p = YBX(p0,c0,c1,p1,x); 
    
      point2.setAttribute('cx',p.x);
      point2.setAttribute('cy',-p.y+150);  
    } 
    

    http://jsfiddle.net/u214gco8/1/

    I also created some C-Code to test the results for the cubic curve. Just enter the X and Y coordinates in the main function.

    #include <stdio.h>
    #include <stdlib.h> 
    #include <math.h> 
    
    void bezierCurve(int x[] , int y[]) 
    { 
        double xu = 0.0 , yu = 0.0 , u = 0.0 ; 
        int i = 0 ; 
        for(u = 0.0 ; u <= 1.0 ; u += 0.05) 
        { 
            xu = pow(1-u,3)*x[0]+3*u*pow(1-u,2)*x[1]+3*pow(u,2)*(1-u)*x[2] 
                 +pow(u,3)*x[3]; 
            yu = pow(1-u,3)*y[0]+3*u*pow(1-u,2)*y[1]+3*pow(u,2)*(1-u)*y[2] 
                +pow(u,3)*y[3]; 
            printf("X: %i   Y: %i \n" , (int)xu , (int)yu) ; 
        } 
    } 
    
    int main(void) {
        int x[] = {0,75,50,300};
        int y[] = {0,2,140,100};
        bezierCurve(x,y);
        return 0;
    }
    

    https://ideone.com/glLXcB

    0 讨论(0)
  • 2020-11-28 02:34

    Use the quadratic Bézier formula, found, for instance, on the Wikipedia page for Bézier Curves:

    quadratic Bezier formula

    In pseudo-code, that's

    t = 0.5; // given example value
    x = (1 - t) * (1 - t) * p[0].x + 2 * (1 - t) * t * p[1].x + t * t * p[2].x;
    y = (1 - t) * (1 - t) * p[0].y + 2 * (1 - t) * t * p[1].y + t * t * p[2].y;
    

    p[0] is the start point, p[1] is the control point, and p[2] is the end point. t is the parameter, which goes from 0 to 1.

    0 讨论(0)
  • 2020-11-28 02:35

    I created this demo :

    // x = a * (1-t)³ + b * 3 * (1-t)²t + c * 3 * (1-t)t² + d * t³
    //------------------------------------------------------------
    // x = a - 3at + 3at² - at³ 
    //       + 3bt - 6bt² + 3bt³
    //             + 3ct² - 3ct³
    //                    + dt³
    //--------------------------------
    // x = - at³  + 3bt³ - 3ct³ + dt³
    //     + 3at² - 6bt² + 3ct²
    //     - 3at + 3bt
    //     + a
    //--------------------------------
    // 0 = t³ (-a+3b-3c+d) +  => A
    //     t² (3a-6b+3c)   +  => B
    //     t  (-3a+3b)     +  => c
    //     a - x              => D
    //--------------------------------
    
    var A = d - 3*c + 3*b - a,
        B = 3*c - 6*b + 3*a,
        C = 3*b - 3*a,
        D = a-x;
    
    // So we need to solve At³ + Bt² + Ct + D = 0 
    

    Full example here

    may help someone.

    0 讨论(0)
  • 2020-11-28 02:40

    Just a note: If you are using the usual formulas presented here then don't expect t = 0.5 to return the point at half of the curve's length.. In most cases it won't.

    More on this here under "§23 — Tracing a curve at fixed distance intervals" and here.

    0 讨论(0)
  • 2020-11-28 02:41

    In case somebody needs the cubic form:

            //B(t) = (1-t)**3 p0 + 3(1 - t)**2 t P1 + 3(1-t)t**2 P2 + t**3 P3
    
            x = (1-t)*(1-t)*(1-t)*p0x + 3*(1-t)*(1-t)*t*p1x + 3*(1-t)*t*t*p2x + t*t*t*p3x;
            y = (1-t)*(1-t)*(1-t)*p0y + 3*(1-t)*(1-t)*t*p1y + 3*(1-t)*t*t*p2y + t*t*t*p3y;
    
    0 讨论(0)
提交回复
热议问题