Reputation: 37
When I wrote this script to calculate the angle from 2 points (I know I can use atan2, but experiments and math learning), I got some weird results when I combined it with a triangle function I wrote. It suddenly turns around when the halfway point on the x axis is passed with the mouse, and as I don't know much about trigonometery I didn't know how to fix this issue... Here's my code:
const can = document.getElementById('can');
const ctx = can.getContext('2d');
can.width = innerWidth;
can.height = innerHeight;
var length = 200;
var origin = {x: can.width / 2, y: can.height / 2};
var mousey;
var mousex;
function triangle(x1, y1, x2, y2){
ctx.strokeStyle = "blue";
ctx.lineWidth = "2";
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x2, y2);
ctx.lineTo(x2, y2 + (y1 - y2));
ctx.strokeStyle = "#33cc33";
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x2, y2 + (y1 - y2));
ctx.lineTo(x1, y1);
ctx.strokeStyle = "red";
ctx.stroke();
}
(function loop(){
ctx.clearRect(0, 0, can.width, can.height);
calc2(mousex, mousey);
requestAnimationFrame(loop);
})();
function update(){
calc2(mousex, mousey);
}
function calc2(x1, y1){
let x2 = origin.x;
let y2 = origin.y;
let opposite = y1 - y2;
let hypotenuse = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
let a = Math.asin(opposite / hypotenuse);
triangle(x2, y2, x2 + Math.cos(a) * length, y2 + Math.sin(a) * length);
}
addEventListener('mousemove', (e)=>{
mousey = e.clientY;
mousex = e.clientX;
});
<canvas id="can" width="400" height="400"></canvas>
Thanks in advance!
Upvotes: 0
Views: 56
Reputation: 431
In function calc2(x1, y1), variable 'hypotenuse' is always a non-negative number, it can't tell if your mouse is on the left or right side. You need a boolean to store this.
The range of Math.asin() is from -pi/2 to pi/2 (-90 degrees to 90 degrees). Cos() this angle is always greater or equal to 0. In your calculations, the -90 deg relative to the horizontal red line is a straight downward line. Rotating counterclockwise from there, -45 deg is a line to lower right corner, 0 deg is the red line itself, 45 deg to upper right corner, 90 deg is straight upward. That means all possible blue lines are from starting point to the right.
The y-axis is correct. To let cos(x) produce a negative number, x should be pi/2 to pi (90 deg to 180 deg). As cos(pi-x) == -cos(x)
, we will flip this angle when mouse is on the left side.
const can = document.getElementById('can');
const ctx = can.getContext('2d');
can.width = innerWidth;
can.height = innerHeight;
var length = 200;
var origin = {x: can.width / 2, y: can.height / 2};
var mousey;
var mousex;
function triangle(x1, y1, x2, y2){
ctx.strokeStyle = "blue";
ctx.lineWidth = "2";
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x2, y2);
ctx.lineTo(x2, y2 + (y1 - y2));
ctx.strokeStyle = "#33cc33";
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x2, y2 + (y1 - y2));
ctx.lineTo(x1, y1);
ctx.strokeStyle = "red";
ctx.stroke();
}
(function loop(){
ctx.clearRect(0, 0, can.width, can.height);
calc2(mousex, mousey);
requestAnimationFrame(loop);
})();
function update(){
calc2(mousex, mousey);
}
function calc2(x1, y1){
let x2 = origin.x;
let y2 = origin.y;
let opposite = y1 - y2;
let hypotenuse = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
let onLeft = x1 < x2 ? true : false;
let a = Math.asin(opposite / hypotenuse);
triangle(x2, y2, x2 + Math.cos(onLeft ? Math.PI - a : a) * length, y2 + Math.sin(a) * length)
}
addEventListener('mousemove', (e)=>{
mousey = e.clientY;
mousex = e.clientX;
});
<canvas id="can" width="400" height="400"></canvas>
Upvotes: 2