Reputation: 569
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
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