Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding points on curves in HTML 5 2d Canvas context

Given lines drawn by 2d canvas context functions bezierCurveTo, quadraticCurveTo or arcTo, how can I find points along those lines?

My intent is to draw an object at the midpoint of a curve. Using the SVG DOM, I can do this with methods getPointAtLength & getTotalLength, but I can't see an equivalent in HTML canvas.

like image 354
Paul Butcher Avatar asked Aug 25 '10 21:08

Paul Butcher


2 Answers

You find them the hard way :(

There isn't an equivalent in HTML canvas. You have to find the midpoints yourself with plain old math.

I did an example of how to find midpoint of bezier curves for you. See it live at jsFiddle here. A copy of the javascript is pasted below.

Real curve is red, midpoint is the tiny green rectangle. Everything else is just a visual aid.

var ctx = $("#test")[0].getContext("2d")
function mid(a,b) {
 return (a+b) / 2;
}


var cp1x = 100;
var cp1y = 150;
var cp2x = 175;
var cp2y = 175;
var x = 200;
var y = 0;

ctx.lineWidth = 4;
ctx.strokeStyle = "red";
ctx.fillStyle = "rgba(0,0,0,0.6)";

ctx.beginPath();
ctx.moveTo(0, 0);
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
ctx.stroke();

//line goes from start to control point 1
ctx.strokeStyle = "rgba(0,0,200,0.4)";
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(cp1x , cp1y);
ctx.stroke();

//line goes from end to control point 2
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(cp2x , cp2y);
ctx.stroke();

//line goes from control point to control point
ctx.strokeStyle = "rgba(200,0,200,0.4)";
ctx.beginPath();
ctx.moveTo(cp1x, cp1y);
ctx.lineTo(cp2x , cp2y);
ctx.stroke();

// now find the midpoint of each of those 3 lines
var ax = mid(cp1x,0);
var bx = mid(cp2x,x)
var cx = mid(cp1x,cp2x)

var ay = mid(cp1y,0)    
var by = mid(cp2y,y)    
var cy = mid(cp1y,cp2y)


// draw midpoints for visual aid 
// not gonna look exact 'cause square
// will be drawn from top-right instead of center
ctx.fillRect(ax, ay, 4, 4);
ctx.fillRect(bx, by, 4, 4);
ctx.fillRect(cx, cy, 4, 4);


//now draw lines between those three points. These are green
ctx.strokeStyle = "rgba(0,200,0,0.4)";
ctx.beginPath();
ctx.moveTo(ax, ay);
ctx.lineTo(cx , cy);
ctx.stroke();

ctx.beginPath();
ctx.moveTo(bx, by);
ctx.lineTo(cx , cy);
ctx.stroke();

//now the midpoint of the green lines:
// so g1 and g2 are the green line midpoints
var g1x = mid(ax,cx);
var g2x = mid(bx,cx);

var g1y = mid(ay,cy); 
var g2y = mid(by,cy);  

//draw them to make sure:
ctx.fillRect(g1x , g1y, 4, 4);
ctx.fillRect(g2x , g2y, 4, 4);

//now one final line, in gray
ctx.strokeStyle = "rgba(20,20,20,0.4)";
ctx.beginPath();
ctx.moveTo(g1x , g1y);
ctx.lineTo(g2x , g2y);
ctx.stroke();

//whew! We made it!
var FinallyTheMidpointx = mid(g1x,g2x); 
var FinallyTheMidpointy = mid(g1y,g2y); 

//draw something at the midpoint to celebrate
ctx.fillStyle = "rgba(0,255,0,1)";
ctx.fillRect(FinallyTheMidpointx, FinallyTheMidpointy, 4, 4);

like image 148
Simon Sarris Avatar answered Oct 13 '22 20:10

Simon Sarris


A Bezier Curve is calculated Mathematically with this formula
Bezier Curve Mathematically
Where P0 is the startpoint, P1 and P2 are the control points and P3 is the end point.

To calculate the halfwaypoint you can just use t = 0.5.

Similar for the Quadratic Curve:
Quadratic Curve Mathematically

Source and further Information

like image 44
Plagiatus Avatar answered Oct 13 '22 21:10

Plagiatus