c++ - 找到多边形的质心?

标签 c++ c vector vector-graphics

为了获得中心,我尝试了,对于每个顶点,将其加到总数中,然后除以顶点数。

我也试过找到最上面,最下面 -> 得到中点...找到最左边,最右边,找到中点。

这两个都没有返回完美的中心,因为我依靠中心来缩放多边形。

我想缩放我的多边形,所以我可以在它们周围设置一个边框。

鉴于多边形可能是凹的、凸的并且有许多不同长度的边,找到多边形质心的最佳方法是什么?

最佳答案

公式给出here对于按其在多边形周长上出现次数排序的顶点

对于那些难以理解这些公式中的 sigma 表示法的人,这里有一些 C++ 代码展示了如何进行计算:

#include <iostream>

struct Point2D
{
    double x;
    double y;
};

Point2D compute2DPolygonCentroid(const Point2D* vertices, int vertexCount)
{
    Point2D centroid = {0, 0};
    double signedArea = 0.0;
    double x0 = 0.0; // Current vertex X
    double y0 = 0.0; // Current vertex Y
    double x1 = 0.0; // Next vertex X
    double y1 = 0.0; // Next vertex Y
    double a = 0.0;  // Partial signed area

    // For all vertices except last
    int i=0;
    for (i=0; i<vertexCount-1; ++i)
    {
        x0 = vertices[i].x;
        y0 = vertices[i].y;
        x1 = vertices[i+1].x;
        y1 = vertices[i+1].y;
        a = x0*y1 - x1*y0;
        signedArea += a;
        centroid.x += (x0 + x1)*a;
        centroid.y += (y0 + y1)*a;
    }

    // Do last vertex separately to avoid performing an expensive
    // modulus operation in each iteration.
    x0 = vertices[i].x;
    y0 = vertices[i].y;
    x1 = vertices[0].x;
    y1 = vertices[0].y;
    a = x0*y1 - x1*y0;
    signedArea += a;
    centroid.x += (x0 + x1)*a;
    centroid.y += (y0 + y1)*a;

    signedArea *= 0.5;
    centroid.x /= (6.0*signedArea);
    centroid.y /= (6.0*signedArea);

    return centroid;
}

int main()
{
    Point2D polygon[] = {{0.0,0.0}, {0.0,10.0}, {10.0,10.0}, {10.0,0.0}};
    size_t vertexCount = sizeof(polygon) / sizeof(polygon[0]);
    Point2D centroid = compute2DPolygonCentroid(polygon, vertexCount);
    std::cout << "Centroid is (" << centroid.x << ", " << centroid.y << ")\n";
}

我只测试了右上角 x/y 象限中的方形多边形。


如果您不介意在每次迭代中执行两个(可能很昂贵)额外的模运算,那么您可以将之前的 compute2DPolygonCentroid 函数简化为以下内容:

Point2D compute2DPolygonCentroid(const Point2D* vertices, int vertexCount)
{
    Point2D centroid = {0, 0};
    double signedArea = 0.0;
    double x0 = 0.0; // Current vertex X
    double y0 = 0.0; // Current vertex Y
    double x1 = 0.0; // Next vertex X
    double y1 = 0.0; // Next vertex Y
    double a = 0.0;  // Partial signed area

    // For all vertices
    int i=0;
    for (i=0; i<vertexCount; ++i)
    {
        x0 = vertices[i].x;
        y0 = vertices[i].y;
        x1 = vertices[(i+1) % vertexCount].x;
        y1 = vertices[(i+1) % vertexCount].y;
        a = x0*y1 - x1*y0;
        signedArea += a;
        centroid.x += (x0 + x1)*a;
        centroid.y += (y0 + y1)*a;
    }

    signedArea *= 0.5;
    centroid.x /= (6.0*signedArea);
    centroid.y /= (6.0*signedArea);

    return centroid;
}

关于c++ - 找到多边形的质心?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2792443/

相关文章:

c - 为什么执行这个基本程序会出错?

c - 如何使用 C 套接字 API 监听所有 IPV6 地址

r - 如何获取列表中每一项的第 n 个元素,它本身就是一个未知长度的向量

c++ - 为什么这些 C++ 案例实例化不同的模板

c - 为什么运行它不会发出段错误?

c++ - 检查 vector<vector<queue<msg>>> 中的 vector 'space' 是否为空

c++ - 访问 vector 的内容

c++ - 如何重载空 std::initializer_list?

c++ - 2个类之间的双向关联

c++ - Qt 和 OpenGL : texture transparency