Related
I have been trying to figure out whether the following problem has a solution. Almost having given up, I would like to ask whether someone can confirm that there is no solution, or maybe give me a hint.
We have two vectors v and w in 3D space and know that the ratio of their magnitudes is ||v|| / ||w|| = 0.8019.
in 3D space an observer would see that they form an angle of 27.017 degrees.
on the other side, an observer in 2D (only seeing the x and z axis), observes an angle of 7.125 degrees between the vectors.
From their view, the vector coordinates are v = (x: 2, z: 1) and w = (x: 3, z: 2).
Is there somehow a way that the 2D observer can calculate the actual angle between these vectors in 3D space?
I would be more than happy for any input. All my tries have failed so far and I just want to know whether there could be a possible solution.
I have solved this problem and get that the values of y1 and y2 are given by this function:
eq1: 0.6439*y2^(2)-y1^(2)=9.785.
Therefore real angle can practically any value, the factor that would narrow this problem down to an actual solution would be the information about where the observer is in the 3d space so that he sees the angle of 27.017º, however, if this is the whole problem, then I can share my solution and process.
Some graphs that I created from my calculations:
The side view of the vectors is directly from the point of view of the x and z axis of the graph, therefore the coordinates of the (x1,z1) and (x2,z2) points(terminal points of the vectors), appear authentic, and not augmented, hence you can use them in your calculations to calculate the coordinates of z1 and z2, which you need to calculate the angle.
V = (x1, y1, z1) V = (2, y1, 1)
W = (x2, y2, z2) W = (3, y2, 2)
Since ||v|| / ||w|| = 0.8019
∴Then sqrt((x1^2)+(y1^2)+(z1^2))/sqrt((x2^2)+(y2^2)+(z2^2)) = 0.8019
∴(x1^2)+(y1^2)+(z1^2)/(x2^2)+(y2^2)+(z2^2) = 0.6430
∴4+(y1^2)+1/9+(y2^2)+4 = 0.6430
∴5+(y1^2) = 8.359 + 0.6430(y2^2)
∴13.359 = 0.6430(y2^2)-(y1^2)
This gives you therefore a function that calculates the other value of y given the some input y.
You can then graph this function using Geogebra.
For all the pairs of values on the curve, together with the fixed values of x and z for both of the vectors you can calculate that the ratio between the magnitudes of the two vectors is equal to 0.8019.
This problem has therefore infinitely many solutions for the angle as there are infinitely many values of z1 and z2 that satisfy the ratio; ||v|| / ||w|| = 0.8019.
Therefore the answer to this problem can be expressed as:
∀Θº∈R:Θº≥0
I have 4 points in space A(x,y,z), B(x,y,z), C(x,y,z) and D(x,y,z). How can I check if these points are the corner points of a rectangle?
You must first determine whether or not the points are all coplanar, since a rectangle is a 2D geometric object, but your points are in 3-space. You can determine they are coplanar by comparing cross products as in:
V1 = (B-A)×(B-C)
V2 = (C-A)×(C-D)
This will give you two vectors which, if A, B, C, and D are coplanar are linearly dependent. By considering what Wolfram has to say on vector dependence, we can test the vectors for linear dependence by using
C = (V1∙V1)(V2∙V2) - (V1∙V2)(V2∙V1)
If C is 0 then the vectors V1 and V2 are linearly dependent and all the points are coplanar.
Next compute the distances between each pair of points. There should be a total of 6 such distances.
D1 = |A-B|
D2 = |A-C|
D3 = |A-D|
D4 = |B-C|
D5 = |B-D|
D6 = |C-D|
Assuming none of these distances are 0, these points form a rectangle if and only if the vertices are coplanar (already verified) and these lengths can be grouped into three pairs where elements of each pair have the same length. If the figure is a square, two sets of the pairs will have be the same length and will be shorter than the remaining pair.
Update: Reading this again, I realize the the above could define a parallelogram, so an additional check is required to check that the square of the longest distance is equal to the sum of the squares of the two shorter distances. Only then will the parallelogram also be a rectangle.
Keep in mind all of this is assuming infinite precision and within a strictly mathematical construct. If you're planning to code this up, you will need to account for rounding and accept a degree of imprecision that's not really a player when speaking in purely mathematical terms.
Check if V1=B-A and V2=D-A are orthogonal using the dot product. Then check if
C-A == V1+V2
within numerical tolerances. If both are true, the points are coplanar and form a rectangle.
Here a function is defined to check whether the 4 points represents the rectangle or not .
from math import sqrt
def Verify(A, B, C, D, epsilon=0.0001):
# Verify A-B = D-C
zero = sqrt( (A[0]-B[0]+C[0]-D[0])**2 + (A[1]-B[1]+C[1]-D[1])**2 + (A[2]-B[2]+C[2]-D[2])**2 )
if zero > epsilon:
raise ValueError("Points do not form a parallelogram; C is at %g distance from where it should be" % zero)
# Verify (D-A).(B-A) = 0
zero = (D[0]-A[0])*(B[0]-A[0]) + (D[1]-A[1])*(B[1]-A[1]) + (D[2]-A[2])*(B[2]-A[2])
if abs(zero) > epsilon:
raise ValueError("Corner A is not a right angle; edge vector dot product is %g" % zero)
else:
print('rectangle')
A = [x1,y1,z1]
print(A)
B = [x2,y2,z2]
C = [x3,y3,z3]
D = [x4,y4,z4]
Verify(A, B, C, D, epsilon=0.0001)
Ok, I know this sounds really daft to be asking here, but it is programming related.
I'm working on a game, and I'm thinking of implementing a system that allows users to triangulate their 3D coordinates to locate something (eg for a task).
I also want to be able to let the user make the coordinates of the points they are using for triangulation have user-determined coordinates (so the location's coordinate is relative, probably by setting up a beacon or something).
I have a method in place for calculating the distance between the points, so essentially I can calculate the lengths of the sides of the triangle/pyramid as well as all but the coordinate I am after.
It has been a long time since I have done any trigonometry and I am rusty with the sin, cos and tan functions, I have a feeling they are required but have no clue how to implement them.
Can anyone give me a demonstration as to how I would go about doing this in a mathematical/programatical way?
extra info:
My function returns the exact distance between the two points, so say you set two points to 0,0,0 and 4,4,0 respectively, and those points are set to scale(the game world is divided into a very large 3d grid, with each 'block' area being represented by a 3d coordinate) then it would give back a value at around 5.6.
The key point about it varying is that the user can set the points, so say they set a point to read 0,0,0, the actual location could be something like 52, 85, 93. However, providing they then count the blocks and set their other points correctly (eg, set a point 4,4,0 at the real point 56, 89, 93) then the final result will return the relative position (eg the object they are trying to locate is at real point 152, 185, 93, it will return the relative value 100,100,0). I need to be able to calculate it knowing every point but the one it's trying to locate, as well as the distances between all points.
Also, please don't ask why I can't just calculate it by using the real coordinates, I'm hoping to show the equation up on screen as it calculates the result.7
Example:
Here is a diagram
Imagine these are points in my game on a flat plain.
I want to know the point f.
I know the values of points d and e, and the sides A,B and C.
Using only the data I know, I need to find out how to do this.
Answered Edit:
After many days of working on this, Sean Kenny has provided me with his time, patience and intellect, and thus I have now got a working implementation of a triangulation method.
I hope to place the different language equivalents of the code as I test them so that future coders may use this code and not have the same problem I have had.
I spent a bit of time working on a solution but I think the implementer, i.e you, should know what it's doing, so any errors encountered can be tackled later on. As such, I'll give my answer in the form of strong hints.
First off, we have a vector from d to e which we can work out: if we consider the coordinates as position vectors rather than absolute coordinates, how can we determine what the vector pointing from d to e is? Think about how you would determine the displacement you had moved if you only knew where you started and where you ended up? Displacement is a straight line, point A to B, no deviation, not: I had to walk around that house so I walked further. A straight line. If you started at the point (0,0) it would be easy.
Secondly, the cosine rule. Do you know what it is? If not, read up on it. How can we rearrange the form given in the link to find the angle d between vectors DE and DF? Remember you need the angle, not a function of the angle (cos is a function remember).
Next we can use a vector 'trick' called the scalar product. Notice there is a cos function in there. Now, you may be thinking, we've just found the angle, why are we doing it again?
Define DQ = [1,0]. DQ is a vector of length 1, a unit vector, along the x-axis. Which other vector do we know? Do we know of two position vectors?
Once we have two vectors (I hope you worked out the other one) we can use the scalar product to find the angle; again, just the angle, not a function of it.
Now, hopefully, we have 2 angles. Could we take one from the other to get yet another angle to our desired coordinate DF? The choice of using a unit vector earlier was not arbitrary.
The scalar product, after some cancelling, gives us this : cos(theta) = x / r
Where x is the x ordinate for F and r is the length of side A.
The end result being:
theta = arccos( xe / B ) - arccos( ( (A^2) + (B^2) - (C^2) ) / ( 2*A*B ) )
Where theta is the angle formed between a unit vector along the line y = 0 where the origin is at point d.
With this information we can find the x and y coordinates of point f relative to d. How?
Again, with the scalar product. The rest is fairly easy, so I'll give it to you.
x = r.cos(theta)
y = r.sin(theta)
From basic trigonometry.
I wouldn't advise trying to code this into one value.
Instead, try this:
//pseudo code
dx = 0
dy = 0 //initialise coordinates somehow
ex = ex
ey = ey
A = A
B = B
C = C
cosd = ex / B
cosfi = ((A^2) + (B^2) - (C^2)) / ( 2*A*B)
d = acos(cosd) //acos is a method in java.math
fi = acos(cosfi) //you will have to find an equivalent in your chosen language
//look for a method of inverse cos
theta = fi - d
x = A cos(theta)
y = A sin(theta)
Initialise all variables as those which can take decimals. e.g float or double in Java.
The green along the x-axis represents the x ordinate of f, and the purple the y ordinate.
The blue angle is the one we are trying to find because, hopefully you can see, we can then use simple trig to work out x and y, given that we know the length of the hypotenuse.
This yellow line up to 1 is the unit vector for which scalar products are taken, this runs along the x-axis.
We need to find the black and red angles so we can deduce the blue angle by simple subtraction.
Hope this helps. Extensions can be made to 3D, all the vector functions work basically the same for 3D.
If you have the displacements from an origin, regardless of whether this is another user defined coordinate or not, the coordinate for that 3D point are simply (x, y, z).
If you are defining these lengths from a point, which also has a coordinate to take into account, you can simply write (x, y, z) + (x1, y1, z1) = (x2, y2, z2) where x2, y2 and z2 are the displacements from the (0, 0, 0) origin.
If you wish to find the length of this vector, i.e if you defined the line from A to B to be the x axis, what would the x displacement be, you can use Pythagoras for 3D vectors, it works just the same as with 2D:
Length l = sqrt((x^2) + (y^2) + (z^2))
EDIT:
Say you have a user defined point A (x1, y1, z1) and you want to define this as the origin (0,0,0). You have another user chosen point B (x2, y2, z2) and you know the distance from A to B in the x, y and z plane. If you want to work out what this point is, in relation to the new origin, you can simply do
B relative to A = (x2, y2, z2) - (x1, y1, z1) = (x2-x1, y2-y1, z2-z1) = C
C is the vector A>B, a vector is a quantity which has a magnitude (the length of the lines) and a direction (the angle from A which points to B).
If you want to work out the position of B relative to the origin O, you can do the opposite:
B relative to O = (x2, y2, z2) + (x1, y1, z1) = (x1+x2, y1+y2, z1+z2) = D
D is the vector O>B.
Edit 2:
//pseudo code
userx = x;
usery = y;
userz = z;
//move origin
for (every block i){
xi = xi-x;
yi = yi - y;
zi = zi -z;
}
I'm doing something where I have a plane in a coord sys A with a set of points already on it. I also have a normal vector in space N. How can I rotate the points on coord sys A so that the underlying plane will have the same normal direction as N?
Wondering if any one has a good idea on how to do this. Thanks
If you have, or can easily compute, the normal vector to the plane that your points are currently in, I think the easiest way to do this will be to rotate around the axis common to the two planes. Here's how I'd go about it:
Let M be the vector normal to your current plane, and N be the vector normal to the plane you want to rotate into. If M == N you can stop now and leave the original points unchanged.
Calculate the rotation angle as
costheta = dot(M,N)/(norm(M)*norm(N))
Calculate the rotation axis as
axis = unitcross(M, N)
where unitcross is a function that performs the cross product and normalizes it to a unit vector, i.e. unitcross(a, b) = cross(a, b) / norm(cross(a, b)). As user1318499 pointed out in a comment, this step can cause an error if M == N, unless your implementation of unitcross returns (0,0,0) when a == b.
Compute the rotation matrix from the axis and angle as
c = costheta
s = sqrt(1-c*c)
C = 1-c
rmat = matrix([ x*x*C+c x*y*C-z*s x*z*C+y*s ],
[ y*x*C+z*s y*y*C+c y*z*C-x*s ]
[ z*x*C-y*s z*y*C+x*s z*z*C+c ])
where x, y, and z are the components of axis. This formula is described on Wikipedia.
For each point, compute its corresponding point on the new plane as
newpoint = dot(rmat, point)
where the function dot performs matrix multiplication.
This is not unique, of course; as mentioned in peterk's answer, there are an infinite number of possible rotations you could make that would transform the plane normal to M into the plane normal to N. This corresponds to the fact that, after you take the steps described above, you can then rotate the plane around N, and your points will be in different places while staying in the same plane. (In other words, each rotation you can make that satisfies your conditions corresponds to doing the procedure described above followed by another rotation around N.) But if you don't care where in the plane your points wind up, I think this rotation around the common axis is the simplest way to just get the points into the plane you want them in.
If you don't have M, but you do have the coordinates of the points in your starting plane relative to an origin in that plane, you can compute the starting normal vector from two points' positions x1 and x2 as
M = cross(x1, x2)
(you can also use unitcross here but it doesn't make any difference). If you have the points' coordinates relative to an origin that is not in the plane, you can still do it, but you'll need three points' positions:
M = cross(x3-x1, x3-x2)
A single vector (your normal - N) will not be enough. You will need another two vectors for the other two dimensions. (Imagine that your 3D space could still rotate/spin around the normal vector, and you need another 2 vectors to nail it down). Once you have the normal and another one on the plane, the 3rd one should be easy to find (left- or right-handed depending on your system).
Make sure all three are normalized (length of 1) and put them in a matrix; use that matrix to transform any point in your 3D space (use matrix multiplication). This should give you the new coordinates.
I'm thinking make a unit vector [0,0,1] and use the dot-product along two planes to find the angle of difference, and shift all your points by those angles. This is assuming you want the z-axis to align with the normal vector, else just use [1,0,0] or [0,1,0] for x and y respectively.
This is a maths problem I am not exactly sure how to do. The vector is not aligned to an axis, so just rotating 90 degrees around x, y or z won't necessarily give me the other axes.
I can think of a couple of different scenarios you might be asking about.
Given: A pre-existing coordinate system
In a 2D system, your axes/basis are always [1,0] and [0,1] -- x and y axes.
In a 3D system, your axes/basis are always [1,0,0], [0,1,0], and [0,0,1] -- x, y, and z.
Given: One axis in an arbitrary-basis 2D coordinate system
If you have one axis in an arbitrary-basis 2D coordinate system, the other axis is the orthogonal vector.
To rotate a vector orthogonally counter-clockwise:
[x_new, y_new] = [ -y_old, x_old]
To rotate a vector orthogonally clockwise:
[x_new, y_new] = [ y_old, -x_old]
To summarize:
Given: x-axis = [ a, b]
Then: y-axis = [-b, a]
Given: y-axis = [ c, d]
Then: x-axis = [ d, -c]
Given: Two axes in an arbitrary-basis 3D coordinate system
To do this, find the cross product.
[a,b,c] x [d,e,f] = [ b*f - c*e, c*d - a*f, a*e - b*d ]
Following these three guidelines:
(x axis) x (y axis) = (z axis)
(y axis) x (z axis) = (x axis)
(z axis) x (x axis) = (y axis)
Given: One axis in an arbitrary-basis 3D coordinate system
There is not enough information to find the unique solution this problem. This is because, if you look at the second case (One axis in an arbitrary-basis 2D coordinate system), you first need to find an orthogonal vector. However, there are an infinite amount of possible orthogonal vectors to a single axis in 3D space!
You can, however, find one of the possible solutions.
One way to find an arbitrary one of these orthogonal vectors by finding any vector [d,e,f] where:
[a,b,c] = original axis
[d,e,f] = arbitrary orthogonal axis (cannot be [0,0,0])
a*d + b*e + c*f = 0
For example, if your original axis is [2,3,4], you'd solve:
2 * d + 3 * e + 4 * f = 0
That is, any value of [d,e,f] that satisfies this is a satisfactory orthogonal vector (as long as it's not [0,0,0]). One could pick, for example, [3,-2,0]:
2 * 3 + 3 *-2 + 4 * 0 = 0
6 + -6 + 0 = 0
As you can see, one "formula" that works to is [d,e,f] = [b,-a,0]...but there are many other ones that can work as well; there are, in fact, an infinite!
Once you find your two axes [a,b,c] and [d,e,f], you can reduce this back to the previous case (case 3), using [a,b,c] and [d,e,f] as your x and y axes (or whatever axes you need them to be, for your specific problem).
Normalization
Note that, as you continually do dot products and cross products, your vectors will begin to grow larger and larger. Depending on what you want, this might not be desired. For example, you might want your basis vectors (your coordinate axes) to all be the same size/length.
To turn any vector (except for [0,0,0]) into a unit vector (a vector with a length of 1, in the same direction as the original vector):
r = [a,b,c]
v = Sqrt(a^2 + b^2 + c^2) <-- this is the length of the original vector
r' = [ a/v , b/v , c/v ]
Where r' represents the unit vector of r -- a vector with length of 1 that points in the same direction as r does. An example:
r = [1,2,3]
v = Sqrt(1^2 + 2^2 + 3^2) = Sqrt(13) = 3.60555 <-- this is the length of the original vector
r' = [0.27735, 0.55470, 0.83205]
Now, if I wanted, for example, a vector in the same direction of r with a length of 5, I'd simply multiply out r' * 5, which is [a' * 5, b' * 5, c' * 5].
Having only one axis isn't enough, since there are still an infinite number of axes that can be in the perpendicular plane.
If you manage to get another axis though, you can use the cross product to find the third.
If you have one vector (x,y,z) you can get one perpendicular vector to it as (y,-x,0) (dot-product is xy-yx+0*z = 0)
Then you take the cross-product of both to get the remaining perpendicular vector:
(x,y,z) × (y,-x,0) = (0y+zx, yz-0x, -x²-y²) = (zx, yz, -x²-y²)
Are you talking about a typical 3coordinate system like the one used in a 3D engine?
With just a vector you can't find the other two, the only information you will have it the plane on which they lay.. but they can be at any angle also if they're perpendicular with the only one vector you have.