1
votes

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?

2
Are the distance from p2 to p1 and p2 to p3 always the same?user1693593
yes, the radius will always be the sameDaCh

2 Answers

3
votes

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>
0
votes
ctx.arc(100,75,50,0,2*Math.PI);

Here first two arguments are point p2 x,y co-ordinates and third argument is radius of circle r. Fourth and fifth argumentsare the start angle and end angle of arc.

let m21 be the slope of line joining point1(x1, y1) and point2(x2, y2)

m21 = (y2-y1)/(x2-x1)

let m21 be the slope of line joining point3(x3, y3) and point2(x2, y2)

m23 = (y2-y3)/(x2-x3)

ctx.arc(100, 75, 50, Math.atan(m21), Math.atan(m23), true)

will do it.

If point2 is origin then the solution is more simpler.

ctx.arc(100, 75, 50, Math.atan2(x1,y1), Math.atan2(x3,y3), true)