7

I have a quadratic curve drawn on html canvas using context.quadraticCurveTo(controlX, controlY, endX, endY); .

I have the control-point and the starting and end points, which are not necessarily level with each other horizontally.

How can I find the centre point on the curve using these parameters?

Actually I want to put a div tag on this center point. Is there any equation solving involved in this process?

Val Redchenko
  • 580
  • 1
  • 8
  • 19
me_digvijay
  • 5,087
  • 5
  • 41
  • 78
  • Please explain what you mean by "control point" and "starting" and "ending" points. – Val Redchenko Feb 08 '12 at 13:50
  • The control point is a point which is responsible for curve shape, the start point is the point where the curve starts and the end pont is one where the curve ends. – me_digvijay Feb 08 '12 at 13:55
  • No single point can be responsible for the curve's shape - the curve's shape is defined by values of a,b,c when written in general form. Your starting and ending points - are they level with each other horizontally? Do you have an equation you are plotting? – Val Redchenko Feb 08 '12 at 13:56
  • please take a look on qudraticCurveTo(a,b,c) function in htmlcanvas/javascript. It draws the curve according to the control points and the endpoint – me_digvijay Feb 08 '12 at 14:00

3 Answers3

21

quadraticCurveTo draws a quadratic Bézier curve.

The formulas to calculate the coordinates of a point at any given position (from 0 to 1) on the curve are

x(t) = (1-t)^2 * x1 + 2 * (1-t) * t * x2 + t^2 * x3
y(t) = (1-t)^2 * y1 + 2 * (1-t) * t * y2 + t^2 * y3

where (x1, y1) is the starting point, (x2, y2) is the control point and (x3, y3) is the end point.

So, turning that into JavaScript, we end up with something like

function _getQBezierValue(t, p1, p2, p3) {
    var iT = 1 - t;
    return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3;
}

function getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, position) {
    return {
        x:  _getQBezierValue(position, startX, cpX, endX),
        y:  _getQBezierValue(position, startY, cpY, endY)
    };
}

If you pass the start, end and control points to getQuadraticCurvePoint there, along with 0.5 for the halfway position, you should get an object with the X and Y coordinates.

Example

function _getQBezierValue(t, p1, p2, p3) {
  var iT = 1 - t;
  return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3;
}

function getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, position) {
  return {
    x: _getQBezierValue(position, startX, cpX, endX),
    y: _getQBezierValue(position, startY, cpY, endY),
  };
}

var position = 0.0;
var startPt = { x: 120, y: 10 };
var controlPt = { x: 410, y: 250 };
var endPt = { x: 10, y: 450 };
var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");
function drawNextPoint() {
  var pt = getQuadraticCurvePoint(
    startPt.x,
    startPt.y,
    controlPt.x,
    controlPt.y,
    endPt.x,
    endPt.y,
    position,
  );
  position = (position + 0.006) % 1.0;

  ctx.fillStyle = "rgba(255,0,0,0.5)";
  ctx.fillRect(pt.x - 2, pt.y - 2, 5, 5);
}

ctx.strokeStyle = "black";
ctx.moveTo(startPt.x, startPt.y);
ctx.quadraticCurveTo(controlPt.x, controlPt.y, endPt.x, endPt.y);
ctx.stroke();

setInterval(drawNextPoint, 40);
<canvas id="c" width="500" height="500">
AKX
  • 93,995
  • 11
  • 81
  • 98
0

A possible way:

// compute coordinates of the middle point of a quadratic Bezier curve
// need two functions: quadraticBezierCurvePoint and quadraticBezierCurvesMiddle

function quadraticBezierCurvePoint(t, c) {
  // compute relative coordinates of a point on the curve using t and c
  // t is a number between 0 and 1
  // c is an array of 3 points:
  //     the initial point of the curve (always (0,0))
  //     the "handle" point of the curve
  //     the final point of the curve
  var t1, t1_2a, t1_2b, t1_2c;
  t1 = 1 - t;
  t1_2a = t1 * t1;
  t1_2b = (2 * t) * t1;
  t1_2c = t * t;
  return {
    x: (c[0].x * t1_2a) + (t1_2b * c[1].x) + (t1_2c * c[2].x),
    y: (c[0].y * t1_2a) + (t1_2b * c[1].y) + (t1_2c * c[2].y)
  };
}

function quadraticBezierCurvesMiddle(m, c) {
  var k, km = 1000,
    km2 = (km >> 1),
    len = 0,
    len2, x, y, a = new Array(km + 1);
  // compute curve lengths from start point to any point
  // store relative point coordinates and corresponding length in array a
  for (k = 0; k <= km; k++) {
    a[k] = {
      pt: quadraticBezierCurvePoint(k / km, c),
      len: 0
    };
    if (k > 0) {
      x = a[k].pt.x - a[k - 1].pt.x;
      y = a[k].pt.y - a[k - 1].pt.y;
      a[k].len = a[k - 1].len + Math.sqrt(x * x + y * y);
    }
  }
  // retrieve the point which is at a distance of half the whole curve length from start point
  // most of the time, this point is not the one at indice km2 in array a, but it is near it
  len2 = a[km].len / 2;
  if (a[km2].len > len2)
    for (k = km2; k >= 0; k--) {
      if (len2 >= a[k].len) break;
    } else
    for (k = km2; k <= km; k++) {
      if (len2 <= a[k].len) break;
    }
    // return absolute coordinates of the point
  return {
    x: Math.round((a[k].pt.x + m.x) * 100) / 100,
    y: Math.round((a[k].pt.y + m.y) * 100) / 100
  };
}

And the corresponding jsfiddle: jsfiddle.net/pTccL/

Simon Hi
  • 2,448
  • 1
  • 13
  • 15
0

Here's a page describing the quadratic equation and it's solution: wiki page . And here is a good tutorial on the subject, complete with diagrams: tutorial

Val Redchenko
  • 580
  • 1
  • 8
  • 19
  • This page I know and also i am looking at it but I want to calculate the center point using javascript. I dont know how to find the center point. – me_digvijay Feb 08 '12 at 13:57
  • If your starting and ending points are level with each other horizontally, then the x coordinate of the curve will be directly in the middle (i.e.) x_start + ((x_end - x_start) / 2) and the y coordinate can be found by substituting this x value into the original equation instead of x and solving it. Do you have the equation? – Val Redchenko Feb 08 '12 at 14:00
  • This is the real problem man. I have random start and end points – me_digvijay Feb 08 '12 at 14:01
  • Where does the curve come from in the first place? Do you have an equation describing it? – Val Redchenko Feb 08 '12 at 14:13