Find angle from two points formula - formula

I have question about the formula to calculate the Angle between two points p1(x1,y1), p2(x2,y2).
I use this formula :
angle = arctan(y2-y1/x2-x1)
Can you explain, why y2,y1 and x2,x1 must be subtracted ?
Thanks

tan, sin, and cos are actually measuring the ratios between two edges of a 3-edged object aka a triangle.
Hence in your case, to form that triangle, you will need the lengths of two edges. They are the lengths between y1 and y2, and x1 and x2.
That is why you deduct y1 from y2 and x1 from x2.
In fact, you have to ensure that the signs are correct too, else you will get a different angle as your answer.

According to Wikipedia's article on inverse trigonometric functions (which includes the arctangent function), they are 'used to obtain an angle from any of the angle's trigonometric ratios' i.e. the y-component compared to the x-component of the vector you're looking at. Your vector starts at (x1, y1) so subtracting those components from second point effectively centers the vector at (0, 0), then dividing the y-component by the x-component will give you the trigonometric ratio (aka gradient in this case) that can be passed through the arctan function to get the angle.
On an implementation note, you will want to use an arctan2 function to prevent a divide-by-zero error in the case of a vertical line. A vertical line has an infinite gradient which computers don't deal with. The arctan2 function will accept the x and y components separately, side stepping the issue. See the documentation for Java or Python for example.

Related

Having 3 vectors, how to check that a straight line can be drawn through them

I get the positions of 5 enemies in the game in vectors. Depending on the distance I choose, the number of enemies can vary from 0 to 5. I need to know their vectors each time to check whether it is possible to draw a straight line through a certain number of heroes (vectors).
After that, my hero will have to use his ability called wall. It consists of 2 start and end vectors. Thus, check whether my hero can put a wall on the enemies in the line to catch them
Let's say there are 3 enemy heroes whose positions I can get. I need to find out if I can pass through them directly, in order to use the ability on them.
Here's what using the ability looks like in the game
Here is getting the vector of one of the heroes
The ability itself can be twisted at a certain point. But anyway, it is necessary that the wall would touch several heroes
Wherever I move the mouse, I can put it in the desired position. But unfortunately it takes a lot of time, so I would like to automate
The coordinates of the wall itself, or rather its two edges, I can also get, but only after the ability has been used
If one prefers geometry to linear algebra...
Then One can compute the dot product of (unit-vector1. Unit-Vector2). That is equal to the SIN of the angle between them.
So if unit vector is the shooter position to target1, unit vector2 is the shooter to target2, etc... then when DOTPRODUCT(Vector1,vector2) = 1 and DOTPRODUCT(Vector1,vector3) = 1, then the three points are in syzygy.
And repeat from shooter to as many targets as you have to determine whether some or all of the points are in syzygy.
From your statement that there is a start and an endpoint I take that you select two enemys and want to trap anything in between.
So you're actually not looking for a straight line that can be drawn through your enemy positions but if they are withn a rectangle. It would be very unlikely and for more points nearly impossible that they are all collinear anyway.
So it becomes quite trivial. You draw a line through start and end enemy. Then you check the remaining enemies distance to that line vs the width of your AoE. Maye you want to also handle some body width in that calculation.
https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
You can describe all points belonging to line (x0, y0) + (dx, dy)t = (x1, y1). Chose any two points and t as 1 and you will get (dx, dy) for line connecting two dots. Now you will need to find distance between this line and (x2, y2). it is distance between (x2, y2) and (xd, yd), where on one hand (xd, yd) = (x0, y0) + t1(dx, dy) and on other hand (xd, yd) = (x2, y2) + t2*(-dy, dx). Solving this two equations you will find t1, t2, (xd, yd) and distance between (x2, y2) and (xd, yd), which is distance between (x2, y2) and line, connecting (x0, y0) and (x1, y1).
Knowing this, you select dots with min_x and max_x and calculate ditance between line, connecting said dots and rest of the dots. If distance is lesser then some threshold of your choice, then you can assume that you can have line passing through all dots.
Any line in the plane can be described by an equation a*x + b*y + c = 0 with (a, b) ≠ (0, 0). Note that if you have an equation of this form, then multiplying each coefficient a, b, c with the same number yields an equation describing the same line. That's the reason (a, b, c) is called a homogeneous coordinate vector for that line.
How do you find a, b, c? One simple approach would be treating this as three linear equations in three unknowns. You plug in the x and y coordinates for all your three points, and get tree equations for a thorough c. However, there is a catch. Since the right hand side of each equation is zero, a = b = c = 0 is always a solution. In those cases where there is only one solution, that will be it. So in order for there to be a line, you need more than one solution. The mathematical tool to determine whether a set of equations had more than one solution is the determinant. It is zero if the system has no single unique solution.
Long story short: three points are collinear (on a line) if
⎛x1 y1 1⎞
det ⎜x2 y2 1⎟ = 0
⎝x3 y3 1⎠
The homogeneous coordinate vector describing the line world correspond to the kernel of that matrix.
Of course, if your input coordinates are floating point numbers, exact zero is unlikely. Presumably that wall does allow for some error in some way, and you'd need to tell us about that in order to get an answer that models this aspect correctly. In the mean time, know that the absolute value of the determinant above is proportional to the area of the triangle created by these three points. So if your were to pick a constant threshold value, the farther your enemies are apart along the direction of the wall, the less they could deviate from the straight line without violating that threshold.

Understanding mean curvature of a 3D surface

I am currently trying to understand the calculation of the mean curvature for a 3D surface, where one coordinate is a function of the other two coordinates.
Looking at wikipedia https://en.wikipedia.org/wiki/Mean_curvature#Surfaces_in_3D_space under "[For the special case of a surface defined as a function of two coordinates, e.g. z = S(x,y)]" they give this formula:
mean curvature
What i don't understand here is the div(z - S) . If z = S(x,y) then i would think that z is the same as S and thus z - S equals 0.
I tried to follow the cited literature but i didn't find what i was looking for.
Apparently i misunderstand something here and z is not the same as S?
Any help would be appreciated.
z-S(x,y) is a function of 3 variables, the gradient of which is (-S_x,-S_y,1), see the second line. Then you normalize this gradient vector and compute the divergence of the normalized vector field.

The X angle between two 3D vectors?

I have two 3D vectors called A and B that both only have a 3D position. I know how to find the angle along the unit circle ranging from 0-360 degrees with the atan2 function by doing:
EDIT: (my atan2 function made no sense, now it should find the "y-angle" between 2 vectors):
toDegrees(atan2(A.x-B.x,A.z-B.z))+180
But that gives me the Y angle between the 2 vectors.
I need to find the X angle between them. It has to do with using the x, y and z position values. Not the x and z only, because that gives the Y angle between the two vectors.
I need the X angle, I know it sounds vague but I don't know how to explain. Maybe for example you have a camera in 3D space, if you look up or down than you rotate the x-axis. But now I need to get the "up/down" angle between the 2 vectors. If I rotate that 3D camera along the y-axis, the x-axis doens't change. So with the 2 vectors, no matter what the "y-angle" is between them, the x-angle between the 2 vectors wil stay the same if y-angle changes because it's the "up/down" angle, like in the camara.
Please help? I just need a line of math/pseudocode, or explanation. :)
atan2(crossproduct.length,scalarproduct)
The reason for using atan2 instead of arccos or arcsin is accuracy. arccos behaves very badly close to 0 degrees. Small computation errors in argument will lead to disproportionally big errors in result. arcsin has same problem close to 90 degrees.
Computing the altitude angle
OK, it might be I finally understood your comment below about the result being independent of the y angle, and about how it relates to the two vectors. It seems you are not really interested in two vectors and the angle between these two, but instead you're interested in the difference vector and the angle that one forms against the horizontal plane. In a horizontal coordinate system (often used in astronomy), that angle would be called “altitude” or “elevation”, as opposed to the “azimuth” you compute with the formula in your (edited) question. “altitude” closely relates to the “tilt” of your camera, whereas “azimuth” relates to “panning”.
We still have a 2D problem. One coordinate of the 2D vector is the y coordinate of the difference vector. The other coordinate is the length of the vector after projecting it on the horizontal plane, i.e. sqrt(x*x + z*z). The final solution would be
x = A.x - B.x
y = A.y - B.y
z = A.z - B.z
alt = toDegrees(atan2(y, sqrt(x*x + z*z)))
az = toDegrees(atan2(-x, -z))
The order (A - B as opposed to B - A) was chosen such that “A above B” yields a positive y and therefore a positive altitude, in accordance with your comment below. The minus signs in the azimuth computation above should replace the + 180 in the code from your question, except that the range now is [-180, 180] instead of your [0, 360]. Just to give you an alternative, choose whichever you prefer. In effect you compute the azimuth of B - A either way. The fact that you use a different order for these two angles might be somewhat confusing, so think about whether this really is what you want, or whether you want to reverse the sign of the altitude or change the azimuth by 180°.
Orthogonal projection
For reference, I'll include my original answer below, for those who are actually looking for the angle of rotation around some fixed x axis, the way the original question suggested.
If this x angle you mention in your question is indeed the angle of rotation around the x axis, as the camera example suggests, then you might want to think about it this way: set the x coordinate to zero, and you will end up with 2D vectors in the y-z plane. You can think of this as an orthogonal projection onto said plain. Now you are back to a 2D problem and can tackle it there.
Personally I'd simply call atan2 twice, once for each vector, and subtract the resulting angles:
toDegrees(atan2(A.z, A.y) - atan2(B.z, B.y))
The x=0 is implicit in the above formula simply because I only operate on y and z.
I haven't fully understood the logic behind your single atan2 call yet, but the fact that I have to think about it this long indicates that I wouldn't want to maintain it, at least not without a good explanatory comment.
I hope I understood your question correctly, and this is the thing you're looking for.
Just like 2D Vectors , you calculate their angle by solving cos of their Dot Product
You don't need atan, you always go for the dot product since its a fundamental operation of vectors and then use acos to get the angle.
double angleInDegrees = acos ( cos(theta) ) * 180.0 / PI;

Finding the coordinates of points from distance matrix

I have a set of points (with unknow coordinates) and the distance matrix. I need to find the coordinates of these points in order to plot them and show the solution of my algorithm.
I can set one of these points in the coordinate (0,0) to simpify, and find the others. Can anyone tell me if it's possible to find the coordinates of the other points, and if yes, how?
Thanks in advance!
EDIT
Forgot to say that I need the coordinates on x-y only
The answers based on angles are cumbersome to implement and can't be easily generalized to data in higher dimensions. A better approach is that mentioned in my and WimC's answers here: given the distance matrix D(i, j), define
M(i, j) = 0.5*(D(1, j)^2 + D(i, 1)^2 - D(i, j)^2)
which should be a positive semi-definite matrix with rank equal to the minimal Euclidean dimension k in which the points can be embedded. The coordinates of the points can then be obtained from the k eigenvectors v(i) of M corresponding to non-zero eigenvalues q(i): place the vectors sqrt(q(i))*v(i) as columns in an n x k matrix X; then each row of X is a point. In other words, sqrt(q(i))*v(i) gives the ith component of all of the points.
The eigenvalues and eigenvectors of a matrix can be obtained easily in most programming languages (e.g., using GSL in C/C++, using the built-in function eig in Matlab, using Numpy in Python, etc.)
Note that this particular method always places the first point at the origin, but any rotation, reflection, or translation of the points will also satisfy the original distance matrix.
Step 1, arbitrarily assign one point P1 as (0,0).
Step 2, arbitrarily assign one point P2 along the positive x axis. (0, Dp1p2)
Step 3, find a point P3 such that
Dp1p2 ~= Dp1p3+Dp2p3
Dp1p3 ~= Dp1p2+Dp2p3
Dp2p3 ~= Dp1p3+Dp1p2
and set that point in the "positive" y domain (if it meets any of these criteria, the point should be placed on the P1P2 axis).
Use the cosine law to determine the distance:
cos (A) = (Dp1p2^2 + Dp1p3^2 - Dp2p3^2)/(2*Dp1p2* Dp1p3)
P3 = (Dp1p3 * cos (A), Dp1p3 * sin(A))
You have now successfully built an orthonormal space and placed three points in that space.
Step 4: To determine all the other points, repeat step 3, to give you a tentative y coordinate.
(Xn, Yn).
Compare the distance {(Xn, Yn), (X3, Y3)} to Dp3pn in your matrix. If it is identical, you have successfully identified the coordinate for point n. Otherwise, the point n is at (Xn, -Yn).
Note there is an alternative to step 4, but it is too much math for a Saturday afternoon
If for points p, q, and r you have pq, qr, and rp in your matrix, you have a triangle.
Wherever you have a triangle in your matrix you can compute one of two solutions for that triangle (independent of a euclidean transform of the triangle on the plane). That is, for each triangle you compute, it's mirror image is also a triangle that satisfies the distance constraints on p, q, and r. The fact that there are two solutions even for a triangle leads to the chirality problem: You have to choose the chirality (orientation) of each triangle, and not all choices may lead to a feasible solution to the problem.
Nevertheless, I have some suggestions. If the number entries is small, consider using simulated annealing. You could incorporate chirality into the annealing step. This will be slow for large systems, and it may not converge to a perfect solution, but for some problems it's the best you and do.
The second suggestion will not give you a perfect solution, but it will distribute the error: the method of least squares. In your case the objective function will be the error between the distances in your matrix, and actual distances between your points.
This is a math problem. To derive coordinate matrix X only given by its distance matrix.
However there is an efficient solution to this -- Multidimensional Scaling, that do some linear algebra. Simply put, it requires a pairwise Euclidean distance matrix D, and the output is the estimated coordinate Y (perhaps rotated), which is a proximation to X. For programming reason, just use SciKit.manifold.MDS in Python.
The "eigenvector" method given by the favourite replies above is very general and automatically outputs a set of coordinates as the OP requested, however I noticed that that algorithm does not even ask for a desired orientation (rotation angle) for the frame of the output points, the algorithm chooses that orientation all by itself!
People who use it might want to know at what angle the frame will be tipped before hand so I found an equation which gives the answer for the case of up to three input points, however I have not had time to generalize it to n-points and hope someone will do that and add it to this discussion. Here are the three angles the output sides will form with the x-axis as a function of the input side lengths:
angle side a = arcsin(sqrt(((c+b+a)*(c+b-a)*(c-b+a)*(-c+b+a)*(c^2-b^2)^2)/(a^4*((c^2+b^2-a^2)^2+(c^2-b^2)^2))))*180/Pi/2
angle side b = arcsin(sqrt(((c+b+a)*(c+b-a)*(c-b+a)*(-c+b+a)*(c^2+b^2-a^2)^2)/(4*b^4*((c^2+b^2-a^2)^2+(c^2-b^2)^2))))*180/Pi/2
angle side c = arcsin(sqrt(((c+b+a)*(c+b-a)*(c-b+a)*(-c+b+a)*(c^2+b^2-a^2)^2)/(4*c^4*((c^2+b^2-a^2)^2+(c^2-b^2)^2))))*180/Pi/2
Those equations also lead directly to a solution to the OP's problem of finding the coordinates for each point because: the side lengths are already given from the OP as the input, and my equations give the slope of each side versus the x-axis of the solution, thus revealing the vector for each side of the polygon answer, and summing those sides through vector addition up to a desired vertex will produce the coordinate of that vertex. So if anyone can extend my angle equations to handling beyond three input lengths (but I note: that might be impossible?), it might be a very fast way to the general solution of the OP's question, since slow parts of the algorithms that people gave above like "least square fitting" or "matrix equation solving" might be avoidable.

3D Rotation without Trigonometry?

I am developing a rotate-around-axis algorithm in 3 dimensions. My inputs are
the axis I am revolving around, as a vector from my center point
the center point (obviously)
the angle I wish to rotate around
my current position
I am wondering if there is a way to do this without trigonometry, just with vector operations. Does anyone have a potential solution?
EDIT: Is there a way that I could rotate by pi/4 radians (45 degrees) each time, rather than an inputted angle theta? This might simplify things a bit, I don't know.
Rotations are inherently well-described by and .
It's a handy trick that unit quaternions nicely represent 3-D rotations just as well as (and in some senses, better than) rotation matrices. Converting a rotation by angle about a normal axis where , does require a little bit of trigonometry: .
But from there on it's simple arithmetic.
A quaternion can be directly applied to rotate a vector with , or converted to a rotation matrix .
This is a rotation around the origin, of course. To rotate around an arbitrary point in space, simply translate by to the origin, rotate, then translate by to return.
use matrices: http://en.wikipedia.org/wiki/Rotation_matrix#Rotations_in_three_dimensions
If this is some sort of dumb homework problem, you can use Taylor Series approximation of the sine/consine functions. Whether or not this "counts" as trigonometry is I guess up for debate. You could then use these values in a rotation matrix or quarternion, if you want to use vector operations.
But again, there's no practical reason to do this.
Are there other techniques that don't use trig functions? Possibly, but there are no know efficient, general (i.e. for arbitrary angles) ways to perform rotations without use of trig functions.
However, based on your edit, you can precompute the sin and cos for a collection of angles you're interested in and store them in a lookup table. You need not be constrained in such a circumstance to π/4 increments, but you can do π/256 or π/1024 increments if you want. Also, you don't need two tables, since cos(θ) = sin(θ+π/2).
From there, you can use any of a number of interpolation methods to include simple rounding, linear interpolation or some sort of polynomial interpolation based on your needs.
You would then use either the matrix or quaternion based transformation to compute the rotated vector.
This will be faster than computing the sin and cos for general angles, though will require some additional space, and there will be an accuracy penalty as well. But if it satisfies your needs...
Theres a cheaper way than matrices, I think ive got it to sum count of adders.
The perimetre box of the vector is as good as an angle, if you step in partitions of the box size. (thats only a binary shift if its a power of 2.)
Then that would be a "box rotate" then just use the side report to give you how far along the diagonal you would be then you can split it up into so many gradients, the circle shape.
Id like to see someone proove that u can rotate without matrices or any trig like that too.
Is it possible to rotate without trigonometry? Yes.
Is it useful to rotate without using trigonometry? Probably not.
The first option is a problem-level solution: Change your coordinate system to spherical or cylindrical coordinates.
Since you rotate around an axis cylindrical coordinates of the form (alpha, radius, x3) will work.
Naming your center point O (for origin) and the point to rotate P, you can get the vector between them v=P-O. You also know the normal vector n of your plane of rotation (the vector you rotate around). With this, you can get the components of v that are parallel and orthogonal to n using a vector projection.
You have the freedom to choose how your new coordinate frame is rotated (relative to your original frame), so you can measure angles from the projection of v onto the plane of rotation. You also have the freedom to choose between degree and radians.
From there, you can now rotate to your heart's content using addition and subtraction.
Using dot(.,.) to denote the scalar product it would look something like this in code
v_parallel = dot(v, n) / dot(n, n) * n
radius = norm(v - v_parallel)
x3 = norm(v_parallel)
new_axis = (v - v_parallel) / norm(v - v_parallel)
P_polar = (0, radius, x3)
# P rotated by 90 degrees
P_polar = (pi/2, radius, x3)
# P rotated by -10 degrees
P_polar = (-pi/36, radius, x3)
However, if you want to change back to a standard basis you will have to use trigonometry again. Hence why I said this approach exists, but may not be too useful in practice.
Another approach comes from the cool observation that you can describe any planar rotation using two reflections along two given axis (represented by two vectors). The plane of rotation is the plane that is spun up by the two vectors and the angle of rotation is twice the angle between the two vectors.
You can reflect a vector using the vector projection from above; hence, you can do the entire process without trigonometry if you know the two vectors (let's call them x1 and x2).
tmp = v - 2 * dot(v, x1) / dot(x1, x1) * x1
v_rotated = tmp - 2 * dot(tmp, x2) / dot(x2, x2) * x2
The problem then turns into finding two vectors that are orthogonal to n and have an enclosing angle of alpha/2. How to do this is specific to your problem. For arbitrary alpha this is again the point where you can't dodge the trigonometry bullet; hence, it is again possible, but maybe not so viable in practice.
With help from Mathematica, it looks like we can rotate a point around a vector without Sin/Cos if you are willing to specify the amount of rotation as a number between -1 and 1, rather than an angle in radians.
The below starts with Mathematica's RotationTransform of a point {x,y,z} around a vector {u,v,w} by c radians (which contains many instances of Cos[c] and Sin[c]). It then substitutes all the Cos[c] with "c" and Sin[c] with Sqrt[1-c^2] (a trig identity for Sin in terms of Cos). Everything is simplified with the assumption that the rotation vector is normalized. The resulting equation produces the rotated point without any trig operations.
Note: as c ranges from -1 to 1 the point will only rotate through half a circle, the other half of the rotation can be achieved by flipping the signs on {u,v,w}.

Resources