【问题标题】:Robust polygon normal calculation强大的多边形法线计算
【发布时间】:2014-05-15 07:22:50
【问题描述】:

是否有一个很好的鲁棒算法来计算凸多边形的法向量(当然是 3D 的)?对于三角形,这很简单:取三角形的两条边并计算叉积:

vec3 u = point[0] - point[1], v = point[0] - point[2];
vec3 n = normalize(cross(u, v));

但是这种方法并不能很好地扩展到多边形。多边形的某些边可能几乎或“完全”共线(这经常发生在删除 T 形接头的网格中),因此有必要选择一对边,给出“强”法线(两条边都是“足够长”并且它们保持“几乎垂直”的角度)。

不过,这种方法仍然不适用于所有多边形。想象一个圆盘形状的多边形。如果细分得非常精细,则所有边都将非常短,并且所有连续的边将几乎共线,而与圆盘的半径无关。同时,法线也非常明确。

一种解决方案可能是找到最大的内接三角形并计算其法线。但是,找到它的复杂度将达到O(n^2),这似乎令人望而却步。

更好的解决方案可能是使用 SVD 或特征值分解来计算法线,给定所有多边形点,而不仅仅是三个或四个。

对此有标准算法吗?有谁有好的方法吗?

【问题讨论】:

    标签: algorithm 3d geometry numerical-methods


    【解决方案1】:

    如果对三角形的公式进行因式分解,您将得到以下结果:

    n ~ (p1 - p0) x (p2 - p0)
      = p0 x p1 + p1 x p2 + p2 x p0
    

    您可以将此公式推广到任意多边形:

    n ~ p0 x p1 + p1 x p2 + ... + pn x p0
    

    因此对连续边的叉积求和。这是一种稳健的算法,适用于非平面多边形。

    如果您可以确定多边形是平面的,我会执行以下操作(以节省计算时间):

    Repeat k times
        Pick 3 random polygon vertices
        Calculate the normal of the according triangle
    Choose the longest normal as the polygon's normal.
    

    您可以丢弃任何具有length <= epsilon 的法线。

    【讨论】:

    • 您考虑过光盘示例吗?我不认为它非常健壮,因为连续边的叉积在那里会相当小。但除此之外,谢谢,我想这在大多数情况下会更好。
    • 稳健性来自求和。
    • 此外,使用 epsilon 可以保证该方法在数值上不稳健。考虑在有狭窄多边形的地方使用网格。如果阈值很高,这些多边形将没有法线。如果它太低,算法可能会接受稍微不平坦的边缘或其他次优边缘对,即使在法线定义明确的多边形上也会产生不精确的法线。
    • 这也称为纽厄尔方法 (opengl.org/wiki/Calculating_a_Surface_Normal)。
    • @Lenny:各个加数不相等,但是总和是相等的。如果我们看一下 x 分量,Newell 方法的扩展公式是:nx += cur.y * next.z - next.y * cur.z - next.y * next.z + cur.y * cur.z。前两个和来自叉积。最后两个是额外的。所以每个顶点为自己添加y * z,并为下一个顶点减去y * z。如果您对所有顶点执行此操作,则附加项会抵消,您会得到叉积的总和。
    【解决方案2】:

    您可以计算多边形所有点的协方差矩阵(这将是 3D 空间的 3x3 矩阵)。多边形的法线将是对应于最小特征值的特征向量。

    【讨论】:

    • 知道如何确定法线方向吗?因为在计算协方差矩阵时,顶点的顺序丢失了。显然,可以使用叉积计算不太精确的法线,并将精确的法线翻转为指向更相似的方向。你能想出更优雅的解决方案吗?
    • 你是对的,协方差矩阵会失去连接性,因此法线向量可能有正号或负号,具体取决于您的约定。对不起,我不知道任何简单的方法,然后你提议的那个,得到标志。与其他方法相比,该方法非常稳健,但成本较高。
    【解决方案3】:

    从任意顶点开始(我们称之为顶点 A),然后移动到列表中的下一个顶点(称之为顶点 B)。计算 AB 向量的垂直向量(称为向量 P)。然后继续在顶点列表中迭代,找到垂直距离向量 AB 最远的顶点。因此,在每次迭代中,将当前元素(以顶点 B 为原点)与向量 P 的点积取为幅度结果最大的那个(取绝对值)并将其称为 C。计算的叉积ABC 向量。

    如果多边形是凸的,您可以停止迭代,直到垂直距离开始 幅度变小。

    我想出了这个想法,我不知道这种方法的效率有多高,因为我不知道任何其他算法可以与之比较。

    【讨论】:

    • 您无法真正计算 3 空间中的一个垂直向量。即使您将自己限制为单位长度向量,其中也有无数个。您可以计算从一点到通过两点 (AB) 的线的距离。您可以选择这样的 C,即与 AB 的最大距离。这与选择不同的 ABC 并根据其叉积的范数对其进行评分非常相似。
    • 在我的解决方案中,我假设多边形是一个平面,并且所有的点都是共面的。
    • 那是鸡和蛋的问题。你需要先知道那架飞机,才能得分。但是你正在得分,这样你就可以计算出那架飞机。我认为这行不通。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 2018-02-15
    • 2012-04-06
    • 2012-11-10
    • 2018-01-17
    • 1970-01-01
    相关资源
    最近更新 更多