Rotating both in local and world coordinate system - math

Let's consider a simple case where we have an object with transformation matrix and then we do simple transoformations:
rotate the x axis through X1 angle -> A matrix
rotate the y axis through Y1 angle -> B matrix
rotate the x axis through X2 angle -> C matrix
In usual case I would do C * B * A and that would be the end of a story. But what it does, as we know, is applying new transformation in local coordinate system created by previous transformation. I don't like it.
What I would like to do in some certain situations is to rotate in local and some other times in world coordinate system. What I mean is that if I have matrix M = B * A (but I don't have X1 and Y1 angles available; all I have is M) and I would like to apply C in the world coordinate system then the output new transformation matrix would have the following:
x rotation = X1 + X2
y rotation = Y1
Is there any way to achieve it?
EDIT
I think I explained in wrongly.
Let's assume we have an object A at position described by matrix M. M has rotation, scaling and translation. I'd like to rotate the object along axes positioned in the center of object A but parallel to axes of a base coordinate system. After all I would also like the object to stay at (x,y,z) in base coordinate system.

In usual case I would do C * B * A and that would be the end of a story. But what it does, as we know, is applying new transformation in local coordinate system created by previous transformation.
Incorrect.
Consider a test point p. The coordinates of B * A * p in the local coordinate system of B * A are simply the world-space components of p – because a transformation is just a change of coordinate system.
So replacing p with C * p applies the transformation locally, i.e.:
C * (B * A) applies C in the world coordinate system
(B * A) * C applies C in the local coordinate system of B * A
EDIT
To rotate an object around its position p:
Translate by -p
Apply the desired rotation matrix C
Translate by +p to restore the original position
The final matrix is T * C * inv(T) * M, where T is a translation by p, and M is the original matrix. p is given by the last column of M.

Related

3D Vectors - Align a vector's coordinate system to a normal

I'm trying to align a coordinate system to a normal direction, in a way I only input X,Y,Z and the direction of the normal and the Y-rotation of the coordinate, to get the new X,Y,Z from the new aligned coordinate system.
A function that would look like this:
func transform(coordinate: XYZposition, to: XYZnormal, withY:Radians){
//missing mathematic
//rotate coordinates
return XYZpositionOfNewSystem
}
Here is an image representing visualize what I want to achieve. The axis are the representation of the coordinate system. First coordinate system is the original one, and the 2 on the right are the rotated ones.
Why 2 examples on the right?
As you can see, when aligning it to a face-normal, there is one free axis. The Y axis can take any rotation and still be aligned to the face.
That's why a rotation needs to be given to the function so it applies this Y-rotation as well.
I've found some maths on the Mathematics Stack Exchange site (Rotate 3D coordinate system such that z-axis is parallel to a given vector), but I'm lost if this is what I need, and I'm kind of lost on the maths applied and the symbols used.
Here is the answer you cited, implemented using python and numpy, and exchanging the roles of y and z to fit your needs:
from numpy import array, dot, cross, arccos, sin, cos
from scipy.spatial.distance import cosine
def angle(u,v):
return arccos(1 - cosine(u,v))
# assumes all four vectors are normalized
def get_transform_matrix(orig_system, n):
j = orig_system[:,1]
b = cross(j, n)
theta = angle(j, n)
q0 = cos(theta/2)
q1,q2,q3 = sin(theta/2) * b
Q = array([
[q0**2 + q1**2 - q2**2 - q3**2, 2*(q1*q3+q0*q2), 2*(q1*q2-q0*q3)],
[2*(q3*q1-q0*q2), q0**2 - q1**2 - q2**2 + q3**2, 2*(q3*q2+q0*q1)],
[2*(q2*q1+q0*q3), 2*(q2*q3-q0*q1), q0**2 - q1**2 + q2**2 - q3**2]
])
return Q
To transform a vector p into the new system, just compute Q # p:
from numpy import eye, sqrt
orig_system = eye(3)
n = array([0,1,1]) / sqrt(2)
Q = get_transform_matrix(orig_system, n)
print(Q)
# [[ 0.9267767 0. 0. ]
# [ 0. 0.78033009 0.5 ]
# [ 0. -0.5 0.78033009]]
p = array([10, 20, 30])
print(Q # p)
# [ 9.26776695 30.60660172 13.40990258]
Please do test it extensively!! I tested with a few different vectors and it looked okay, but I cannot guarantee that there are no mistakes.

What is the Correct Way to Scale then Rotate a set of Points?

I have 4 points, point A(x1, y1), point B(x2, y1), and point C(x2, y2), point D(x2, y3) creating two scales: Scale1 yRange(B, D), Scale2 yRange(B, C).
I want to scale the y axis only, so that point D is scaled down to point C, so that the angle between CAB is a certain degree. Then I want to rotate the scaled point C around point B a certain degree, obtaining point E. Then I want to find the real value of point E on the un-scaled coordinate grid where original point D is located. I think I need to use affine transformations, but all examples are rotate first, then scale. But I need to scale first, then rotate. How do I find this new value? I know how to perform rotations alone and a bit of scaling alone, but not together.
Maybe I am confused, after I perform the scaling and rotation, I would not need to scale back, because the new value of E equates to F? I know there are plenty of examples, but I can not wrap my head around this...
Here is my objective. I have the 3 points A, B and D. I want to scale so that DAB equates to let's say 60 degrees, creating point C, then perform several point rotations on C inside the scaled grid. I ultimately want to find the value of F, and the other rotated points, which lies in geometrical positions inside the original unscaled grid that I can not calculate unless I scale the 3 original points to said degree first. The scaled grid contains the correct ratio I need in order to rotate my points. I need to do all my rotations inside the scaled grid, without losing values, but changing aspect ratio, and then take those new points inside the scaled grid and plot them in the unscaled grid, which will then lose correct aspect ratios, which is fine.
Coding in python.
Here's a Python3 program that I think does what you want:
import math
# Use a negative angle since we're rotating clockwise
rotate_C_angle = math.radians(-60)
A = [0, 0]
B = [100, 0]
D = [100, 250]
# Create point D such that angle CAB = target_angle_CAB
target_angle_CAB = math.radians(60)
C = [B[0], B[0] * math.tan(target_angle_CAB)]
# What do we scale B by in order to get C
scale_factor = C[1] / D[1]
# Rotate C around B by rotate_C_angle
# (translate C by -Bx, then rotate, then translate back)
E = [
C[0] - C[1] * math.sin(rotate_C_angle),
C[1] * math.cos(rotate_C_angle)
]
# Scale E back
F = [E[0], E[1] / scale_factor]
This is assuming that A is at the origin. If it isn't then subtract Ax from all the x coordinates and Ay from the y coordinates, then do the calculations before translating back again.
Whether you need to scale back E to F depends on what you're doing. What happens here assumes that the scaling transformation along y does not get rotated.

Transfering between 2d coordinate systems where the x and y axes aren't perpendicular

my question is more of a mathematical question in 2d computer graphics, but I figured that its more relevant here than the standard Stack overflow, if there's one dedicated especially to computer graphics by all means you can move this there.
Anyway my question is about transferring from 2 different 2d cartesian coordinate systems, where the coordinate systems are described as vectors that aren't necessarily perpendicular to each other.
As you can see in the diagram I provided, you have 3 local coordinate systems A,B and C defined by vectors: Ai,Aj,Bi,Bj,Ci,Cj.
I need to find a way to describe the point p in all the local coordinate systems and then find the transformation that takes a point from coordinate system C to B.
Now A is pretty easy, I can just move the origin back to 0,0 and rotate 90 degrees counter-clockwise and by multiplying these matrices I get the transformation that takes point P from the standard coordinate system to A.
Whats not clear to me is what to do with B and C since their axes aren't perpendicular.
To make a transition between two coordinate systems, you have to calculate appropriate affine transform matrix. It is enough to have three non-collinear points in the first system and three corresponding points in the second system. For example, we can use triplet (5,6),(4,7)(2,7) for B, and triplet (4,3),(0,7),(0,1) for C system.
(x1 y1 1) (X1 Y1 1)
(x2 y2 1) * M = (X2 Y2 1)
(x3 y3 1) (X3 Y3 1)
M is affine matrix. To find M, we can left-multiply both sides by inverse of (x1...) matrix. Resulting affine matrix is:
(0, -3, 0)
M = (-4, -5, 0)
(28, 48, 1)
Quick check for middle point between Bi, Bj ends gives (3,7,1)*M=(0,4,1), middle point between Ci, Cj, as expected

Hexagonal Grid Coordinates To Pixel Coordinates

I am working with a hexagonal grid. I have chosen to use this coordinate system because it is quite elegant.
This question talks about generating the coordinates themselves, and is quite useful. My issue now is in converting these coordinates to and from actual pixel coordinates. I am looking for a simple way to find the center of a hexagon with coordinates x,y,z. Assume (0,0) in pixel coordinates is at (0,0,0) in hex coords, and that each hexagon has an edge of length s. It seems to me like x,y, and z should each move my coordinate a certain distance along an axis, but they are interrelated in an odd way I can't quite wrap my head around it.
Bonus points if you can go the other direction and convert any (x,y) point in pixel coordinates to the hex that point belongs in.
For clarity, let the "hexagonal" coordinates be (r,g,b) where r, g, and b are the red, green, and blue coordinates, respectively. The coordinates (r,g,b) and (x,y) are related by the following:
y = 3/2 * s * b
b = 2/3 * y / s
x = sqrt(3) * s * ( b/2 + r)
x = - sqrt(3) * s * ( b/2 + g )
r = (sqrt(3)/3 * x - y/3 ) / s
g = -(sqrt(3)/3 * x + y/3 ) / s
r + b + g = 0
Derivation:
I first noticed that any horizontal row of hexagons (which should have a constant y-coordinate) had a constant b coordinate, so y depended only on b. Each hexagon can be broken into six equilateral triangles with sides of length s; the centers of the hexagons in one row are one and a half side-lengths above/below the centers in the next row (or, perhaps easier to see, the centers in one row are 3 side lengths above/below the centers two rows away), so for each change of 1 in b, y changes 3/2 * s, giving the first formula. Solving for b in terms of y gives the second formula.
The hexagons with a given r coordinate all have centers on a line perpendicular to the r axis at the point on the r axis that is 3/2 * s from the origin (similar to the above derivation of y in terms of b). The r axis has slope -sqrt(3)/3, so a line perpendicular to it has slope sqrt(3); the point on the r axis and on the line has coordinates (3sqrt(3)/4 * s * r, -3/4 * s * r); so an equation in x and y for the line containing the centers of the hexagons with r-coordinate r is y + 3/4 * s * r = sqrt(3) * (x - 3sqrt(3)/4 * s * r). Substituting for y using the first formula and solving for x gives the second formula. (This is not how I actually derived this one, but my derivation was graphical with lots of trial and error and this algebraic method is more concise.)
The set of hexagons with a given r coordinate is the horizontal reflection of the set of hexagons with that g coordinate, so whatever the formula is for the x coordinate in terms of r and b, the x coordinate for that formula with g in place of r will be the opposite. This gives the third formula.
The fourth and fifth formulas come from substituting the second formula for b and solving for r or g in terms of x and y.
The final formula came from observation, verified by algebra with the earlier formulas.

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