Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 鲁棒多边形法线计算_Algorithm_3d_Geometry_Numerical Methods - Fatal编程技术网

Algorithm 鲁棒多边形法线计算

Algorithm 鲁棒多边形法线计算,algorithm,3d,geometry,numerical-methods,Algorithm,3d,Geometry,Numerical Methods,是否有一个好的鲁棒算法来计算凸多边形的法向量(当然是在3D中)?对于三角形,这很简单:取三角形的两条边并计算叉积: vec3 u = point[0] - point[1], v = point[0] - point[2]; vec3 n = normalize(cross(u, v)); 但这种方法并不能很好地扩展到多边形。多边形的某些边可以近似或“完全”共线(这通常发生在删除T形连接的网格中),因此有必要选择一对边,以提供“强”法线(两条边都“足够长”,并且它们保持“几乎垂直”的角度) 不

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

vec3 u = point[0] - point[1], v = point[0] - point[2];
vec3 n = normalize(cross(u, v));
但这种方法并不能很好地扩展到多边形。多边形的某些边可以近似或“完全”共线(这通常发生在删除T形连接的网格中),因此有必要选择一对边,以提供“强”法线(两条边都“足够长”,并且它们保持“几乎垂直”的角度)

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

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

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


有标准的算法吗?任何人都有这样做的好方法吗?

如果你将三角形的公式分解,你会得到以下结果:

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
所以求连续边的叉积和。这是一种稳健的算法,适用于非平面多边形

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


您可以放弃具有
长度的任何法线。您可以计算多边形所有点的协方差矩阵(对于三维空间,协方差矩阵为3x3)。多边形的法线将是对应于最小特征值的特征向量。

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

如果多边形是凸的,则可以停止迭代,直到垂直距离开始增加 在数量上变小


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

您考虑过光盘示例吗?我不认为它非常健壮,因为连续边的叉积在这里相当小。但另外,谢谢,我想这在大多数情况下都会更好。稳健性来自求和。而且,使用ε可以保证方法在数值上不稳健性。考虑有一个有窄多边形的网格。如果阈值较高,则这些多边形将没有法线。如果它太低,该算法可能会接受稍微非平面的边或其他次优的边对,即使在法线定义良好的多边形上也会产生不精确的法线。这也被称为Newell方法()。@Lenny:各个和数不相等,但是,和数不相等。如果我们看一下x分量,纽厄尔方法的扩展公式是:
nx+=cur.y*next.z-next.y*cur.z-next.y*cur.z-next.y*next.z+cur.y*cur.z
。前两个总和来自叉积。最后两个是附加的。因此,每个顶点为自身添加
y*z
,为下一个顶点减去
y*z
。如果你对所有顶点都这样做,附加的项就会被抵消,得到叉积之和。你知道如何确定法线方向吗?因为在计算协方差矩阵时,顶点的顺序丢失了。显然,可以使用叉积计算不太精确的法线,并将精确法线翻转到更相似的方向。你能想出一个更优雅的解决方案吗?你是对的,协方差矩阵将失去连通性,因此法向量可能有一个正号或负号,这取决于你的约定。对不起,我不知道有什么简单的办法,那就是你提议的那个办法,来得到这个标志。与其他方法相比,该方法非常稳健,但成本昂贵。你无法真正计算3-空间中的一个垂直向量。其中有无限多个向量,即使你将自己限制为单位长度向量。可以计算从一点到通过两点的直线的距离(AB)。你可以选择这样的C,它是距离AB的最大距离。这与选择不同的ABC并根据它们的叉积的范数对它们进行评分非常相似。在我的解决方案中,我假设多边形是一个平面,所有的点都是共面的。这有点像是鸡和蛋的问题。你需要先知道那架飞机,才能得分。但是你正在得分,这样你就可以计算出这个平面。我认为那不行。
Repeat k times
    Pick 3 random polygon vertices
    Calculate the normal of the according triangle
Choose the longest normal as the polygon's normal.