从PVector获取XYZ旋转

时间:2018-01-30 23:38:08

标签: java 3d angle

我有一个标准化的PVector代表来自原点的方向:

PVector dir = new PVector(-0.1, 0.8, 0.3);

我想在那个方向上得到X,Y和Z角,所以我可以使用rotateX()等矩阵变换。

在2D中,我使用atan2()来获取角度,但我不知道如何为3D点做这个。

2 个答案:

答案 0 :(得分:2)

我找到与轴的角度的方法是使用点积。我的向量都被称为GravVector,主要是因为我在引力n体模拟中使用它。我对向量的实现有类似.magnitude()的方法,可以轻松返回向量的大小,这是你需要的。

dot product基本上是在矢量X,Y和Z值上相乘,然后对所有这些产品求和。对于三维,可以这样明确写出:

public double dotProduct(GravVector vector) {
    return this.x * vector.x + this.y * vector.y + this.z * vector.z;
}

现在,点积具有一个很好的特性,其中乘积等于两个向量的大小乘以这两个向量之间角度的余弦。转移时,这就变成了这个:

Latex is the best formatting.

这意味着要找到角度,您可以简单地将右侧的值进行反射。

我的代码在下面执行此操作,产生double angleXangleYangleZ。请注意,结果是弧度。如果你想要这个度数,你需要乘以180 / Math.PI以弧度为单位乘以它。

GravVector vector = new GravVector(1, 1, 0);

// magnitude * 1 because the magnitude of the temporary vector is 1.
double angleX = Math.acos(vector.dotProduct(new GravVector(1, 0, 0)) / (vector.magnitude() * 1));
double angleY = Math.acos(vector.dotProduct(new GravVector(0, 1, 0)) / (vector.magnitude() * 1));
double angleZ = Math.acos(vector.dotProduct(new GravVector(0, 0, 1)) / (vector.magnitude() * 1));

// in radians
System.out.println(String.format("x: %.2f, y: %.2f, z: %.2f",
        angleX, angleY, angleZ));

// in degrees
System.out.println(String.format("x: %.2f, y: %.2f, z: %.2f",
        angleX * 180 / Math.PI,
        angleY * 180 / Math.PI, 
        angleZ * 180 / Math.PI));

打印出来的控制台输出是,第一行是弧度,第二行是度数:

x: 0.79, y: 0.79, z: 1.57
x: 45.00, y: 45.00, z: 90.00

你可以很容易地推广这个以获得任意两个向量之间的角度(如果它们是单位幅度的话无关紧要),如下所示:

public static double angleBetween(GravVector v1, GravVector v2) {
    return Math.acos(v1.dotProduct(v2) / (v1.magnitude() * v2.magnitude())); 
    // in radians
}

编辑。考虑到对于任何一个轴,点积将始终等效于相关组件。因此,对于X轴,它只是X分量。

这意味着您可以简化计算并使用以下方法:

public static double xAngle(GravVector vector) {
    return Math.acos(vector.x / (vector.magnitude()));
}

public static double yAngle(GravVector vector) {
    return Math.acos(vector.y / (vector.magnitude()));
}

public static double zAngle(GravVector vector) {
    return Math.acos(vector.z / (vector.magnitude()));
}

对于示例向量,使用[1,1,0]的组件,如果您调用并打印了每个方法的值,则会产生以下结果,这与上述值一致:

x, rad: 0.7853981633974484
y, rad: 0.7853981633974484
z, rad: 1.5707963267948966

答案 1 :(得分:0)

不是100%确定我是否理解你的x,y,z角度是什么意思,但我认为你的意思是,在“z角度”的情况下,使用你的单词,旋转a所需的角度带有原点(0,0,0)的矢量和Z为0的结束,它沿着X轴或Y轴(这是你的选择),围绕Z轴旋转,以便得到的矢量是投影的原始矢量在X,Y平面上,投影偶然是(x,y,0)。

Z周围的角度是y / x或(x / y)的反正切。

对X轴和Y轴执行相同操作,并且您具有这三个旋转角度。你只需要两个和一个初始向量,但我不知道这是否与问题有关。