【问题标题】:What is the need for normalizing a vector?对向量进行归一化需要什么?
【发布时间】:2012-04-03 23:26:51
【问题描述】:

尝试更多地理解向量。

对向量进行归一化需要什么?

如果我有一个向量,N = (x, y, z)

当你规范化它时你实际上得到了什么 - 我明白你必须除以 x/|N|是/|N| &z/|N|。我的问题是,我们为什么要做这件事,我的意思是我们从这个等式中得到了什么?

这样做的意义或“内部”目的是什么。

有点数学题,我很抱歉,但我真的不清楚这个话题。

【问题讨论】:

    标签: vector normalizing


    【解决方案1】:

    对于任何向量V = (x, y, z)|V| = sqrt(x*x + y*y + z*z) 给出向量的长度。

    当我们对一个向量进行归一化时,我们实际上计算的是V/|V| = (x/|V|, y/|V|, z/|V|)

    很容易看出,归一化向量的长度为 1。这是因为:

    | V/|V| | = sqrt((x/|V|)*(x/|V|) + (y/|V|)*(y/|V|) + (z/|V|)*(z/|V|))
              = sqrt(x*x + y*y + z*z) / |V|
              = |V| / |V|
              = 1
    

    因此,我们可以将归一化向量称为单位向量(即具有单位长度的向量)。

    任何向量,当归一化时,只会改变它的大小,而不是它的方向。此外,指向同一方向的每个向量都被归一化为同一向量(因为幅度和方向唯一地定义了一个向量)。因此,单位向量对于提供方向非常有用。

    但是请注意,以上所有讨论都是针对 3 维笛卡尔坐标(x, y, z)。但笛卡尔坐标的真正含义是什么?

    事实证明,要在 3D 空间中定义一个向量,我们需要一些参考方向。这些参考方向被规范地称为 ijk(或 i、j、k 上带有小大写字母 - 称为“i帽”、“j 帽”和“k 帽”)。任何我们认为是V = (x, y, z) 的向量实际上都可以写成V = xi + yj + zk。 (注意:我不再用大写字母来称呼它们,我只会称它们为 i、j、k)。 i、j 和 k 是 X、Y 和 Z 方向的单位向量,它们形成一组相互正交的单位向量。它们是所有笛卡尔坐标几何的基础。

    还有其他形式的坐标(例如圆柱坐标和球坐标),虽然它们的坐标不像(x, y, z)那样直接理解,但它们也是由一组3个相互正交的单位向量组成的,它们构成了基础3个坐标相乘得到一个向量。

    所以,上面的讨论清楚地表明我们需要单位向量来定义其他向量,但你为什么要关心呢?

    因为有时,只有量级很重要。那是当您使用“常规”数字时(例如 4 或 1/3 或 3.141592653 - 不,对于所有强迫症怪胎,我不会把 Pi 放在那里 - 这将保持一个终止小数,因为我是邪恶的化身)。你不想扔到一个讨厌的方向,是吗?我的意思是,说我要4公斤西瓜面向西方真的有意义吗?当然,除非你是个疯狂的狂热分子。

    其他时候,只有方向很重要。你只是不在乎量级,或者量级太大而无法理解(有点像无限,只是没有人真正知道无限到底是什么——万岁伟大的无限,因为他有无限的无限......对不起,有点忘乎所以)。在这种情况下,我们使用向量的归一化。例如,说我们有一条面向北 4 公里的线没有任何意义。说我们有一条面向北方的线更有意义。那你怎么办?你摆脱了4公里。你破坏了规模。你所剩下的就是北方(冬天来了)。经常这样做,你将不得不给你正在做的事情一个名字和符号。您不能只称其为“忽略大小”。那太粗鲁了。你是一个数学家,所以你把它叫做“归一化”,你给它一个“上限”的符号(可能是因为你想去参加一个聚会而不是被向量困住)。

    顺便说一句,由于我提到了笛卡尔坐标,这里是强制性的 XKCD:

    【讨论】:

    • 非常有帮助。清楚地了解标准化的重要性。
    • 这是一个很好的解释。事实上,我一直很喜欢这类问题,因为它会产生这样的答案,而且这里的一些人总是自己解释行话,而不解释为什么叫它的“为什么”。我是开发人员并且被行话所吸引(我根本不在乎),但有时他们命名的原因对我来说比它的作用更重要。例如(Espresso 单元测试中的 Intending 与 Intended 方法)和(反应式中的 map 与 flatMap 方法)。
    【解决方案2】:

    阅读Godot Game Enginedocumentation about unit vector、规范化和点积真的很有意义。这是文章:

    单位向量

    好的,所以我们知道什么是向量。它有方向和幅度。我们也知道如何在 Godot 中使用它们。下一步是学习单位向量。任何长度为 1 的向量都被视为单位向量。在 2D 中,想象绘制一个半径为 1 的圆。该圆圈包含所有存在的二维单位向量:

    那么,单位向量有什么特别之处呢?单位向量是惊人的。换句话说,单位向量有几个非常有用的属性。

    迫不及待地想了解更多关于单位向量奇妙特性的信息,但一步一步来。那么,单位向量是如何从正则向量创建的呢?

    标准化

    在保持方向不变的情况下,将任何向量的大小减小到 1.0 称为归一化。归一化是通过将向量的 x 和 y(以及 3D 中的 z)分量除以其大小来执行的:

    var a = Vector2(2,4)
    var m = sqrt(a.x*a.x + a.y*a.y)
    a.x /= m
    a.y /= m
    

    正如您可能已经猜到的那样,如果向量的大小为 0(这意味着它不是向量,而是原点也称为空向量),则会发生除以零并且宇宙经历第二次大爆炸,但极性相反的情况除外然后回来。结果,人类是安全的,但 Godot 会打印一个错误。记住! Vector(0,0) 无法归一化!

    当然,Vector2 和 Vector3 已经提供了一种方法来做到这一点:

    a = a.normalized()
    

    点积

    好的,点积是向量数学中最重要的部分。如果没有点积,Quake 就不会被制作出来。这是本教程中最重要的部分,因此请务必正确掌握。大多数试图理解向量数学的人在这里放弃了,因为尽管它很简单,但他们无法从中得出正面或反面。为什么?这就是为什么,这是因为......

    点积采用两个向量并返回一个标量:

    var s = a.x*b.x + a.y*b.y
    

    是的,差不多就是这样。将向量 a 中的 x 乘以向量 b 中的 x。对 y 执行相同操作并将其相加。在 3D 中几乎是一样的:

    var s = a.x*b.x + a.y*b.y + a.z*b.z
    

    我知道,这完全没有意义!您甚至可以使用内置函数来实现:

    var s = a.dot(b)
    

    两个向量的顺序无关紧要,a.dot(b) 返回的值与b.dot(a) 相同。

    这就是绝望开始的地方,书籍和教程向您展示了这个公式:

    A ⋅ B = ∥A∥ ∥B∥ cos(θ)

    您意识到是时候放弃制作 3D 游戏或复杂的 2D 游戏了。这么简单的事情怎么会这么复杂?其他人将不得不制作下一个塞尔达或使命召唤。毕竟,自上而下的 RPG 看起来并没有那么糟糕。是的,我听说有人对 Steam 上的其中一个做了很好的打算...

    所以这是你的时刻,这是你闪耀的时刻。不放弃!在这一点上,本教程将急转直下,重点关注点积的有用之处。这就是为什么它有用。我们将一一关注点积的用例,以及现实生活中的应用。没有更多没有任何意义的公式。一旦您了解了公式的用途,公式就会变得有意义。

    壁板 点积的第一个有用且最重要的属性是检查正在查看的内容。假设我们有任意两个向量,a 和 b。任何方向或大小(无原点)。不管它们是什么,但假设我们计算它们之间的点积。

    var s = a.dot(b)
    

    该操作将返回一个浮点数(但由于我们处于向量世界中,我们称它们为标量,从现在开始将继续使用该术语)。这个数字将告诉我们以下信息:

    如果数字大于零,则两者都朝向同一方向(它们之间的角度小于 90°)。 如果数字小于零,则两者都朝相反的方向看(它们之间的角度> 90°)。 如果数字为零,则向量的形状为 L(它们之间的角度为 90°)。

    让我们考虑一个真实的用例场景。想象 Snake 正在穿过一片森林,然后附近有一个敌人。我们如何快速判断敌人是否看到发现了 Snake?为了发现他,敌人必须能够看到 Snake。比方说,那么:

    Snake 在位置 A。 敌人在B位置。 敌人面向方向向量F。

    所以,让我们通过将两者相减来创建一个从守卫 (B) 到蛇 (A) 的新向量 BA:

    var BA = A - B
    

    理想情况下,如果守卫直视蛇,为了进行眼神交流,它会在与向量 BA 相同的方向上进行。

    如果 F 和 BA 的点积大于 0,就会发现 Snake。发生这种情况是因为我们将能够判断守卫面向他:

    if (BA.dot(F) > 0):
        print("!")
    

    到目前为止,Snake 似乎是安全的。

    支持单位向量 好的,现在我们知道两个向量之间的点积可以让我们知道它们是朝向同一侧、相反侧还是彼此垂直。

    无论大小如何,这对所有向量都适用,因此单位向量也不例外。但是,将相同的属性与单位向量一起使用会产生更有趣的结果,因为添加了一个额外的属性:

    如果两个向量都面向完全相同的方向(彼此平行,它们之间的角度为 0°),则结果标量为 1。 如果两个向量都面向完全相反的方向(彼此平行,但它们之间的角度为 180°),则结果标量为 -1。 这意味着单位向量之间的点积总是在 1 到 -1 的范围内。再说一遍……

    如果它们的角度为 0°,点积为 1。 如果它们的角度为 90°,则点积为 0。 如果它们的角度为 180°,则点积为 -1。 呃……这奇怪的熟悉……以前见过……在哪里?

    让我们取两个单位向量。第一个指向上方,第二个也指向上方,但我们会将其从上(0°)一直旋转到下(180°)...

    在绘制结果标量时!

    啊哈!现在一切都说得通了,这是一个余弦函数!

    我们可以这么说,那么,作为一个规则...

    两个单位向量之间的点积是这两个向量之间夹角的余弦值。所以,要获得两个向量之间的夹角,我们必须这样做:

    var angle_in_radians = acos( a.dot(b) )
    

    这有什么用?那么直接获得角度可能没有那么有用,但是能够分辨出角度是有用的参考。一个例子是在运动学角色演示中,当角色向某个方向移动时,我们会撞到一个物体。如何判断我们击中的是不是地板?

    通过将碰撞点的法线与先前计算的角度进行比较。

    这样做的美妙之处在于,相同的代码在 3D 中的工作方式完全相同且无需修改。矢量数学在很大程度上与维度数量无关,因此添加或删除轴只会增加很少的复杂性。

    【讨论】:

    • 这是一篇非常好的文章。我认为他们已经编辑并删掉了其中的许多部分。
    • @manaszon 这篇文章在答案的乞求中被提及
    • @Adelin 是的,我已经看到了,但是您正在参考最新的文档。正如 WeirdElfB0y 所说,他们对文章做了一些改动,这就是为什么我想把原始链接放在这里。 (但如果你愿意,我可以删除我的评论。)
    【解决方案3】:

    这有点像问我们为什么要乘以数字。它总是出现。

    我们使用的笛卡尔坐标系是正交基(由相互正交的长度为 1 的向量组成,基意味着任何向量都可以由这些向量的唯一组合表示),当您要旋转时您的基础(当您环顾四周时会出现在视频游戏机制中)您使用行和列是正交向量的矩阵。

    只要你开始在线性代数中使用矩阵,你就会需要正交向量。例子太多了,不一一列举。

    归根结底,我们不需要 归一化向量(就像我们不需要 汉堡包一样,我们可以没有它们,但是谁会去?),但是v / |v| 的类似模式经常出现,以至于人们决定给它一个名称和一个特殊的符号(向量上的 ^ 表示它是一个归一化向量)作为快捷方式。

    归一化向量(也称为单位向量)基本上是生活中的事实。

    【讨论】:

    • 太棒了。非常感谢。现在我有了更好的理解。矩阵表示有很大帮助! :)
    • 标准化有什么好处?
    • @StanlyMoses 可以根据两个分量来考虑向量 - 方向和幅度。通过将向量除以其大小,我们只保留方向分量并丢弃大小。例如, 和 变得等价。这对于投影等许多操作很有用。
    • Re Shuklaswag 的评论。处理管道中较少显式数据和较多隐式数据(例如,能够假设单位长度为 1)使得处理速度更快。
    【解决方案4】:

    您将其长度设为 1 - 找到指向同一方向的单位向量。

    这对于各种用途很有用,例如,如果您将向量与单位向量进行点积,则您将获得该向量在单位向量方向上的分量的长度。

    【讨论】:

      【解决方案5】:

      法线应该仅用作方向向量。它们用于光照计算,需要归一化的法线向量。

      【讨论】:

        【解决方案6】:

        我看到帖子很老了,但我还是想回答它,因为我没有看到明确的答案,为什么我们要规范化。向量归一化的原因是为了找到向量的确切大小以及它在另一个向量上的投影。

        示例=向量 a 在 b 上的投影是 b.cos(theta)

        enter image description here

        但在点积的情况下,两个向量 a 和 b 的点积是 a.b.cos(theta)

        这意味着点积是 a 超过 b 乘以 a 的投影。因此,我们将它除以 a 以进行归一化以找到投影的确切长度,即 (b.cos(theta))。 希望很清楚。

        【讨论】:

          猜你喜欢
          • 2012-07-25
          • 1970-01-01
          • 2017-03-24
          • 2019-09-26
          • 2015-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多