How to calculate slope of line if lines are perpendicular? - javascript

There are two points lastPoint and prePoint. They determine a line.
I try to calculate slope of this line using this:
let kbase = (lastPoint.Y - prePoint.Y) / (lastPoint.X - prePoint.X);
let bbase = lastPoint.Y - kbase * lastPoint.X; //y = kx + b -> y - kx;
let ybase = `${kbase} * x + ${bbase}`;
So, if Y are equals then kbase is zero, it means straight line equation is y = b.
After that I try to calculate slope of perpendicular line to the first line, but I get error, because 1 / kbase where kbase == 0.
let kh = -1 * (1 / kbase);
let bh = startPoint.Y - kh * startPoint.X;
let yh = `${kh} * x + ${bh}`;
How to find a slope of perpendicular line if line equation is y = b?

The explicit form of a line equation, y = mx + p does not allow to represent verticals, as the slope is infinite.
For your purposes, you can use the implicit form, ax + by + c = 0, which does not have this problem. An orthogonal line can be given the equation bx - ay + d = 0.

As others have said, the slope of a vertical line is undefined. This is just how it works mathematically, and there are no problems with your code, and your math is correct. As you have realized, a horizontal line is a function that follows the form y = ox+b and its slope is 0. The perpendicular line of a horizontal line results in a vertical line which is not a function. This means that there are several values of y that correspond to one value you of x. Here is why that is important.
The general way of calculating slop is the change in y over the change in x.
Because a vertical line is not a function, there are multiple y's for one x. Here is an example. Let's say that we had the equation x=5. Here are some points: (5,1),(5,2),(5,3)(5,7). If you calculated slope with the first two points, it would result in (2-1)/(5-5) which is 1/0, and if you calculated slope with the last two points,
it would result in (7-3)/(5-5) which is 4/0. If you continued to do this, you would have an infinite number of undefined values for the slope of a vertical line. Keep in mind that 1/0 does not necessarily equal 2/0 or 6/0.Even if you tried to find a horizontal line and take the inverse reciprocal, which you did, you would not be able to find a defined value.
For example, if slope is the change in y over the change in x, then the inverse reciprocal would be -1 * the change in x over the change in y. Let's say that we had the horizontal line y = 0x + 5. The coefficient of the x or slope is 0. Four points would be (5,5), (9,5), (3,5) (6,5), and the two slope calculations for the slope of the perpendicular line would be 4/0 and 3/0 which leads to the same situation as last time.
To conclude, the answer to your question "How to find a slope of perpendicular line if line equation is y = b?" is that there is no defined value for the slope of a perpendicular line, and you definitely wont find one through the code you are using.

Related

How to calculate the angle to shoot a bullet in order to hit a moving target?

I found one interesting project on that is requiring to calculate the angle to shoot a bullet in order to hit a moving object/target. There are five parameters that should be provided in this function. Here is the list of the arguments:
`xP` - last known x position of the target
`yP` - last known y position of the target
`xV` - last known x velocity of the target
`yV` - last known y velocity of the target
`bulletS` - the speed of the bullet
For example if I provide set of parameters like this:
xP yP xV yV bulletS
5 5 0 1 3
4 4 1 0 2
5 5 0 -1 3
So far I was able to calculate the distance but I'm not sure if that is correct. Here is example:
import java.lang.*;
public class Problem2 {
public static void main(String[] args) {
// Function takes arguments from the parameters table.
System.out.println(calculateShotAngle(10,10,1,0,2));
}
static double calculateShotAngle(float xP, float yP, float xV, float yV, float pSpeed) {
// Function equation to calculate distance
double distance = Math.pow(Math.sqrt(Math.pow((xV-xP),2) + Math.pow((yV-yP), 2)),2);
return distance;
}
}
Once I get the distance I should use speed of the bullet to get an angle. I'm trying to understand how this algorithm should work. I guess the distance between the target and the bullet should be calculated first then check if bullet reached the target. If anyone have an example or tips how this should be achieved please let me know. Thank you.
This problem is complicated but I will try to make a descriptive answer.
We need to establish some constants, like gravity (for now only gravity):
double gravity = 0.98;
// Add more constants if needed
After establishing the need constants we will do the calculations.
=========== PART 1 ===========
First you need to know where your target is moving by using the Projectile Motion Formula.
Here are the need variables for the target:
`xPT` - last known x position of the target
`yPT` - last known y position of the target
`xVT` - last known x velocity of the target
`yVT` - last known y velocity of the target
After that calculate the position of the target at time t.
Where:
Vx is the velocity along x-axis (You need to calculate this)
Vxo is the initial velocity along x-axis (the xVT)
Vy is the velocity along y-axis (You need to calculate this)
Vyo is the initial velocity along y-axis (the yVT)
g is the acceleration due to gravity
t is the time taken
Just start t at 1 then increment it. (Play with the initial value and increment to get the desired output)
=========== PART 2 ===========
After calculating the location of the target at time t, you then calculate the possible launch angle of the bullet given the position and speed if it can reach the position of the target at time t, if it can reach then the angle will be the answer, if not increment t
The needed variables for the bullet are:
`xPB` - last known x position of the bullet
`yPB` - last known y position of the bullet
`bulletS` - the speed of the bullet
The formula to calculate the angle is:
Where :
v is initial launch speed (this is bulletS)
g is the gravity constant
x is the x position of the target at time t (this is xPT)
y is the y position of the target at time t (this is yPT)
=========== PART 3 ===========
Using the angle, speed, initial position of the bullet check if the bullet can reach the target's position at time t
The formula is:
Where :
u is initial launch speed (this is bulletS)
g is the gravity constant
θ is the launch angle
Ux is initial x velocity of the bullet
Uy is initial y velocity of the bullet
After that calculate the position of the bullet at time t.
Where:
x is the x position of the bullet at time t
y is the y position of the bullet at time t
Vx is the velocity along x-axis (You need to calculate this)
Vxo is the initial velocity along x-axis (the Ux)
Vy is the velocity along y-axis (You need to calculate this)
Vyo is the initial velocity along y-axis (the Uy)
g is the acceleration due to gravity
t is the time taken
xPB - last known x position of the bullet
yPB - last known y position of the bullet
=========== PART 4 ===========
Now you have the need variables, which are:
`xPB` - last known x position of the bullet
`yPB` - last known y position of the bullet
`xPT` - last known x position of the target
`yPT` - last known y position of the target
Compare the above variables, if xPB is equal to xPT and yPB is equal to yPT then the bullet will hit the target at time t and at launch angle θ. If not then increment time t and do Part 1 until Part 4.
=========== SUMMARY ===========
This will be the flow of your program.
static double calculateShotAngle(
double xPT, double yPT, double xVT, double yVT,
double xPB, double yPB, double bulletS) {
double gravity = 0.98;
double angle = null;
double time = 1; // change this value if needed (try smaller increments if after a single increment the bullet's position will pass the target's position)
double xPTOriginal = xPt; // Save the initial x position of target
double yPTOriginal = yPt; // Save the initial y position of target
while (true) {
// do Part 1;
// do Part 2;
// do Part 3;
// below code is Part 4
if (hasBeenHit(xPT, yPT, xPB, yPB)) {
break;
} else {
t++; // increment t
// Revert the initial position of target
xPt = xPTOriginal;
yPt = yPTOriginal;
}
}
return angle;
}
// Method used to check if bullet hits the target
// Method assumes that bullet and target only occupies a point (1 of axis x and 1 of axis y)
static boolean hasBeenHit(double xPT, double yPT, double xPB, double yPB) {
return xPT == xPB && yPT == yPB;
}
I hope you understand my explanation (I've spent a lot of time making it. Haha) But if you have any questions/clarifications, feel free to comment it.
Assuming the bullet will be fired from origin (0,0).
If the bullet meets the target after time t, then equation would be:
(xP + xV * t, yP + yV * t) = ((bullets * t) * cos(angle), (bullets * t) * sin(angle))
Now, If you solve it, you will get
xP = (bullets * cos(angle) - xV) * t /* equation 1 */
yP = (bullets * sin(angle) - yV) * t /* equation 2 */
Dividing equation 1 with equation 2 you get:
xP * sin(angle) - yP * sin(angle) = (xP * yV - xV * yP) / bullets
Now, if you assume m = sin(angle), then cos(angle) = sqrt(1 - m * m)
So now, you have to solve the equation:
xP * m - yP * sqrt(1 - m * m) = (xP * yV - xV * yP) / bullets
Move the term with square root on one side and the rest on other, so that you get a quadratic equation after squaring and you can solve that equation to get 2 valuee in terms of m = sin(angle)
So, the final angle is angle = arcsin(m)

How can I offset a global directional force to be applied over a local axis?

I want to apply a forward force in relation to the object's local axis, but the engine I'm using only allows to me apply a force over the global axis.
I have access to the object's global rotation as a quaternion. I'm not familiar with using quats however (generally untrained in advanced maths). Is that sufficient information to offset the applied force along the desired axis? How?
For example, to move forward globally I would do:
this.entity.rigidbody.applyForce(0, 0, 5);
but to keep that force applied along the object's local axis, I need to distribute the applied force in a different way along the axes, based on the object's rotational quat, for example:
w:0.5785385966300964
x:0
y:-0.815654993057251
z:0
I've researched quaternions trying to figure this out, but watching a video on what they are and why they're used hasn't helped me figure out how to actually work with them to even begin to figure out how to apply the offset needed here.
What I've tried so far was sort of a guess on how to do it, but it's wrong:
Math.degrees = function(radians) {
return radians * 180 / Math.PI;
};
//converted this from a python func on wikipedia,
//not sure if it's working properly or not
function convertQuatToEuler(w, x, y, z){
ysqr = y * y;
t0 = 2 * (w * x + y * z);
t1 = 1 - 2 * (x * x + ysqr);
X = Math.degrees(Math.atan2(t0, t1));
t2 = 2 * (w * y - z * x);
t2 = (t2 >= 1) ? 1 : t2;
t2 = (t2 < -1) ? -1 : t2;
Y = Math.degrees(Math.asin(t2));
t3 = 2 * (w * z + x * y);
t4 = 1 - 2 * (ysqr + z * z);
Z = Math.degrees(Math.atan2(t3, t4));
console.log('converted', {w, x, y, z}, 'to', {X, Y, Z});
return {X, Y, Z};
}
function applyGlobalShift(x, y, z, quat) {
var euler = convertQuatToEuler(quat.w, quat.x, quat.y, quat.z);
x = x - euler.X; // total guess
y = y - euler.Y; // total guess
z = z - euler.Z; // total guess
console.log('converted', quat, 'to', [x, y, z]);
return [x, y, z];
}
// represents the entity's current local rotation in space
var quat = {
w:0.6310858726501465,
x:0,
y:-0.7757129669189453,
z:0
}
console.log(applyGlobalShift(-5, 0, 0, quat));
Don't laugh at my terrible guess at how to calculate the offset :P I knew it was not even close but I'm really bad at math
Quaternions are used as a replacement for euler angles. Your approach, thus, defeats their purpose. Instead of trying to use euler angles, levy the properties of a quaternion.
A quaternion has 4 components, 3 vector components and a scalar component.
q = x*i + y*j + z*k + w
A quaternion therefore has a vector part x*i + y*j + z*k and a scalar part w. A vector is thus a quaternion with a zero scalar or real component.
It is important to note that a vector multiplied by a quaternion is another vector. This can be easily proved by using the rules of multiplication of quaternion basis elements (left as an exercise for the reader).
The inverse of a quaternion is simply its conjugate divided by its magnitude. The conjugate of a quaternion w + (x*i + y*j + z*k) is simply w - (x*i + y*j + z*k), and its magnitude is sqrt(x*x + y*y + z*z + w*w).
A rotation of a vector is simply the vector obtained by rotating that vector through an angle about an axis. Rotation quaternions represent such an angle-axis rotation as shown here.
A vector v can be rotated about the axis and through the angle represented by a rotation quaternion q by conjugating v by q. In other words,
v' = q * v * inverse(q)
Where v' is the rotated vector and q * v * inverse(q) is the conjugation operation.
Since the quaternion represents a rotation, it can be reasonably assumed that its magnitude is one, making inverse(q) = q* where q* is the conjugate of q.
On separating q into real part s and vector part u and simplifying the quaternion operation (as beautifully shown here),
v' = 2 * dot(u, v) * u + (s*s - dot(u, u)) * v + 2 * s * cross(u, v)
Where dot returns the dot product of two vectors, and cross returns the cross product of two vectors.
Putting the above into (pseudo)code,
function rotate(v: vector3, q: quaternion4) -> vector3 {
u = vector3(q.x, q.y, q.z)
s = q.w
return 2 * dot(u, v) * u + (s*s - dot(u, u)) * v + 2 * s * cross(u, v)
}
Now that we know how to rotate a vector with a quaternion, we can use the world (global) rotation quaternion to find the corresponding world direction (or axis) for a local direction by conjugating the local direction by the rotation quaternion.
The local forward axis is always given by 0*i + 0*j + 1*k. Therefore, to find the world forward axis for an object, you must conjugate the vector (0, 0, 1) with the world rotation quaternion.
Using the function defined above, the forward axis becomes
forward = rotate(vector3(0, 0, 1), rotationQuaternion)
Now that you have the world forward axis, a force applied along it will simply be a scalar multiple of the world forward axis.

Javascript Determine if a point resides above or below a line defined by two points

I am trying to calculate if a point resides above or below a line that is defined by two points. For clarification I only need to know if the point is on "this side" or "that side". I realize if the line is perfectly vertical there will be no "above" or "below". I have a line defined by two points (centerX, centerY) and (xprime, yprime). For simplicity centerX, centerY can be converted to (0,0). I want to determine if (mouseX, mouseY) is above or below that line.
I have tried to use this formula but it is not giving me the results I expected.
var position = Math.sin((xprime -centerX) * (mouseY - centerY) - (yprime - centerY) * (mouseX - prime));
The values for position seem to oscillate randomly from positive to negative as mouseX,mouseY values rotate around the line. I was under the impression the sign would change one time from positive to negative as the mouse position (mouseX,mouseY) crossed over the line. Values above the line would be positive, and values below would be negative.
I am using this code in conjunction with a formula to determine the angle of deflection from the original click. But I am not able to determine if the mouse is now above the initial click, or below. (again please excuse "above" and "below")
Simple solution exploiting cross product properties.
dx = xprime - centerX
dy = yprime - centerY
mx = mouseX - centerX
my = mouseY - centerY
cross = dx * my - dy * mx //zero means point on line
below = (cross > 0) //mouse is "at the right hand" of the directed line
if dx <> 0 then // check for vertical line
if dy/dx < 0 then //negative slope, invert result
below = not below
I'll try to give you general solution.
How to check if exact point is above or below line function:
Just imagine, we have line f(x) = 4x + 2. We need check, if point (x1, y1) below or above the line, we need to calculate f(x1) and compare it with y1.
if f(x1) > y1 it means, that (x1, y1) below the line.
if f(x1) < y1 means point (x1, y1) above the line.
if f(x1) = y1 - point on a line.
You can see on plot:
All line functions looks like f(x) = k * x + b, so, you need know k and b constants to know exact line function.
How to get line function by two points:
Imagine points A (x_a, y_a) and B (x_b, y_b) and we want to get line function, we need to solve system of two equations:
y_a = k * x_a + b
y_b = k * x_b + b
That is very easy. After you will know k and b and after you can check if point below or above AB line

So I have a triangle with the point (100, 90) the distance (11) and the angle of the line (45º) Can I find the other point of the line? How?

okay so I am trying to draw a triangle, the triangle can be completely random, on a canvas in JavaScript
so I got the angles and the side for triangle ABC(this is not what I'm calling it in the code)
the sides
AB(11)
AC(12)
BC(13)
the angles which are solved in a function
BAC(69)
ABC(52)
BCA(59)
And the starting Point of the triangle at (100, 90)
The question I am having is how do I find the other points to the Triangle
I thought the easiest way to draw it would be to draw a line that goes to each point
So I tired the mathematics with this code (I found on another page but )
function FindTriPoints(){
//Y2 = H(Sin(A)) + Y1
//X2 = Sqrt((H^2)-(Y2^2)) + X1
pointX1 = 100;
pointY1 = 90;
pointY2 = s3 * (Math.sin(angle1*Math.PI/180)) + pointY1;
pointX2 = Math.sqrt((s3 * s3) - (pointY2 * pointY2)) + pointX1;
alert("X2 = " + pointX2 + "\n Y2 = " + pointY2)
}
but X2 ends up becoming NaN because it is a negative value that it is trying to square root.
Edit Thanks to Cbroe and Jing3142 for helping me with Y2
well if you know valid triangle sides lengths (l1,l2,l3) and their angles (a,b,c) ...
then it is quite simple with vector math ...
// compute directions
a1=0;
a2=180-b;
a3=a2+180-c;
a3=-b-c;
a3=-a;
// convert them from [deg] to [rad]
a1*=Math.pi/180.0;
a2*=Math.pi/180.0;
a3*=Math.pi/180.0;
// compute points
A=(x0,y0); // your start point is known
B=A+l1*dir(a0)=(x0+l1*Math.cos(a0),y0+l1*Math.sin(a0));
B=A+l1*dir( 0)=(x0+l1 ,y0 ); // a0 is always zero
C=A-l3*dir(a3)=(x0-l3*Math.cos(a3),y0-l3*Math.sin(a3)); // C from A point
C=B+l2*dir(a2)=(x0+l1+l2*Math.cos(a2),y0+l2*Math.sin(a2)); // C from B point
[notes]
as you can see there are more alternatives for some variables choose one you like
do not forget to check if l1+l2>l3 and l1+l3>l2 and l2+l3>l1
if not then your lengths are not valid triangle sides
also a+b+c = 180
if not then your angle computation is wrong
if you want to over-check the triangle then compute C from A and from B point
if they are not the same (their distance > some accuracy constant like 0.001)
then it is not a valid triangle

How to find the postion of this point (canvas)?

http://img684.imageshack.us/img684/9305/fffnv.png
Do i need to solve a math, is there a easy way to solve this problem?
First you compute the angle of the line from second to first point
var angle = Math.atan2(first.y - second.y, first.x - second.x);
then you compute the resulting point using sin and cos
var result = {x : second.x + z*Math.cos(angle + Math.PI/2),
y : second.y + z*Math.sin(angle + Math.PI/2)};
Obviously you do need some math to get this going.
Math.atan ((y-y')/(x-x')) will get you the angle (in Radians) of the first line from the horrizon.
Add Pi/2 (90 degrees) to this angle to get the angle of the z line.
You can then use Math.sin and Math.cos `multiplied by z to find the coordinates of the third point.

Categories