muliku
muliku

Reputation: 476

JS move point by an angle on circle

I have program where I click three times, each click creating a point on canvas. I then calculate angle between those three points like this:

function find_angle(A, B, C) {
    var AB = Math.sqrt(Math.pow(B.x - A.x, 2) + Math.pow(B.y - A.y, 2));
    var BC = Math.sqrt(Math.pow(B.x - C.x, 2) + Math.pow(B.y - C.y, 2));
    var AC = Math.sqrt(Math.pow(C.x - A.x, 2) + Math.pow(C.y - A.y, 2));
    return Math.acos((BC * BC + AB * AB - AC * AC) / (2 * BC * AB));
}

degree

In example picture above, the calculated angle is 93°. I need to move point 3 by -3° so the points make exactly 90°. I have this function for it:

var angleToCorrect = alpha * (Math.PI / 180) - 90 * (Math.PI / 180);
correct_angle(point2, point3, angleToCorrect)

...

function correct_angle(p2, p3, angle) {

    var x = p2.x - p3.x;
    var y = p2.y - p3.y;
    var r = Math.sqrt(x * x + y * y); //circle radius. origin of the circle is point 2


    return {
        X: p2.x + (Math.cos(angle) * r),
        Y: p2.y + (Math.sin(angle) * r)

    };

}

Now, this function should return new x and y for point 3 with corrected angle to 90°. Yet the coordinates don't agree with what I expect. Can someone point out what I'm doing wrong?

Upvotes: 1

Views: 1899

Answers (1)

obscure
obscure

Reputation: 12891

To calculate the new position it isn't enough to provide just two of the points since the angle is measured between the three.

So inside this function you have to figure out what the current angle of the vector between point 1 and point 2 is. Javascript offers a nifty built-in function for this Math.atan2() Now that we know the angle (in radians) we need to add the new angle to it. This makes sure we can place point 3 correctly.

function correct_angle(p1, p2, p3, angle)
{
    var currentAngle=Math.atan2(p1.y-p2.y, p1.x-p2.x);

    currentAngle+=angle;

    var x = p2.x - p3.x;
    var y = p2.y - p3.y;
    var r = Math.sqrt(x * x + y * y);

    return {
        X: p2.x + (Math.cos(currentAngle) * r),
        Y: p2.y + (Math.sin(currentAngle) * r)

    };
}

The angle parameter of the function should be the target angle in radians (90 or 1.5707963267949 in your case)

Here's an interactive example:

Point = function(x, y) {
  this.x = x;
  this.y = y;
}

var pointA = new Point(162, 39);
var pointB = new Point(105, 161);
var pointC = new Point(211, 242);

var context = document.getElementById("canvas").getContext("2d");

function correct() {
  var newPoint = correct_angle(pointA, pointB, pointC, 1.5707963267949);
  pointC.x = newPoint.X;
  pointC.y = newPoint.Y;
  draw();
}

function correct_angle(p1, p2, p3, angle) {
  var currentAngle = Math.atan2(p1.y - p2.y, p1.x - p2.x);

  currentAngle += angle;

  var x = p2.x - p3.x;
  var y = p2.y - p3.y;
  var r = Math.sqrt(x * x + y * y);

  return {
    X: p2.x + (Math.cos(currentAngle) * r),
    Y: p2.y + (Math.sin(currentAngle) * r)

  };
}

function draw() {
  context.clearRect(0, 0, 400, 300);
  context.fillStyle = "red";
  context.beginPath();
  context.arc(pointA.x, pointA.y, 10, 0, 2 * Math.PI);
  context.fill();

  context.beginPath();
  context.arc(pointB.x, pointB.y, 10, 0, 2 * Math.PI);
  context.fill();

  context.beginPath();
  context.arc(pointC.x, pointC.y, 10, 0, 2 * Math.PI);
  context.fill();
}

draw();
<canvas id="canvas" width="400" height="300" style="background-color:#dddddd;"></canvas>
<button onclick="correct()" style="float:left">
correct me
</button>

Upvotes: 1

Related Questions