即使我遵循公式,为啥我的 2 个向量的角度函数返回 NaN

Posted

技术标签:

【中文标题】即使我遵循公式,为啥我的 2 个向量的角度函数返回 NaN【英文标题】:Why is my angle of 2 vectors function return NaN even though i follow the formula即使我遵循公式,为什么我的 2 个向量的角度函数返回 NaN 【发布时间】:2021-10-20 21:03:09 【问题描述】:

我正在制作一个函数,使用点积公式为我的统一游戏计算 2 个给定向量之间的角度:

vector(a)*vector(b)=|vector(a)|*|vector(b)|*cos(the angle)

所以我认为角度等于

acos((vector(a)*vector(b))/(|vector(a)|*|vector(b)|))

这是我的代码:

float rotateAngle(Vector2 a,Vector2 b)
    
        return Mathf.Acos((a.x * b.x + a.y * b.y) / ((Mathf.Sqrt(a.x * a.x + a.y * a.y)) * (Mathf.Sqrt(b.x * b.x + b.y * b.y)))) * (180 / Mathf.PI);
    

但是当我播放它时,控制台显示NaN。我已经尝试并查看了代码和公式,但空手而归。

有人可以帮助我吗?提前谢谢你!

【问题讨论】:

【参考方案1】:

float.NaN 是未定义(实数)数学运算的结果,例如 0 / 0(请注意,x / 0 其中x != 0 返回正或负无穷大)或负数的平方根价值。只要一个操作中的一个操作员已经是NaN,那么整个操作也会再次返回NaN

第二个(负值的平方根)不能在这里发生,因为您使用的是平方值,所以很可能您的向量的大小为 0


如果您查看Vector2 source code,您会发现他们实现了Vector2.AngleVector2.SignedAngle(您应该使用btw,因为它们已经过测试并且效率更高)。

    public static float Angle(Vector2 from, Vector2 to)
    
        // sqrt(a) * sqrt(b) = sqrt(a * b) -- valid for real numbers
        float denominator = (float)Math.Sqrt(from.sqrMagnitude * to.sqrMagnitude);
        if (denominator < kEpsilonNormalSqrt)
            return 0F;

        float dot = Mathf.Clamp(Dot(from, to) / denominator, -1F, 1F);
        return (float)Math.Acos(dot) * Mathf.Rad2Deg;
    

    // Returns the signed angle in degrees between /from/ and /to/. Always returns the smallest possible angle
    public static float SignedAngle(Vector2 from, Vector2 to)
    
        float unsigned_angle = Angle(from, to);
        float sign = Mathf.Sign(from.x * to.y - from.y * to.x);
        return unsigned_angle * sign;
    

在那里你会发现他们检查的第一件事是

float denominator = (float)Math.Sqrt(from.sqrMagnitude * to.sqrMagnitude);
if (denominator < kEpsilonNormalSqrt)
    return 0F;

这基本上可以确保两个给定向量都具有“足够大”的量级,尤其是不是0 的向量;)


长话短说:不要重新发明***,而是使用已经内置的 Vector2.AngleVector2.SignedAngle

【讨论】:

实际上我从一开始就尝试了 Vector2.SignedAngle 但它没有用。我刚刚重新检查了一下,结果发现我从和到的向量都搞砸了。非常感谢您的详细解释:D 经验教训:)【参考方案2】:

NaN 通常是对浮点数进行无效数学运算的结果。一个常见的来源是除以零,所以我的猜测是向量是 0,0。

我还建议使用内置函数来计算标准化、长度/幅度、点等,这将使代码更易于阅读,并且编译器应该非常擅长优化此类代码。如果您需要进行任何额外的优化,请仅在完成一些测量后进行。

【讨论】:

啊啊啊是的,这就是问题所在!我的向量中有 1 个是 (0,0),所以它搞砸了。非常感谢,我也去找找这些内置函数:)

以上是关于即使我遵循公式,为啥我的 2 个向量的角度函数返回 NaN的主要内容,如果未能解决你的问题,请参考以下文章

为啥可以从函数返回“向量”?

OpenGL 计算三角形法线 C++

向量旋转公式:

为啥我不能在使用 sort_by_key 对向量进行排序时使用返回引用的键函数?

三维方形坐标空间内转角对应的单位向量

为啥即使配置文件设置为分发,xcode 也会抛出此错误?