Andis59
Andis59

Reputation: 569

Two ways of rotating 3D point, What is the difference

I need to rotate a 3D point round the Y-axis

I'm no matematician so I have searched the internet and found this page https://www.siggraph.org/education/materials/HyperGraph/modeling/mod_tran/3drota.htm#Y-Axis%20Rotation

Using this code

private void RotateAroundY_1()
{
    double x = 40.46;
    double y = 16.52;
    double z = 56.5;
    double b = -1* 64.77;       // rotation degree (mult with -1 to get the rotation counter clockwise

    double B = DegreeToRadian(b);   // B


    double X = x * Math.Cos(B) + z*Math.Sin(B);
    double Y = y;
    double Z = z*Math.Cos(B) - x*Math.Sin(B);

    Console.WriteLine(string.Format("X: {0} Y: {1} Z: {2}",X,Y,Z));
}
private double DegreeToRadian(double b)
{
    return (Math.PI / 180) * b;
}

I get this result

X: -33,8639291270836 
Y: 16,52 
Z: 60,6835719455922

BUT, the rotated coordinates should be (according to the 3D CAD program and its user)

X: 68.38
Y: 16,52 
Z: -12.5

If I use this code

private void RotateAroundY_2()
{
    double x = 40.46;
    double y = 16.52;
    double z = 56.5;
    double b = -1* 64.77;   // rotation degree (mult with -1 to get the rotation counter clockwise

    double curAng = Math.Atan2(z, x);
    double X = Math.Sqrt(Math.Pow(x, 2) + Math.Pow(z, 2));
    double Y = Math.Cos(DegreeToRadian(b) + curAng) * hyp;
    double Z = Math.Sin(DegreeToRadian(b) + curAng) * hyp;

    Console.WriteLine(string.Format("X: {0} Y: {1} Z: {2}",X,Y,Z));
}
private double DegreeToRadian(double b)
{
    return (Math.PI / 180) * b;
}

I get this result

X: 68,3563218478633
Y: 16,52
Z: -12,5169830003609

So I'm going to use the RotateAroundY_2, but I wish I could understand what the difference are and why I should use the second one?

ELI5 (Explain Like I'm five)

Upvotes: 0

Views: 73

Answers (1)

Spektre
Spektre

Reputation: 51873

you got the - sign wrong it should be on the other sinus... I do not code in C# so all the code chunks are in C++ (need to port it but that shoul dbe simple enough).

void rotate_y(double &x,double &y,double &z,double ang)
    {
    double u=x,v=z;
    ang*=M_PI/180.0;
    x=+u*cos(ang)-v*sin(ang);
    z=+u*sin(ang)+v*cos(ang);
    }

using it like this:

double x=40.46,y=16.52,z=56.5,ang=-64.77;
mm_log->Lines->Add(AnsiString().sprintf("(%03.3f,%03.3f,%03.3f)",x,y,z));
rotate_y(x,y,z,ang);
mm_log->Lines->Add(AnsiString().sprintf("(%03.3f,%03.3f,%03.3f)",x,y,z));

results in this output:

(40.460,16.520,56.500)
(68.356,16.520,-12.517)

When you got the minus on the other sin then you are rotating the other way around so multiplying angle by -1 will lead to your wanted result too.

void rotate_y(double &x,double &y,double &z,double ang)
    {
    double u=x,v=z;
    ang*=-M_PI/180.0;       
    x=+u*cos(ang)+v*sin(ang);
    z=-u*sin(ang)+v*cos(ang);
    }

like this:

(40.460,16.520,56.500)
(68.356,16.520,-12.517)

You can also optimized the rotation a bit:

void rotate_y(double &x,double &y,double &z,double ang)
    {
    double u=x,v=z,c,s;
    ang*=M_PI/180.0;
    c=cos(ang);
    s=sin(ang);
    x=+u*c-v*s;
    z=+u*s+v*c;
    }

to avoid multiple sin,cos usage.

The other rotation code you got is very slow and inaccurate as it relays on atan2 (that has also the potential danger of getting NaN in subresults). It simply converts your point into polar coordinates add the delta angle and convert back to cartesian.

Upvotes: 3

Related Questions