3d 三维空间中3个点之间的角度

3d 三维空间中3个点之间的角度,3d,3d,我有3个点,包含X,Y,Z坐标: var A = {x: 100, y: 100, z: 80}, B = {x: 100, y: 175, z: 80}, C = {x: 100, y: 100, z: 120}; 坐标是来自3d CSS变换的像素。 如何获得向量BA和BC之间的角度? 一个数学公式就可以了,JavaScript代码会更好。 多谢各位 在伪码中,向量BA(称为v1)是: 类似地,向量BC(称为v2)是: v1和v2的点积是它们之间夹角的余弦的函数(它由它们的大

我有3个点,包含X,Y,Z坐标:

var A = {x: 100, y: 100, z: 80},
    B = {x: 100, y: 175, z: 80},
    C = {x: 100, y: 100, z: 120};
坐标是来自3d CSS变换的像素。 如何获得向量BA和BC之间的角度? 一个数学公式就可以了,JavaScript代码会更好。 多谢各位


在伪码中,向量BA(称为v1)是:

类似地,向量BC(称为v2)是:

v1
v2
的点积是它们之间夹角的余弦的函数(它由它们的大小的乘积缩放)。因此,首先规范化
v1
v2

v1mag = sqrt(v1.x * v1.x + v1.y * v1.y + v1.z * v1.z)
v1norm = {v1.x / v1mag, v1.y / v1mag, v1.z / v1mag}

v2mag = sqrt(v2.x * v2.x + v2.y * v2.y + v2.z * v2.z)
v2norm = {v2.x / v2mag, v2.y / v2mag, v2.z / v2mag}
然后计算点积:

res = v1norm.x * v2norm.x + v1norm.y * v2norm.y + v1norm.z * v2norm.z
最后,恢复角度:

angle = acos(res)
double-GetAngleABC(double*a、double*b、double*c)
{
双ab[3]={b[0]-a[0],b[1]-a[1],b[2]-a[2]};
双bc[3]={c[0]-b[0],c[1]-b[1],c[2]-b[2]};
双abVec=sqrt(ab[0]*ab[0]+ab[1]*ab[1]+ab[2]*ab[2]);
双bcVec=sqrt(bc[0]*bc[0]+bc[1]*bc[1]+bc[2]*bc[2]);
双异常[3]={ab[0]/abVec,ab[1]/abVec,ab[2]/abVec};
双bcNorm[3]={bc[0]/bcVec,bc[1]/bcVec,bc[2]/bcVec};
双精度=异常[0]*bcNorm[0]+异常[1]*bcNorm[1]+异常[2]*bcNorm[2];
返回ACO(res)*180.0/3.141592653589793;
}
双a[]={1,0,0};
双b[]={0,0,0};
双c[]={0,1,0};

swift中的Roger算法

func SCNVector3Angle(start: SCNVector3, mid: SCNVector3, end: SCNVector3) -> Double {
    let v1 = (start - mid)
    let v2 = (end - mid)
    let v1norm = v1.normalized()
    let v2norm = v2.normalized()

    let res = v1norm.x * v2norm.x + v1norm.y * v2norm.y + v1norm.z * v2norm.z
    let angle: Double = Double(GLKMathRadiansToDegrees(acos(res)))
    return angle
}

/**
* Subtracts two SCNVector3 vectors and returns the result as a new SCNVector3.
*/
func - (left: SCNVector3, right: SCNVector3) -> SCNVector3 {
    return SCNVector3Make(left.x - right.x, left.y - right.y, left.z - right.z)
}

extension SCNVector3
{
    /**
    * Returns the length (magnitude) of the vector described by the SCNVector3
    */
    func length() -> Float {
        return sqrtf(x*x + y*y + z*z)
    }

    /**
    * Normalizes the vector described by the SCNVector3 to length 1.0 and returns
    * the result as a new SCNVector3.
    */
    func normalized() -> SCNVector3 {
        return self / length()
    }
}
在python中也是如此(输出以度为单位):

输出:

角度:90.0


经过时间:8.392333984375e-05

见我知道我必须规范化向量,但不知道如何将向量除以其长度。它的长度就是它的平方根。图片指向直角吗?很好,让我把它放在JavaScription中。你能看一看结果的一半吗@Mircea?@y_nk对不起,不要小提琴,但看看它应该在thereman中的槽,不是有更有效、更不精确的吗?一个渲染循环中的ACO和两个SQRT可以建立得很慢很快@Roger Rowland:是的,基本上是一样的。我真傻,在打扰你之前没有仔细注意到!:)该代码是可行的。我注意到一个危险的情况:你假设double*的长度总是3,而不检查这个。当用户/编码器传递不同长度的数组时,此代码将产生异常,但您没有处理异常。这是一件挑剔的事情,因为代码可以工作,但是我更喜欢对任何数组操作使用try/catch异常处理(或类似的操作,包括任何长度/大小如vector的集合),并且我更喜欢确认数组/容器的长度/大小是函数所期望的(这里是3)。投票表决。
angle = acos(res)
double GetAngleABC( double* a, double* b, double* c )
{
    double ab[3] = { b[0] - a[0], b[1] - a[1], b[2] - a[2] };
    double bc[3] = { c[0] - b[0], c[1] - b[1], c[2] - b[2]  };

    double abVec = sqrt(ab[0] * ab[0] + ab[1] * ab[1] + ab[2] * ab[2]);
    double bcVec = sqrt(bc[0] * bc[0] + bc[1] * bc[1] + bc[2] * bc[2]);

    double abNorm[3] = {ab[0] / abVec, ab[1] / abVec, ab[2] / abVec};
    double bcNorm[3] = {bc[0] / bcVec, bc[1] / bcVec, bc[2] / bcVec};

    double res = abNorm[0] * bcNorm[0] + abNorm[1] * bcNorm[1] + abNorm[2] * bcNorm[2];

    return acos(res)*180.0/ 3.141592653589793;
}


double a[] = {1, 0, 0};

double b[] = {0, 0, 0};

double c[] = {0, 1, 0};

std::cout<< "The angle of ABC is " << GetAngleABC(a,b,c)<< "º " << std::endl;
func SCNVector3Angle(start: SCNVector3, mid: SCNVector3, end: SCNVector3) -> Double {
    let v1 = (start - mid)
    let v2 = (end - mid)
    let v1norm = v1.normalized()
    let v2norm = v2.normalized()

    let res = v1norm.x * v2norm.x + v1norm.y * v2norm.y + v1norm.z * v2norm.z
    let angle: Double = Double(GLKMathRadiansToDegrees(acos(res)))
    return angle
}

/**
* Subtracts two SCNVector3 vectors and returns the result as a new SCNVector3.
*/
func - (left: SCNVector3, right: SCNVector3) -> SCNVector3 {
    return SCNVector3Make(left.x - right.x, left.y - right.y, left.z - right.z)
}

extension SCNVector3
{
    /**
    * Returns the length (magnitude) of the vector described by the SCNVector3
    */
    func length() -> Float {
        return sqrtf(x*x + y*y + z*z)
    }

    /**
    * Normalizes the vector described by the SCNVector3 to length 1.0 and returns
    * the result as a new SCNVector3.
    */
    func normalized() -> SCNVector3 {
        return self / length()
    }
}
import numpy as np
import math 
import time

def angle_2p_3d(a, b, c):       

    v1 = np.array([ a[0] - b[0], a[1] - b[1], a[2] - b[2] ])
    v2 = np.array([ c[0] - b[0], c[1] - b[1], c[2] - b[2] ])

    v1mag = np.sqrt([ v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2] ])
    v1norm = np.array([ v1[0] / v1mag, v1[1] / v1mag, v1[2] / v1mag ])

    v2mag = np.sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2])
    v2norm = np.array([ v2[0] / v2mag, v2[1] / v2mag, v2[2] / v2mag ])
    res = v1norm[0] * v2norm[0] + v1norm[1] * v2norm[1] + v1norm[2] * v2norm[2]
    angle_rad = np.arccos(res)

    return math.degrees(angle_rad)


p1 = np.array([1,0,0])
p2 = np.array([0,0,0])
p3 = np.array([0,0,1])

start = time.time()
angle= angle_2p_3d(p1, p2, p3)
end = time.time()

print("angle: ", angle)
print("elapsed in: ", end - start)