三维多边形的中心点计算

时间:2014-03-17 21:30:06

标签: c# geometry

我试图找出一个平面多边形的中心,并想知道最好的方法是什么。

我可以访问构成多边形的顶点,但没有别的。

有没有人对如何处理此事有任何建议?

感谢。

2 个答案:

答案 0 :(得分:3)

我不打算投影到2D。

质心

顶点质量中心

对所有顶点的坐标求和,并除以顶点数。 请参阅centroid of a finite set of points

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

表面质量中心

对多边形进行三角测量,然后求和所有三角形的质心,按其面积加权,然后除以总面积。您可以选择三角测量,其中并非所有三角形都完全位于多边形内,只要外部区域由不同方向的三角形补偿即可。三角形的面积是其两个边缘向量的叉积长度的一半。

有关2D情况,请参阅centroid of polygon,但对于使用区域的此方法,请更合适centroid by geometric decomposition。另请参阅centroid of triangle,了解三角形曲面的质心等于其顶点的质心。

sx = sy = sz = sarea = 0
x1 = px[1]
y1 = py[1]
z1 = pz[1]
x2 = px[2]
y2 = py[2]
z2 = pz[2]
for i in 3..n:
    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

答案 1 :(得分:0)

我发现我需要对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;
    }