This a bit of a geometric problem that I can probably solve in a clunky manner but I figured I would put it out on the forum to see if anyone else has encountered the same problem has a more simple and elegant solution than the one I have come up with.
I have an initial vector, lets just say [1,0,0] for simplicity. I now have another vector [5,3,2]. Both vectors are at the origin. I want my initial vector to be aligned with the second vector, what would be the single rotational transformation to get me there.
Since a rotation transformation is given by a point, vector and angle. We would need to solve for the vector and the angle since we can assume the point is at the origin.
We could use the angle_between method to compute the angle between vector 1 and vector 2
We could then use the cross method to computer the perpendicular vector for the rotation.
This seems like the easiest way to come up with the solution but I might be missing something here.
angle_between can only measure angles between 0 and 180 degrees; it can’t detect what direction the rotation is going.
With something like this you can get an angle in a plane (defined by the cross product as normal).
# Counter-clockwise angle from vector2 to vector1, as seen from normal.
def planar_angle(vector1, vector2, normal = Z_AXIS)
Math.atan2((vector2 * vector1) % normal, vector1 % vector2)
end
Just remember that if you use the cross product of the two given vectors to find the normal to the common plane, you must then normalize the result (which resizes it to a unit vector) before using it as normal in the method given by @eneroth3
Try this instead to always get the true planar angle:
def planar_angle(vector1, vector2)
normal = (vector1 * vector2).normalize
Math.atan2((vector2 * vector1) % normal, vector1 % vector2)
end
However, calculating (and normalizing) the cross product externally (and prior) to planar_angle yourself would be more efficient since you will also be using that cross product in additional methods after calling @eneroth3’s version.
I’m not entirely sure why but the solution Fredo has shown is what I initially ended up with but ultimately it did not work. Instead I ended up doing this:
@medeek I am not sure what the goal is here, but when I use your code with inputs of [1,0,0] and [5,3,2], then apply the resulting tot_trans to [1,0,0], I get a result of [0.742781, 0.8557086, 0.371391] which is neither the second vector, not any multiple of it (i.e. it does not lie along [5,3,2])
The following method however works for any two input vectors (with credit to @eneroth3 for her planar_angle method which I incorporated):
def test_rotation (vec1, vec2)
tr = find_rot_trans vec1, vec2 # Find rotation transformation
vec3 = vec1.transform tr # Test by applying to 'vec1'
if vec3.samedirection? vec2
puts "This works!" # Resulting transformed vector is parallel to original 'vec2'
else
puts "This did NOT work"
end
end
There is a possibility I misinterpreted your problem, in which case it would be great if you express it as a test method as I have done.