Center point on html quadratic curve
Asked Answered
P

3

8

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?

Photolysis answered 8/2, 2012 at 13:48 Comment(4)
Please explain what you mean by "control point" and "starting" and "ending" points.Gambeson
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.Photolysis
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?Gambeson
please take a look on qudraticCurveTo(a,b,c) function in htmlcanvas/javascript. It draws the curve according to the control points and the endpointPhotolysis
T
22

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">
Tridactyl answered 8/2, 2012 at 14:55 Comment(0)
G
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

Gambeson answered 8/2, 2012 at 13:55 Comment(4)
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.Photolysis
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?Gambeson
This is the real problem man. I have random start and end pointsPhotolysis
Where does the curve come from in the first place? Do you have an equation describing it?Gambeson
M
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/

Monjan answered 12/12, 2015 at 1:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.