多边形的重心

mix*_*kat 20 algorithm geometry polygon geolocation gravity

我正在尝试编写一个PHP函数来计算多边形的重心.

我看过其他类似的问题,但我似乎无法找到解决方案.

我的问题是我需要能够计算规则和不规则多边形甚至自相交多边形的重心.

那可能吗?

我也读过:http://paulbourke.net/geometry/polyarea/ 但这仅限于非自相交的多边形.

我怎样才能做到这一点?你能指出我正确的方向吗?

red*_*t84 34

重心(也称为"质心"或"质心")可以使用以下公式计算:

X = SUM[(Xi + Xi+1) * (Xi * Yi+1 - Xi+1 * Yi)] / 6 / A
Y = SUM[(Yi + Yi+1) * (Xi * Yi+1 - Xi+1 * Yi)] / 6 / A
Run Code Online (Sandbox Code Playgroud)

维基百科中提取:由n个顶点(x0,y0),(x1,y1),...,(xn-1,yn-1)定义的非自相交闭合多边形的质心是点(Cx, Cy),在哪里
中心的X坐标
中心的Y坐标
其中A是多边形的有符号区域,
面积公式

使用VBasic的示例:

' Find the polygon's centroid.
Public Sub FindCentroid(ByRef X As Single, ByRef Y As _
    Single)
Dim pt As Integer
Dim second_factor As Single
Dim polygon_area As Single

    ' Add the first point at the end of the array.
    ReDim Preserve m_Points(1 To m_NumPoints + 1)
    m_Points(m_NumPoints + 1) = m_Points(1)

    ' Find the centroid.
    X = 0
    Y = 0
    For pt = 1 To m_NumPoints
        second_factor = _
            m_Points(pt).X * m_Points(pt + 1).Y - _
            m_Points(pt + 1).X * m_Points(pt).Y
        X = X + (m_Points(pt).X + m_Points(pt + 1).X) * _
            second_factor
        Y = Y + (m_Points(pt).Y + m_Points(pt + 1).Y) * _
            second_factor
    Next pt

    ' Divide by 6 times the polygon's area.
    polygon_area = PolygonArea
    X = X / 6 / polygon_area
    Y = Y / 6 / polygon_area

    ' If the values are negative, the polygon is
    ' oriented counterclockwise. Reverse the signs.
    If X < 0 Then
        X = -X
        Y = -Y
    End If
End Sub
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请查看本网站维基百科.

希望能帮助到你.

问候!

  • @mixkat对于交叉多边形,您必须使用维基百科文章中描述的_integral公式.或者将多边形分解为非交叉多边形并使用上述方法. (2认同)
  • 如果物理对象具有均匀的密度,则其质心与其形状的质心相同.对上述公式的要求是'非自相交的闭合多边形',因此多边形的顶点将仅形成一个非自相交的闭合多边形. (2认同)

Jos*_*eph 8

在冷c ++中,假设你有一个带有x和y属性的Vec2结构:

const Vec2 findCentroid(Vec2* pts, size_t nPts){
    Vec2 off = pts[0];
    float twicearea = 0;
    float x = 0;
    float y = 0;
    Vec2 p1, p2;
    float f;
    for (int i = 0, j = nPts - 1; i < nPts; j = i++) {
        p1 = pts[i];
        p2 = pts[j];
        f = (p1.x - off.x) * (p2.y - off.y) - (p2.x - off.x) * (p1.y - off.y);
        twicearea += f;
        x += (p1.x + p2.x - 2 * off.x) * f;
        y += (p1.y + p2.y - 2 * off.y) * f;
    }

    f = twicearea * 3;

    return Vec2(x / f + off.x, y / f + off.y);
}
Run Code Online (Sandbox Code Playgroud)

并在JavaScript中:

function findCentroid(pts, nPts) {
    var off = pts[0];
    var twicearea = 0;
    var x = 0;
    var y = 0;
    var p1,p2;
    var f;
    for (var i = 0, j = nPts - 1; i < nPts; j = i++) {
        p1 = pts[i];
        p2 = pts[j];
        f = (p1.lat - off.lat) * (p2.lng - off.lng) - (p2.lat - off.lat) * (p1.lng - off.lng);
        twicearea += f;
        x += (p1.lat + p2.lat - 2 * off.lat) * f;
        y += (p1.lng + p2.lng - 2 * off.lng) * f;
    }
    f = twicearea * 3;
    return {
    X: x / f + off.lat,
    Y: y / f + off.lng
    };
}
Run Code Online (Sandbox Code Playgroud)

或者在旧的c中,并假设你有一个带有x和y属性的Point结构:

const Point centroidForPoly(const int numVerts, const Point* verts)
{
    float sum = 0.0f;
    Point vsum = 0;

    for (int i = 0; i<numVerts; i++){
        Point v1 = verts[i];
        Point v2 = verts[(i + 1) % numVerts];
        float cross = v1.x*v2.y - v1.y*v2.x;
        sum += cross;
        vsum = Point(((v1.x + v2.x) * cross) + vsum.x, ((v1.y + v2.y) * cross) + vsum.y);
    }

    float z = 1.0f / (3.0f * sum);
    return Point(vsum.x * z, vsum.y * z);
}
Run Code Online (Sandbox Code Playgroud)