3D多边形的中心点计算

3

我正在尝试计算平面多边形的中心,想知道最好的方法是什么。

我可以访问构成多边形的顶点,但没有其他信息。

有人有任何建议吗?

谢谢。


“平面多边形”是指一个在未知平面内的多边形。如果您只有点的三维坐标,我们可以给您提供一种(可逆的)转换方法,但可能会有更简单的方法;当您说“中心”时,您是指质心、外心还是其他什么呢? - Beta
1
表面、边缘、顶点的质心是什么? - Olivier Jacot-Descombes
2个回答

7

我不会将其投影到二维平面。

质心

顶点的质心

将所有顶点的坐标相加,然后除以顶点数。 参见有限点集的质心

sx = sy = sz = 0
for i in 1..n:
    sx = sx + px[i]
    sy = sy + py[i]
    sz = sz + pz[i]
cx = sx/n
cy = sy/n
cz = sz/n

边缘质心

将所有边缘的质心按其长度加权求和,然后除以总周长。

sx = sy = sz = slen = 0
x1 = px[n]
y1 = py[n]
z1 = pz[n]
for i in 1..n:
    x2 = px[i]
    y2 = py[i]
    z2 = pz[i]
    dx = x2 - x1
    dy = y2 - y1
    dz = z2 - z1
    len = sqrt(dx*dx + dy*dy + dz*dz)
    sx = sx + (x1 + x2)/2*len
    sy = sy + (y1 + y2)/2*len
    sz = sz + (z1 + z2)/2*len
    slen = slen + len
    x1 = x2
    y1 = y2
    z1 = z2
cx = sx/slen
cy = sy/slen
cz = sz/slen

曲面的重心

将多边形三角剖分,然后按其面积加权求出所有三角形的重心之和,再除以总面积。您可以选择一种剖分方式,使得并非所有三角形都完全在多边形内部,只要通过不同方向的三角形来补偿外部区域即可。一个三角形的面积等于两个边向量的叉积的一半。

有关二维情况,请参见多边形的重心,但更合适的是使用面积的几何分解法。此外,三角形的重心说明了曲面的重心等于其顶点的重心。

sx = sy = sz = sarea = 0
x1 = px[1]
y1 = py[1]
z1 = pz[1]
for i in 3..n:
    x2 = px[i-1]
    y2 = py[i-1]
    z2 = pz[i-1]
    x3 = px[i]
    y3 = py[i]
    z3 = pz[i]
    dx1 = x3 - x1
    dy1 = y3 - y1
    dz1 = z3 - z1
    dx2 = x3 - x2
    dy2 = y3 - y2
    dz2 = z3 - z2
    cpx = dy1*dz2 - dz1*dy2
    cpy = dz1*dx2 - dx1*dz2
    cpz = dx1*dy2 - dy1*dx2
    area = sqrt(cpx*cpx + cpy*cpy + cpz*cpz)/2
    sx = sx + (x1 + x2 + x3)/3*area
    sy = sy + (y1 + y2 + y3)/3*area
    sz = sz + (z1 + z2 + z3)/3*area
    sarea = sarea + area
cx = sx/sarea
cy = sy/sarea
cz = sz/sarea

你不必担心凹线,因为奇怪的情况会被消除,代码应该适用于任何多边形。你是对的,我的 px,py,pz 是坐标数组。使用基于 1 或基于 0 的索引取决于你的编程语言,但既然你问了,你可能想从 0 开始。并且使用 [n-1] 而不是 [n] 来访问边界循环之前的最后一个点。我的答案一直使用基于 1 的伪代码编写,因为大多数数学公式都是基于 1 表示的。 - MvG

1
我发现我需要对MvG质心计算的小细节进行调整,以便在每个循环结束时将point2更改为point3(请参见下面的“p2 = p3;”)。 我希望这就是他的本意,所以每个区域只计数一次。这是修改后代码的C#版本。
    public Point3D CalculateCentroid(List<Point3D> verticies)
    {
        var s = new Vector3D();
        var areaTotal = 0.0;

        var p1 = verticies[0];
        var p2 = verticies[1];

        for (var i = 2; i < verticies.Count; i++)
        {
            var p3 = verticies[i];
            var edge1 = p3 - p1;
            var edge2 = p3 - p2;

            var crossProduct = Vector3D.CrossProduct(edge1, edge2);
            var area = crossProduct.Length/2;

            s.X += area * (p1.X + p2.X + p3.X)/3;
            s.Y += area * (p1.Y + p2.Y + p3.Y)/3;
            s.Z += area * (p1.Z + p2.Z + p3.Z)/3;

            areaTotal += area;
            p2 = p3;
        }

        var point = new Point3D
        {
            X = s.X/areaTotal,
            Y = s.Y/areaTotal,
            Z = s.Z/areaTotal
        };


        return point;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接