How to rotate one vector on another? - javascript

I need to place vector b(p2, p3) on vector a(p1, p2)
Could you advise me some formula?

If you need angle to rotate, calculate it as
dAx = P1.x - P2.x
dAy = P1.y - P2.y
dBx = P3.x - P2.x
dBy = P2.y - P2y
an = atan2(dAx * dBy - dAy * dBx, dAx * dBx + dAy * dBy)
but your picture perhaps shows that you need to just make vector with length of P2P3 but collinear with P2P1. In this case:
-calculate length of both vectors
-find normalized direction vector for P2P1 - get it's component nad divide by vector length
-multiply components of normalized vector by length of P2P3

Related

getting the radius from a data point plotted on a radialLine

In short, I have a spiral plot and dates are mapped on to this. This works fine but I now want to map date ranges on this same spiral. This spiral is produced using d3.radialLine. I can get the angle of each data point from using math.atan2(x,y), but how can I get the radius of each data point?
Math.hypot calculates the distance between two points:
const distance = Math.hypot(ax - bx, ay - by);
Similar to:
const dx = ax - bx;
const dy = ay - by;
const distance = Math.sqrt(dx * dx + dy * dy);
This works: radius = Math.sqrt(((x-0)*(x-0))+((y-0)*(y-0))).
However, if there is a more elegant way to write this let me know

Calculate distance between two rotated elements

Hi I want to calculate the perpendicular distance between two rotated elements, when rotation is 0 I use el1.getBoundingClientRect().x - el2.getBoundingClientRect().x and it gives me right distance, but for rotated elements, it does not work as it gives the perpendicular distance between the vertexes (the distance of bounding rectangles, how can I get x? thanks!
https://codesandbox.io/s/epic-thunder-mxqbc?file=/src/index.js
If differences of vertex coordinates of two rectangles before rotation were (dx, dy), then after rotattion by angle fi new differences are:
nx = dx * cos(fi) - dy * sin(fi)
ny = dx * sin(fi) + dy * cos(fi)
If we multiply the first equation by cos(fi) and the second one by sin(fi), then add them, we can find needed value
dx = nx * cos(fi) + ny * sin(fi)
(assuming you know vertex difference in rotated state)
For example below: dx was 25, cos(fi)=4/5, sin(fi)=3/5
After rotation: nx = 5, ny = 35, we can find dx = 5*4/5 + 25*3/5 = 4+21 = 25

need to make a ball travel in the angle it was hit from

self.hitBall = function(ball, x, y) {
var angle = Math.atan2((x - ball.centerX), (y - ball.centerY));
ball.velocityY = (Math.sin(angle) * 10);
ball.velocityX = (Math.cos(angle) * 10);
};
So the function takes in the ball, which has a centerX variable and a centerY variabe. The x and y passed into the function is the x and y is the point the ball was hit. I want to make the ball travel in the direction it was hit from.
Not really sure why my code isn't working.. it's behaving very strangely and I'm not that good with trigonometry so I'm not really quite sure why it isn't working.
Two problems with your code:
Math.atan2() takes the arguments in (y, x) order. Most languages (Java, JavaScript, C, etc.) do this (except Microsoft Excel and some others, which use (x, y) order).
When you say "[make] the ball travel in the angle it was hit from", you want to subtract the hit point from the ball point. In other words, the vector is (ball.centerX - hitX, ball.centerY - hitY).
Thus, the solutions:
Solution 1:
var angle = Math.atan2((ball.centerY - y), (ball.centerX - x));
Solution 2 - do vector math without angles (equivalent calculation):
var dx = ball.centerX - x;
var dy = ball.centerY - y;
var norm = Math.sqrt(dx * dx + dy * dy);
ball.velocityX = (dx / norm) * 10;
ball.velocityY = (dy / norm) * 10;

Calculate angle of triangle with sin or cos

I'm trying to calculate an angle based on triangle sides, preferably with sin.
The first 2 are helper functions getDistance and getPointsDifference
I have these functions:
var getDistance = function(p1, p2){
var dx = p1.x - p2.x, dy = p1.y - p2.y;
return Math.sqrt(dx*dx + dy*dy);
}
var getPointsDifference = function(p1, p2){
return {
x: -1 * (p1.x - p2.x),
y: (p1.y - p2.y)
}
}
and finaly:
var getMenuChoice = function(cx,cy, x, y){
var distance = getDistance({x:cx,y:cy}, {x:x,y:y});
if (distance <= 100) {
console.log(1)
} else {
console.log(2)
}
var diff = getPointsDifference({x:cx,y:cy}, {x:x,y:y});
var a = Math.sin(diff.y/distance)
console.log("asdf:", a)
}
Could someone please show me what am I doing wrong? I would like to calculate the result in degrees.
update
I detect a lick on the screen which gives me a x,y, and then I subtract those x,y from cx and cy which are the center of the screen
This is called the angle (or direction) of the vector from (or to, depends on what you need) point of click to the center of the screen. There is no need in calculation of the distance and arcsin of the angle (instead of yours sin) - you can just use Math.atan2(dy, dx);.
dy is change in y (y2 - y1) and dx is change in x (x2 - x1) between those two points. You can use a regular Math.atan(dy / dx), but then you must be sure that you are not dividing by zero and have to take into account the signs of dy and dx to have answer in the correct quadrant. Math.atan2 will do it all for you. And the picture below is just a reminder.
And yes, the answer will be in radians, as it was mentioned in comments. Conversion is simple degrees = radians * (180 / Math.PI);

How to calculate rotation in 2D in Javascript

I am not so familiar trigonometry, but I have only two points to rotate in 2D:
*nx, ny
. -
. -
. angle -
*cx,cy.................*x,y
cx, cy = rotation center
x,y = current x,y
nx, ny = new coordinates
How to calculate new points in a certain angle?
function rotate(cx, cy, x, y, angle) {
var radians = (Math.PI / 180) * angle,
cos = Math.cos(radians),
sin = Math.sin(radians),
nx = (cos * (x - cx)) + (sin * (y - cy)) + cx,
ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;
return [nx, ny];
}
The first two parameters are the X and Y coordinates of the central point (the origin around which the second point will be rotated). The next two parameters are the coordinates of the point that we'll be rotating. The last parameter is the angle, in degrees.
As an example, we'll take the point (2, 1) and rotate it around the point (1, 1) by 90 degrees clockwise.
rotate(1, 1, 2, 1, 90);
// > [1, 0]
Three notes about this function:
For clockwise rotation, the last parameter angle should be positive. For counterclockwise rotation (like in the diagram you provided), it should be negative.
Note that even if you provide arguments that should yield a point whose coordinates are whole numbers -- i.e. rotating the point (5, 0) by 90 degrees about the origin (0, 0), which should yield (0, -5) -- JavaScript's rounding behavior means that either coordinate could still be a value that's frustratingly close to the expected whole number, but is still a float. For example:
rotate(0, 0, 5, 0, 90);
// > [3.061616997868383e-16, -5]
For this reason, both elements of the resulting array should be expected as a float. You can convert them to integers using Math.round(), Math.ceil(), or Math.floor() as needed.
Finally, note that this function assumes a Cartesian coordinate system, meaning that values on the Y axis become higher as you go "up" in the coordinate plane. In HTML / CSS, the Y axis is inverted -- values on the Y axis become higher as you move down the page.
First, translate the rotation center to the origin
Calculate the new coordinates (nx, ny)
Translate back to the original rotation center
Step 1
Your new points are
center: (0,0)
point: (x-cx, y-cy)
Step 2
nx = (x-cx)*cos(theta) - (y-cy)*sin(theta)
ny = (y-cy)*cos(theta) + (x-cx)*sin(theta)
Step 3
Translate back to original rotation center:
nx = (x-cx)*cos(theta) - (y-cy)*sin(theta) + cx
ny = (y-cy)*cos(theta) + (x-cx)*sin(theta) + cy
For deeper explanation, with some fancy diagrams, I recommend looking at this.
above accepted answer not work for me correctly, rotation are reversed , here is working function
/*
CX # Origin X
CY # Origin Y
X # Point X to be rotated
Y # Point Y to be rotated
anticlock_wise # to rotate point in clockwise direction or anticlockwise , default clockwise
return # {x,y}
*/
function rotate(cx, cy, x, y, angle,anticlock_wise = false) {
if(angle == 0){
return {x:parseFloat(x), y:parseFloat(y)};
}if(anticlock_wise){
var radians = (Math.PI / 180) * angle;
}else{
var radians = (Math.PI / -180) * angle;
}
var cos = Math.cos(radians);
var sin = Math.sin(radians);
var nx = (cos * (x - cx)) + (sin * (y - cy)) + cx;
var ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;
return {x:nx, y:ny};
}
According to Polar coordinate system artycle on Wikipedia:
x = r * cos(deg)
y = r * sin(deg)
r (radius) is equal to distance between Rotation Centre and Rotated Point
deg (degrees) is angle measured in degrees
I think it is better to use matrices for such operations.
Here is the example with gl-matrix (but you can use something like THREEJS as well).
import * as glm from 'gl-matrix';
const rotateVector = (() => {
const q = glm.quat.create();
// const m = glm.mat4.create(); // 2nd way
return (v: glm.vec3, point: glm.vec3, axis: glm.vec3, angle: number) => {
glm.quat.setAxisAngle(q, axis, angle);
// glm.mat4.fromRotation(m, angle, axis); // 2nd way
glm.vec3.sub(v, v, point);
glm.vec3.transformQuat(v, v, q);
// glm.vec3.transformMat4(v, v, m); // 2nd way
glm.vec3.add(v, v, point);
return v;
}
})();
In 2D case you need to rotate around z-axis:
rotateVector([x, y, 0], [cX, cY, 0], [0, 0, 1], angleInRadians);

Categories