Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw arc on canvas from two x, y points and a center x, y point

I'm trying to draw an arc from two points (X, Y cords).

But I can't figure out how to do it so that I can specify the start angle and end angle

I got the center point(p2), radius = r. The start point(p1) and the end point(p3). like shown below What I have

And what I wanna do is use the arc to draw a round line like shown below

What I wanna have

All I have found on this subject is only example where arc draw from 0 to something like 2*Math.PI.

ctx.arc(100,75,50,0,2*Math.PI);

Like this. A can't figure out a way that I can use the p1 and p3 instead of those numbers. Anyone that can explain how this work, and maybe give a shot on how I can solve this?

like image 885
DaCh Avatar asked Oct 23 '25 13:10

DaCh


1 Answers

The arc() method works only with angles so points has to be converted based on their location and distance to center (distance, representing the radius, has to be the same for both in this case).

The signature of arc() is:

void arc(unrestricted double x,
              unrestricted double y,
              unrestricted double radius,
              unrestricted double startAngle,
              unrestricted double endAngle,
              optional boolean anticlockwise = false);

You can find the two angles from center P2 to P1/P3 by simple trigonometry:

var startAngle = Math.atan2(p1.y - p2.y, p1.x - p2.x),
    endAngle   = Math.atan2(p3.y - p2.y, p3.x - p2.x);

These can now be fed into the arc method assuming radius is known:

ctx.arc(p2.x, p2.y, radius, startAngle, endAngle);

If radius is unknown but known to be the same you can do:

var diffX = p1.x - p2.x,
    diffY = p1.y - p2.y,
    radius = Math.abs(Math.sqrt(diffX*diffX + diffY*diffY));

Example

var p2 = {x: 100   , y: 100   },
    p1 = {x: 111, y:  30.9},
    p3 = {x: 149.5 , y:  149.5},
    diffX = p1.x - p2.x,
    diffY = p1.y - p2.y,
    radius = Math.abs(Math.sqrt(diffX*diffX + diffY*diffY)),
    startAngle = Math.atan2(diffY, diffX),
    endAngle   = Math.atan2(p3.y - p2.y, p3.x - p2.x),
    ctx = document.querySelector("canvas").getContext("2d");

// arc
ctx.arc(p2.x, p2.y, radius, startAngle, endAngle, false);
ctx.stroke();

// points / lines helpers:
ctx.fillRect(p1.x - 2, p1.y - 2, 4, 4);
ctx.fillRect(p2.x - 2, p2.y - 2, 4, 4);
ctx.fillRect(p3.x - 2, p3.y - 2, 4, 4);
ctx.beginPath();
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.x);
ctx.lineTo(p3.x, p3.x);
ctx.strokeStyle = "#999";
ctx.stroke();
<canvas height=180></canvas>

Result wo/helper lines

var p2 = {x: 100   , y: 100   },
    p1 = {x: 111, y:  30.9},
    p3 = {x: 149.5 , y:  149.5},
    diffX = p1.x - p2.x,
    diffY = p1.y - p2.y,
    radius = Math.abs(Math.sqrt(diffX*diffX + diffY*diffY)),
    startAngle = Math.atan2(diffY, diffX),
    endAngle   = Math.atan2(p3.y - p2.y, p3.x - p2.x),
    ctx = document.querySelector("canvas").getContext("2d");

// arc
ctx.arc(p2.x, p2.y, radius, startAngle, endAngle, false);
ctx.stroke();
<canvas height=180></canvas>

Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!