'Rotating an end point while having the direction

I have a point and a direction and I would like to know what that point would be if it was rotated by 45 degrees. For example, if I have

Point A being (0, 0, 0) with a direction of (0, 0, 1) and a distance of 5, then my point B would be (0, 0, 5). However, if I wanted to get what point B would be while also incorporating an angle of 45 degrees, how would I do so?

I had thought of using the Rodrigues formula, however, given the formula of Rodrigues being rotation = (v, k, angle), or in this case, rotation = (point b, direction, 45) I would have a resulting vector of (0, 0, 5). This leads me to believe that I should be applying the angle to the direction some how

enter image description here



Solution 1:[1]

You appear to work in 3D, so you need to define a plane in which you want to rotate (i.e. move) some point. For example, given a point (0,0,1) and you choose the x-z-plane as plane in which you want to rotate the point, and you want to rotate it by 90°, you end up with (1,0,0). But if you choose to rotate the point (0,0,1) by 90° in the y-z-plane instead, you end up with (0,-1,0).

Rather than defining a plane, you can also use the normal vector of the plane in which you want to rotate the point. This normal is the rotation axis (called k below) around which the point gets rotated according to the right-hand rule. So, if you choose the x-z-plane, the rotation axis would be k=(0,1,0), i.e. the y-axis. If you choose the y-z-plane as plane, the rotation axis would be k=(1,0,0), i.e. the x-axis.

Note that in 2D you do not have the freedom of choosing the rotation axis: It is always pointing straight "out of your screen". Meaning, you only have x- and y-coordinates, but for the purpose of rotating you imagine a third axis (the z-axis) which is orthogonal to both the x- and y-axes, i.e. k=(0,0,1).

Now, to rotate some general 3D vector v by an angle angle around a rotation axis k, you can use Rodrigues' rotation formula. In pure C++ (since you added it as tag) without any additional libraries, it could be implemented like this:

#include <array>
#include <cmath>

using Vec3 = std::array<double, 3>;

// v = vector to rotate
// k = rotation axis. Must be a **unit** vector! (Length must be 1!)
// angle = rotation angle in radiant
Vec3 Rotate(Vec3 const & v, Vec3 const & k, double angle) {
    double const cosAngle = std::cos(angle);
    double const sinAngle = std::sin(angle);

    Vec3 const cross{
        k[1]*v[2] - k[2]*v[1],
        k[2]*v[0] - k[0]*v[2],
        k[0]*v[1] - k[1]*v[0]};
    double const scalar = k[0]*v[0] + k[1]*v[1] + k[2]*v[2];
    double const scalarWithAngle = scalar * (1.0 - cosAngle);

    Vec3 result;
    for (size_t i = 0; i < 3; ++i){
        // Rodrigues' rotation formula
        result[i] = v[i] * cosAngle + cross[i]*sinAngle + k[i]*scalarWithAngle;
    }
    return result;
}

Here I implement e.g. cross and scalar products manually. Using an appropriate library such as Eigen can make things easier and faster.

Given your explanation, I assume you want to start at a point A=(0,0,0), move a distance=5 into some direction. The direction is (0,0,1) but rotated by 45°. What you did not specify was the rotation axis. Considering your image, I guess to want to rotate around the y-axis (0,1,0), i.e. in the x-z-plane. Thus, in C++:

int main() {
    Vec3 const A{0, 0, 0};
    double const distance = 5.0;
    Vec3 const rotationAxis{0, 1.0, 0.0}; // = y-axis, i.e. rotation in x-z-plane
    double const angle = M_PI / 4.0; // 45° in radiant

    Vec3 const direction{0, 0, 1.0};
    Vec3 const rotatedDirection = Rotate(direction, rotationAxis, angle);
    Vec3 const C{
        A[0] + rotatedDirection[0]*distance, 
        A[1] + rotatedDirection[1]*distance, 
        A[2] + rotatedDirection[2]*distance};

    // Prints C = {3.53553, 0, 3.53553}
    std::cout << "C = {" << C[0] << ", " << C[1] << ", " << C[2] << "}" << std::endl;
}

This code first rotates the direction (0,0,1) by 45° in the x-z-plane, and then moves adistance=5 starting at A along the rotated direction to get to point C.

If you already know the point B that you want to rotate, it can be done similarly:

int main() {
    Vec3 const B{0, 0, 5.0};
    Vec3 const rotationAxis{0, 1.0, 0.0}; // = y-axis, i.e. rotation in x-z-plane
    double const angle = M_PI / 4.0; // 45° in radiant

    Vec3 const C = Rotate(B, rotationAxis, angle);
    // Prints C = {3.53553, 0, 3.53553}
    std::cout << "RotatePointDirectly C = {" << C[0] << ", " << C[1] << ", " << C[2] << "}" << std::endl;
}

Full example on godbolt.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1