I have 3d line(unit direction vector) which allways originate in (0,0,0) and 3d vector which allways points in one of two directions(negative or positive) on this 3d line.
The question is how do I check on which side my vector is ?
Your unit vector is of form (x,y,z) and your other vector is of form (a,b,c).
It's now enough to find any component x,y,z that is not zero and test that the corresponding component in a,b,c has the same sign. If it does, they are on the same side.
The operation of 'dot product' does this automatically:
if (a*x + b*y + c*z) >0 the vectors are on the same side.
Your vector is the unit direction vector multiplied by some non-zero scalar a. If a > 0, it's in the same direction, otherwise it's in the opposite direction.
Related
How would you find the signed angle theta from vector a to b?
And yes, I know that theta = arccos((a.b)/(|a||b|)).
However, this does not contain a sign (i.e. it doesn't distinguish between a clockwise or counterclockwise rotation).
I need something that can tell me the minimum angle to rotate from a to b. A positive sign indicates a rotation from +x-axis towards +y-axis. Conversely, a negative sign indicates a rotation from +x-axis towards -y-axis.
assert angle((1,0),(0,1)) == pi/2.
assert angle((0,1),(1,0)) == -pi/2.
What you want to use is often called the “perp dot product”, that is, find the vector perpendicular to one of the vectors, and then find the dot product with the other vector.
if(a.x*b.y - a.y*b.x < 0)
angle = -angle;
You can also do this:
angle = atan2( a.x*b.y - a.y*b.x, a.x*b.x + a.y*b.y );
If you have an atan2() function in your math library of choice:
signed_angle = atan2(b.y,b.x) - atan2(a.y,a.x)
I've run into an interesting piece of legacy code that I'm having trouble understanding.
We perform two rotations using euler matrices and then multiply by the original vector to determine the new position of a point (x,y). No problem.
However, the next line of code takes the dot product of the rotation matrix 2nd row with the vector to determine which side of the plane the point is on. For clarity, the rotation matrix is the product of a rotation around the x axis then around the y axis, a “combo” matrix.
I'm aware of how to do this using the dot product of a plane and a vector, but I can find no references about why using the 2nd row of a euler matrix works -- and it does work!
Thank you
Consider a basic rotation:
[p0] [R00 R01 R02] [q0]
[p1] = [R10 R11 R12] [q1]
[p2] [R20 R21 R22] [q2]
The "y" component of p (p1) is just the dot product between the 2nd row of R with q. If positive, it's on one side of the x-z plane, and if negative, it's on the other. If it's zero, it sitting right on top of the plane. (Recall that the x-z plane contain all of the points where y is 0.)
This is easy to find the 2D unit tangent from the unit normal vector. Just make the x component of the unit tangent vector equal to the negative of the y component of the unit normal vector,
and make the y component of the unit tangent vector equal to the x component of the unit normal vector:
ut =〈−uny, unx〉
But how unit tangent from the unit normal vector is obtained in 3D with xyz components?
I'm not entirely sure if I understand your question correctly.
What I understand is that you have a vector (x,y,z) and you want to find the vectors perpendicular to this vector?
Vectors perpendicular to each other are vectors for which the dot product equals zero.
One is (-y,x,0) (if not both x and y are zero). Call it b1.
Another one is obtained computing the cross product of (x,y,z) and (-y,x,0). Call it b2.
The set of all vectors perpendicular to (x,y,z) is the set of linear combination of b1 and b2.
I want to calculate the angle between two vectors a and b. Lets assume these are at the origin. This can be done with
theta = arccos(a . b / |a| * |b|)
However arccos gives you the angle in [0, pi], i.e. it will never give you an angle greater than 180 degrees, which is what I want. So how do you find out when the vectors have gone past the 180 degree mark? In 2D I would simply let the sign of the y-component on one of the vectors determine what quadrant the vector is in. But what is the easiest way to do it in 3D?
EDIT: I wanted to keep the question general but here we go. I'm programming this in c and the code I use to get the angle is theta = acos(dot(a, b)/mag(a)*mag(b)) so how would you programmatically determine the orientation?
This works in 2D because you have a plane defined in which you define the rotation.
If you want to do this in 3D, there is no such implicit 2D plane. You could transform your 3D coordinates to a 2D plane going through all three points, and do your calculation inside this plane.
But, there are of course two possible orientations for the plane, and that will affect which angles will be > 180 or smaller.
I came up with the following solution that takes advantage of the direction change of the cross product of the two vectors:
Make a vector n = a X b and normalize it. This vector is normal to the plane spanned by a and b.
Whenever a new angle is calculated compare it with the old normal. In the comparison, treat the old and the current normals as points and compute the distance between them. If this distance is 2 the normal (i.e. the cross product a X b has flipped).
You might want to have a threshold for the distance as the distance after a flip might be shorter than 2, depending on how the vectors a and b are oriented and how often you update the angle.
One solution that you could use:
What you effectively need to do is create a plane that one of the vectors is coplanar to.
Getting the cross product of both vectors will create a plane, then is you get the normal of this plane, you can get the angle between this and the vector you need to get the signed angle for, and you can use the angle to determine the sign.
If the angle is greater than 90 degrees, then it is below the created plane; less than 90 degrees, and it is above.
Depending on cost of calculations, the dot product can be used at this stage instead of the angle.
Just make sure that you always calculate the normals by the same order of vectors.
This is useable more easily if you're using the XYZ axes, and that's what you're comparing against, since you already have the vectors needed for the plane.
There are possbly more efficient solutions, but this is one I came up with.
Edit: clarification of created vectors
a X b = p. This is perpendicular to both a and b.
Then, do either:
a X p or b X p to create another vector that is the normal to the plane created by the 2 vectors. Choice of vector depends on which you're trying to find the angle for.
Strictly speaking, two 3D vectors always have two angles between them - one below or equal to 180, the other over or equal to 180. Arccos gives you one of them, you can get the other by subtracting from 360. Think of it that way: imagine two lines intersect. You have 4 angles there - 2 of one value, 2 of another. What's the angle between the lines? No single answer. Same here. Without some kind of extra criteria, you can not, in theory, tell which of the two angle values should be taken into account.
EDIT: So what you really need is an arbitrary example of fixing an orientation. Here's one: we look from the positive Z direction. If the plane between the two vectors contains the Z axis, we look from the positive Y direction. If the plane is YZ, we look from the positive X direction. I'll think how to express this in coordinate form, then edit again.
I just came to strange problem with my project in 3D. Everyone knows algorythm of calculating LookAt vector, but it is not so easly to calculate "up" vector from transformation matrix (or at least maybe I simple missed something).
The problem is following:
"Up" vector is (0, 1, 0) for identity rotation matrix and rotate with matrix, but do not scale nor translate. If you have simple rotation matrix procedure is easy (multiply vector and matrix). BUT if matrix contains also translation and rotation (e.g. it was produced by multiplying several other matrices), this won't work, as vector would be translated and scaled.
My question is how to get this "up" vector from single transformation matrix, presuming vector (0, 1, 0) correspond to identity rotation matrix.
Translation actually does affect it. Let's say in the example the transformation matrix didn't do any scaling or rotation, but did translate it 2 units in the Z direction. Then when you transform (0,1,0) you get (0,1,2), and then normalizing it gives (0,1/sqrt(5), 2/sqrt(5)).
What you want to do is take the difference between the transformation of (0,1,0) and the transformation of (0,0,0), and then normalize the resulting vector. In the above example you would take (0,1,2) minus (0,0,2) (0,0,2 being the transformation of the zero vector) to get (0,1,0) as desired.
Apply your matrix to both endpoints of the up vector -- (0, 0, 0) and (0, 1, 0). Calculate the vector between those two points, and then scale it to get a unit vector. That should take care of the translation concern.
Simply multiply the up vector (0,1,0) with the transformation, and normalize. You'll get the new calculated up vector that way.
I'm no expert at matrix calculations, but it strikes me as a simple matter of calculating the up vector for the multiplied matrix and normalizing the resulting vector to a unit vector. Translation shouldn't affect it at all, and scaling is easily defeated by normalizing.
I am aware this is an OLD thread, but felt it was necessary to point this out to anyone else stumbling upon this question.
In linear Algebra, we are taught to look at a Matrix as a collection of Basis Vectors, Each representing a direction in space available to describe a relative position from the origin.
The basis vectors of any matrix (the vectors that describe the cardinal directions) can be directly read from the associated matrix column.
Simply put your first column is your "x++" vector, your second is the "y++" vector, the third is the "z++" vector. If you are working with 4x4 Matrices in 3d, the last elements of these columns and the last column are relating to translation of the origin. In this case, the last element of each of these vectors and the last column of any such matrix can be ignored for the sake of simplicity.
Example: Let us consider a matrix representing a 90 degree rotation about the y axis.
[0, 0, -1]
[0, 1, 0]
[1, 0, 0]
The up vector can be plainly extracted from the third column as (-1, 0, 0), because the matrix is applying a 90 degree rotation about the y axis the up vector now points down the x axis (as the vector says), You can acquire the basis vectors to acquire the positive cardinal directions, and negating them will give you their opposite counterparts.
Once you have a matrix from which to extract the directions, no non-trivial calculations are necessary.