我需要绕Y轴旋转3D点
我不是伴侣,所以我搜索了互联网并找到了此页面 https://www.siggraph.org/education/materials/HyperGraph/modeling/mod_tran/3drota.htm#Y-Axis%20Rotation
使用此代码
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;
}
我得到这个结果
X: -33,8639291270836
Y: 16,52
Z: 60,6835719455922
但是,旋转坐标应为(根据3D CAD程序及其用户)
X: 68.38
Y: 16,52
Z: -12.5
如果我使用此代码
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;
}
我得到这个结果
X: 68,3563218478633
Y: 16,52
Z: -12,5169830003609
所以我将使用RotateAroundY_2,但是我希望我能理解有什么区别以及为什么我 应该使用第二个吗?
ELI5(像我五岁那样解释)
答案 0 :(得分:3)
您弄错了-
符号,它应该在另一个窦上...我没有在 C#中进行编码,因此所有代码块都在 C ++ 中>(需要移植,但应该足够简单)。
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);
}
像这样使用它:
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));
结果如下:
(40.460,16.520,56.500)
(68.356,16.520,-12.517)
当您在另一个sin
上减去负号时,您将沿相反方向旋转,因此将角度乘以-1
也会导致您想要的结果。
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);
}
像这样:
(40.460,16.520,56.500)
(68.356,16.520,-12.517)
您还可以对旋转进行一些优化:
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;
}
避免多次使用sin,cos
。
您获得的另一个轮换代码非常慢且不准确,因为它在atan2
上进行中继(这也有使NaN
进入子结果的潜在危险)。只需将您的点转换为极坐标,再加上增量角,然后转换回笛卡尔坐标即可。