简体   繁体   English

获取2 vector3的角度

[英]Get Angle of 2 vector3

I have 2 points : 我有2分:

v1 = {x:1,y:0,z:0}
v2 = {x:0,y:2,z:0}

I would like to calculate the angle beetwen those 2 points. 我想计算这2点的角度。 I know how to make it in 2D, but not in 3D, I'm a bit lost ^^ 我知道如何用2D制作,但不知道如何用3D制作,我有点迷失了^^

basically like in Unity : 基本上像在Unity中一样:

http://docs.unity3d.com/ScriptReference/Vector3.Angle.html http://docs.unity3d.com/ScriptReference/Vector3.Angle.html

Thanks for the tips :3 感谢您的提示:3

Using acos(ab/(|a||b|) is unstable when the angle is small (or near 180 degrees). In either the 2D or 3D case, the solution is to use atan2(,) instead. 当角度较小(或接近180度)时,使用acos(ab/(|a||b|)是不稳定的,在2D或3D情况下,解决方案都是使用atan2(,)

For 3D, compute both the dot product, and the length of the cross product: 对于3D,请计算点积和积的长度:

let dot = v1.x * v2.x + v1.y * v2.y + v3.z * v3.z;
let crossX = v1.y * v2.z - v1.z * v2.y;
let crossY = v1.z * v2.x - v1.x * v2.z;
let crossZ = v1.x * v2.y - v1.y * v2.x;
let crosslen = sqrt(crossX*crossX + crossY*crossY + crossZ*crossZ);
return atan2(dot, crosslen);

Sounds like for this project you're going to want to find a vector maths reference you can read without going crazy. 听起来像是对于这个项目,您将想要找到一个可以轻松阅读的矢量数学参考。

For this case , the dot product v1.v2 = x1*x2 + y1*y2 + z1*z2 = |v1| * |v2| * cos theta 对于这种情况 ,点积v1.v2 = x1*x2 + y1*y2 + z1*z2 = |v1| * |v2| * cos theta v1.v2 = x1*x2 + y1*y2 + z1*z2 = |v1| * |v2| * cos theta v1.v2 = x1*x2 + y1*y2 + z1*z2 = |v1| * |v2| * cos theta , which means your angle is v1.v2 = x1*x2 + y1*y2 + z1*z2 = |v1| * |v2| * cos theta ,这意味着您的角度是

function angle(v1, v2) {
    return Math.acos(dotProduct(v1, v2) / (length(v1) * length(v2)));
}

function dotProduct(v1, v2) {
    return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}

function length(v) {
    return Math.sqrt(dotProduct(v, v));
}

You can make that a lot faster, but if you want speed then probably use a library. 您可以使速度更快,但是如果您想提高速度,则可以使用库。

Use vector dot product: 使用矢量点积:

a . 一种 。 b = |a||b|cos $\\theta$ b = | a || b | cos $ \\ theta $

In your notation: 用您的符号:

v1.x * v2.x + v1.y * v2.y + v1.z * v2.z v1.x * v2.x + v1.y * v2.y + v1.z * v2.z

While

|a| | a | = sqrt(v1.x * v1.x + v1.y * v1.y + v1.z * v1.z) = sqrt(v1.x * v1.x + v1.y * v1.y + v1.z * v1.z)

and

|b| | b | = sqrt(v2.x * v2.x + v2.y * v2.y + v2.z * v2.z) = sqrt(v2.x * v2.x + v2.y * v2.y + v2.z * v2.z)

Divide top result by bottom two results, then take its arccos , remembering angle will be in radians. 将顶部结果除以底部两个结果,然后取其arccos ,记住的角度将以弧度为单位。

The basic mathematical formula to calculate an angle between two vectors is as such: 计算两个向量之间的夹角的基本数学公式如下:

Consider a & b to be vectors. 考虑a和b为向量。

a dot b = abs(a)*abs(b)*cos(angle) 点b = abs(a)* abs(b)* cos(angle)

-> cos-1((a dot b) / ( abs(a)*abs(b)) -> cos-1((a点b)/(abs(a)* abs(b))

Even though you are working in javascript the concept of doing the calculations are the same: What I can do for you is show you the functions from my Vector3 class that are written in c++ 即使您使用javascript工作,计算的概念也相同:我可以为您做的是向您展示Vector3类中用c ++编写的函数

// -----------------------------------------------------------------------
// GetCosAngle()
// Returns The cos(Angle) Value Between This Vector And Vector V. This
// Is Less Expensive Than Using GetAngle
inline float Vector3::GetCosAngle( const Vector3 &v3, const bool bNormalized ) {
    // a . b = |a||b|cos(angle)
    // -> cos-1((a.b)/(|a||b|))

    // Make Sure We Do Not Divide By Zero
    float fMagA = Length();
    if ( fMagA <= Math::ZERO ) {
        // This (A) Is An Invalid Vector
        return 0;
    }

    float fValue = 0;

    if ( bNormalized ) {
        // v3 Is Already Normalized
        fValue = Dot(v3)/fMagA;
    }
    else {
        float fMagB = v3.Length();
        if ( fMagB <= Math::ZERO) {
            // B Is An Invalid Vector
            return 0;
        }

        fValue = Dot(v3)/(fMagA*fMagB);
    }

    // Correct Value Due To Rounding Problem
    Math::Constrain( -1.0f, 1.0f, fValue );

    return fValue;

} // GetCosAngle

// -----------------------------------------------------------------------
// GetAngle()
// Returns The Angle Between This Vector And Vector V in Radians.
//         This Is More Expensive Than Using GetCosAngle
inline float Vector3::GetAngle( const Vector3 &v3, const bool bNormalized, bool bRadians ) {
    // a . b = |a||b|cos(angle)
    // -> cos-1((a.b)/(|a||b|))

    if ( bRadians ) {
        return acos( this->GetCosAngle( v3 ) );
    }
    else {
        // Convert To Degrees
        return Math::Radian2Degree( acos( GetCosAngle( v3, bNormalized ) ) );
    }

} // GetAngle

Here are the additional functions from within the Vector3 class that are used to do these calculations: 以下是Vector3类中用于执行这些计算的其他函数:

// -----------------------------------------------------------------------
// Length()
// Return The Length Of This Vector
inline float Vector3::Length() const {

    return sqrtf( _fX * _fX +
                  _fY * _fY +
                  _fZ * _fZ );

} // Length

// -----------------------------------------------------------------------
// Dot()
// Return The Dot Product Between This Vector And Another One
inline float Vector3::Dot( const Vector3 v3 ) const {

    return ( _fX * v3._fX + 
             _fY * v3._fY +
             _fZ * v3._fZ );
} // Dot

Here are my Math functions and values that are used within these calculations: 这是这些计算中使用的我的数学函数和值:

const float Math::PI            = 4.0f  * atan(1.0f); // tan(pi/4) = 1
const float Math::PI_INVx180    = 180.0f / Math::PI;
const float Math::ZERO          = (float)1e-7;

// -----------------------------------------------------------------------
// Constrain()
// Prevent Value From Going Outside The Min, Max Range.
template<class T>
inline void Math::Constrain( T min, T max, T &value ) {

    if ( value < min ) {
        value = min;
        return;
    }

    if ( value > max ) {
        value = max;
    }

} // Constrain

/ -----------------------------------------------------------------------
// Radian2Degree()
// Convert Angle In Radians To Degrees
inline float Math::Radian2Degree( float fRadians ) {
    return fRadians * PI_INVx180;
} // Radian2Degree

Now as I stated these belong to a couple of my c++ classes that are within one of my math libraries. 现在,正如我所说的,它们属于我的一个数学库中的几个c ++类。 This is used as a demonstration on how one would calculate an angle between two vectors. 这用作关于如何计算两个向量之间的角度的演示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM