javascriptmathhtml5-canvasbezierquadratic-curve

How to find the control point of a quadratic curve using a parabola?


I can't figure out how to draw a parabola which is having a equation as y^2 = 4ax

So I have both end points i.e. P0, P2, however I can't figure out how to find control point to put in quadraticCurveTo() function.


Solution

  • To match a quadratic Bezier to this parabola formula and assuming origin is 0, you can use place the control point at -y0 or -y1 from one of the end points.

    Example

    First, lets rearrange the formula:

    y2 = 4ax

    to:

    x = y2 / 4a

    so we can plot from bottom down.

    In this case we can simply boil down everything and use the inverse of y and mid x as control point.

    The general principle though, is to find the tangents of the endpoints. Then where the lines from those intersect the control-point should be placed. If you want the mathematical steps on how to find the intersection I would recommend taking a look at Erik Man's answer here (which happened to be posted today but breaks down the math in much more details).

    So, if we plot it within the window of a canvas (black is parabola, red is quadratic curve):

    var ctx = document.querySelector("canvas").getContext("2d"),
        w = ctx.canvas.width, h = ctx.canvas.height;
    ctx.strokeStyle = "red";
    ctx.lineWidth = 2;
    ctx.translate(0, 6);
    
    // formula
    function f(y, a) {return y * y / (a * 4)};
    
    var a = 80;
    
    plotWindow();
    
    function plotWindow() {
      
      ctx.clearRect(0, -6, w, h);
      ctx.fillStyle = "#000";
      
      // plot parabola using formula
      for(var i = 0; i < w; i++) {
        var y = f(i - w * 0.5, a);
        ctx.fillRect(i - 2, y - 2, 4, 4);
      }
    
      // plot parabola using quadratic curve:
      var x0 = 0;
      var y0 = f(-w * 0.5, a);
      var x1 = w;
      var y1 = f( w * 0.5, a);
      var cx = x1 * 0.5;  // control point is center for x
      var cy = -y0;       // control point is -y0 for y assuming top of parabola = 0
    
      ctx.beginPath();
      ctx.moveTo(x0, y0);
      ctx.quadraticCurveTo(cx, cy, x1, y1);
      ctx.stroke();
      
      // plot a
      ctx.fillStyle = "blue";
      ctx.fillRect(cx - 3, a - 3, 6, 6);
      ctx.fillText("a=" + a, cx + 6, a + 5)
    }
    
    // slider
    document.querySelector("input").onchange = function() {
      a = +this.value;
      plotWindow();
    };
    canvas {border:1px solid #777}
    <script src="https://cdn.rawgit.com/epistemex/slider-feedback/master/sliderfeedback.min.js"></script>
    <label>a: <input type="range" min=10 max=172 value=80></label><br>
    <canvas width=600 height=190></canvas>