Angle between plane normal in different coordinates - math

I have three vectors a, b, c in cartesian coordinate system x, y, z. Vectors are expressed in 3*3 matrix form by their components on x, y, z coordinates.
Virtual cube is created from vectors a, b, c which starts at same point.
I want to calculate angle between a vector in x,y,z coordinate and a plane inside virtual cube.
Angle between line and plane is found if plane normal is known. But I can't get normal of plane inside a cube.

If you mean the plane that contains a, b, and c, then the plane's normal can be calculated with the cross product:
n = (b - a) x (c - a)
You may want to normalize this vector afterwards. Make sure that your angle calculation is orientation-invariant, i.e. take the absolute value of the dot product.
angle = acos(abs(dot(v, n)) / (norm(n) * norm(v))

Related

Panning via normal vector and plane

I have got a camera and the direction it is looking at. Therefore I can create a plane out of this direction vector if I take it as a normal vector. So now I want to move my camera which should be on this plane along the plane. Everything's in 3D but I couldn't come up with an idea how to do so. How can I implement the navigational method of panning - so moving in this specific plane?
To pan your camera to the left and to the right you need to know not only lookAt direction, but also up direction for the camera. Then you can calculate cross product of lookAt and upAxis and this gives you direction to the right, negated vector gives you direction to the left.
Definition: A vector N that is orthogonal to every vector in a plane is called a normal vector to the plane.
An equation of the plane containing the point (x0, y0, z0) with normal vector N = (A, B, C), is A(x − x0) + B(y − y0) + C(z − z0) = 0.
Note: The equation of any plane can be expressed as Ax + By + Cz = D.
This is called the standard form of the equation of a plane. From the eqn you can get any other point you want on the plane.
Example: A plane passing through the point P = (1, 6, 4) and the normal vector, R = (2, - 3, - 1). Then the eqn is,
2(x-1) - 3(y-6) - (z-4) = 0
=> 2x - 3y - z = -20

Get a plane's center X, Y, Z, Cartesian coordinates

I need to get a plane's center X, Y, Z, Cartesian coordinates. I have the plane's normal and its center point distance to origin.
I can place a point(s) anywhere and get the distance from it. I suppose that some kind of triangulation COULD be in order. Like placing three (or however many you need) points in some fashion to get a single point.
If your plane is given in the following form:
dot(x, n) = d
, then it's quite easy to get an x that lies on the plane. Assuming that n is a unit vector, then dot(n, n) = 1. So, dot(d * n, n) = d. So one point on the plane is d * n.

Retrieve 2D co-ordinate from a 3D point on a 3D plane

I have a point a point (x, y, z) that is on a plane defined by ax+by+cz+d=0. I'm trying to figure out what the (x', y') relative to the plane, where it has a starting point of (x0, y0, z0) and the x'-axis is defined by (1,0) and the y'-axis is defined by (0,1).
My major goal is to have the mouse click on a surface, and know the 2D co-ordinates on a particular surface. I've managed to intersect the ray onto a plane quite trivially.
As a side-note, I'm using DirectX 9 - my familiarity with matrix/vector math is limited by the APIs provided to me through the D3DX libraries.
One thought I had was to use the angle of between one of the axis vectors and find the distance from origin, and figure out the x/y using simple trig. But I'm not sure if that's really an ideal solution or not - or if it can actually solve the issue at hand.
Since you have a 2D image on that plane, you apparently want to match its coordinate system. To do so, determine the unit vectors of the picture. That is, take the 3d coordinates B for the picture position (x,0) for any x>0, and subtract from that the 3d coordinates A for the origin (0,0) of the picture. The resulting vector B − A will describe the positive x direction of your image. Do the same for the y direction. Then normalize both these vectors. This means dividing them by their length, sqrt(x²+y²+z²), but D3Dx has a function D3DXVec3Normalize for this. Let's call the resulting 3d vectors X and Y. To compute the x and y coordinate of any 3D point p, simply subtract the origin A from p, i.e. compute the vector p − A. Then compute the dot product between the result and the unit vectors X and Y. This will give you two numbers: the desired coordinates. This is because the dot product can be used to compute an orthogonal projection.
Translating this into D3Dx, it should look somewhat like the following. As I have never used it, this might have mistakes.
D3DXVECTOR3 *p; // input point
D3DXVECTOR3 a, b, c, ab, ac, ap; // helper vectors
FLOAT x, y; // output coordinates
imagePosTo3D(&a, 0, 0); // a = origin of image
imagePosTo3D(&b, 1, 0); // b = anywhere on positive x axis, perhaps a corner
imagePosTo3D(&c, 0, 1); // c = anywhere on positive y axis, perhaps a corner
D3DXVec3Subtract(&ab, &b, &a); // ab = b - a
D3DXVec3Subtract(&ac, &c, &a); // ac = c - a
D3DXVec3Normalize(&ab, &ab); // ab = ab / |ab|
D3DXVec3Normalize(&ac, &ac); // ac = ac / |ac|
// the above has to be done once for the image, the code below for every p
D3DXVec3Subtract(&ap, p, &a); // ap = p - a
x = D3DXVec3Dot(&ab, &ap); // x = ab∙ap
y = D3DXVec3Dot(&ac, &ap); // y = ac∙ap

Transform 3D points to 2D

I have a set of points (x1, x2,..xn) that lie on the plane define by Ax+ By+Cz+d=0.
I would like to find the transformation matrix to translate and rotate to XY plane. So, the new point coordinate will be x1'=(xnew, ynew,0).
A lot of answer give quaternion, dot or cross product matrix. I am not sure which one is the correct way.
Thank you
First of all, unless in your plane equation, d=0, there is no linear transformation you can apply. You need to instead perform an affine transformation.
One way to do this is to determine an angle and vector about which to rotate to make your pointset lie in a plane parallel to the XY plane (ie. the Z component of your transformed pointset to all have the same values). Then you simply drop the Z component.
For this, let V be the normalized plane normal for the plane containing your points. For convenience define from your plane equation above Ax+By+Cz+d=0:
V = (A, B, C)
V' = V / ||V|| = (A', B', C')
Z = (0, 0, 1)
where
A' = A / ||V||
B' = B / ||V||
C' = C / ||V||
||V|| = (A2+B2+C2)1/2
The angle will simply be:
θ = cos-1(Z∙V / ||V||)
= cos-1(Z∙V')
= cos-1(C')
The axis R about which to rotate is just the cross product of the normalized plane normal V' and Z. That is
R = V'×Z
= (B', -A', 0)
You can now use this angle / axis pair to build the quaternion rotation needed to rotate all of the points in your dataset to a plane parallel to the XY plane. Then, a I said earlier, just drop the Z component to perform an orthogonal projection onto the XY plane.
Update: antonakos makes a good point about normalizing the R before using an API taking axis / angle pairs.

Rotation matrix that minimizes distance

Let's say I have two points in 3D space (a and b) and a fixed axis/unit vector called n.
I want to create a rotation matrix that minimizes the euclidan distance between point a (unrotated) and the rotated point b.
E.g:
Q := matrix_from_axis_and_angle (n, alpha);
find the unknown alpha that minimizes sqrt(|a - b*Q|)
Btw - If a solution/algorithm can be easier expressed with unit-quaternions go ahead and use them. I just used matrices to formulate my question because they're more widely used.
Oh - I know there are some degenerated cases ( a or b lying exactly in line with n ect.) These can be ignored. I'm just looking for the case where a single solution can be calculated.
sounds fairly easy. Assume unit vector n implies rotation around a line parallel to n through point x0. If x0 != the origin, translate the coordinate system by -x0 to get points a' and b' relative to new coordinate system origin 0, and use those 2 points instead of a and b.
1) calculate vector ry = n x a
2) calculate unit vector uy = unit vector in direction ry
3) calculate unit vector ux = uy x n
You now have a triplet of mutually perpendicular unit vectors ux, uy, and n, which form a right-handed coordinate system. It can be shown that:
a = dot(a,n) * n + dot(a,ux) * ux
This is because unit vector uy is parallel to ry which is perpendicular to both a and n. (from step 1)
4) Calculate components of b along unit vectors ux, uy. a's components are (ax,0) where ax = dot(a,ux). b's components are (bx,by) where bx = dot(b,ux), by = dot(b,uy). Because of the right-handed coordinate system, ax is always positive so you don't actually need to calculate it.
5) Calculate theta = atan2(by, bx).
Your rotation matrix is the one which rotates by angle -theta relative to coordinate system (ux,uy,n) around the n-axis.
This yields degenerate answers if a is parallel to n (steps 1 and 2) or if b is parallel to n (steps 4, 5).
I think you can rephrase the question to:
what is the distance from a point to a 2d circle in 3d space.
the answer can be found here
so the steps needed are as following:
rotating the point b around a vector n gives you a 2d circle in 3d space
using the above, find the distance to that circle (and the point on the circle)
the point on the circle is the rotated point b you are looking for.
deduce the rotated angle
...or something ;^)
The distance will be minimized when the vector from a to the line along n lines up with the vector from b to the line along n.
Project a and b into the plane perpendicular to n and solve the problem in 2 dimensions. The rotation you get there is the rotation you need to minimize the distance.
Let P be the plane that is perpendicular to n.
We can find the projection of a into the P-plane, (and similarly for b):
a' = a - (dot(a,n)) n
b' = b - (dot(b,n)) n
where dot(a,n) is the dot-product of a and n
a' and b' lie in the P-plane.
We've now reduced the problem to 2 dimensions. Yay!
The angle (of rotation) between a' and b' equals the angle (of rotation) needed to swing b around the n-axis so as to be closest to a. (Think about the shadows b would cast on the P-plane).
The angle between a' and b' is easy to find:
dot(a',b') = |a'| * |b'| * cos(theta)
Solve for theta.
Now you can find the rotation matrix given theta and n here:
http://en.wikipedia.org/wiki/Rotation_matrix
Jason S rightly points out that once you know theta, you must still decide to rotate b clockwise or counterclockwise about the n-axis.
The quantity, dot((a x b),n), will be a positive quantity if (a x b) lies in the same direction as n, and negative if (a x b) lies in the opposite direction. (It is never zero as long as neither a nor b is collinear with n.)
If (a x b) lies in the same direction as n, then b has to be rotated clockwise by the angle theta about the n-axis.
If (a x b) lies in the opposite direction, then b has to be rotated clockwise by the angle -theta about the n-axis.

Resources