给定任意凸面二维多边形,计算惯性矩

Par*_*yes 6 physics game-physics

我已经研究了这个问题了几个小时,由于某种原因,我一直无法找到解决方案。

给定一个凸多边形,该多边形定义为围绕多边形质心按顺时针顺序排列的点数组,如何计算多边形的惯性矩?

我已经能够找到各种形状的方程,例如矩形或圆形,但是找不到任意的凸多边形。

例如,以质量m,高度h和宽度w绕其质心旋转的矩形的惯性矩计算如下:

矩形的惯性矩

我正在寻找类似的公式/算法,但要寻找凸多边形。

ja7*_*a72 5

有一种使用向量代数分析 2D 多边形的方法,在我看来,它比依赖三角学的方法更容易以编程方式实现。

每个Vector数量有两个分量.x.y 方法向量代数向量,包括点积和叉积

add(a,b) = [a.x+b.x, a.y+b.y]    // a+b = add(a,b)
scale(f,x) = [f*a.x, f*a.y]      // 2*a = scale(2,a), a/3 = scale(1/3,a)
dot(a,b) = a.x*b.x + a.y*b.y     // a·b = dot(a,b)
cross(a,b) = a.x*b.y - a.y*b.x   // a×b = cross(a,b)
Run Code Online (Sandbox Code Playgroud)

下面的方法遍历多边形的所有边,并将面积、中心和关于由边和原点定义的每个三角形的坐标原点的质量惯性矩相加。最后的总和负责添加或减去靠近或远离原点的区域,并产生准确的结果

最后,质量力矩从原点转移到质心。

polygon(Vector[] points, double depth, double density)
{
    // Accumulate the following values
    double area = 0.0;
    double mass = 0.0;
    Vector center = [0.0, 0.0];
    double mmoi = 0.0;

    // Take each vertex pair starting from the last-first vertex
    // in order to consider all sides.
    int count = points.Length;
    int prev = count - 1;
    for(int index=0; index<count; index++)
    {
        Vector a = points[prev];
        Vector b = points[index];

        double area_step = TriangleArea(a,b);
        double mass_step = density * area_step * depth;
        Vector center_step = TriangleCenter(a,b);
        double mmoi_step = TriangleMmoi(a,b, mass_step);

        area += area_step;
        center = (mass*center + mass_step*center_step)/(mass+mass_step);
        mass += mass_step;
        mmoi += mmoi_step;

        prev = index;
    }

    // Transfer mass moment of inertia from the origin to the center of mass
    mmoi -= mass*dot(center,center);

    // use area, mass, center and mmoi
}

double TriangleArea(Vector a, Vector b)
{
    return cross(a,b)/2;
}
double TriangleCenter(Vector a, Vector b)
{
    return (a+b)/3;
{
double TriangleMmoi(Vector a, Vector b, double triangleMass)
{
    return triangleMass/6*(dot(a,a)+dot(b.b)+dot(a.b));
}
Run Code Online (Sandbox Code Playgroud)

以上是本答案中概述的类似过程。更多细节包含在链接的答案中。


下面是c#上面的实现,但指定了质量,而不是密度和厚度。

public static RigidBody2 FromShape(double mass, params Vector2[] polygon)
{
    double area = 0;
    Vector2 center = Vector2.Zero;
    double mmoi = 0;

    int prev = polygon.Length-1;
    for (int index = 0; index < polygon.Length; index++)
    {
        var a = polygon[prev];
        var b = polygon[index];

        var area_step = Vector2.Cross(a, b)/2;
        var center_step = (a+b)/3;
        var mmoi_step = area_step*(Vector2.Dot(a, a)+Vector2.Dot(b, b)+Vector2.Dot(a, b))/6;

        center = (center*area + center_step * area_step)/(area + area_step);
        area += area_step;
        mmoi += mmoi_step;

        prev = index;
    }

    double density = mass/area;
    mmoi *= density;
    mmoi -= mass * Vector2.Dot(center, center);

    return new RigidBody2(mass, mmoi, center);
}
Run Code Online (Sandbox Code Playgroud)

在测试中我使用了以下形状

形状

以及在 CAD 包中完成的分析的结果center = [1.0, 0.75]mmoi = 787.5匹配

计算机辅助设计

这是检查 CAD 数据的单元测试:

[TestMethod, TestCategory("Linear Algebra, Planar")]
public void Geom_PlanarPolygonMass()
{
    Vector2[] points = new Vector2[] {
        Vector2.Cartesian(0.75, 0),
        Vector2.Cartesian(2, 0),
        Vector2.Cartesian(2, 0.5),
        Vector2.Cartesian(1.25, 0.5),
        Vector2.Cartesian(1.25, 1.5),
        Vector2.Cartesian(0, 1.5),
        Vector2.Cartesian(0, 1.0),
        Vector2.Cartesian(0.75, 1),
    };

    var rg = RigidBody2.FromShape(1500, points);

    Assert.AreEqual(1500, rg.Mass);
    CollectionAssert.AreEqual(Vector2.Cartesian(1.0, 0.75), rg.LocalCg, AbsComparer(TinyNumber));
    Assert.AreEqual(687.5, rg.LocalMmoi, DoubleEx.TinyNumber);
}
Run Code Online (Sandbox Code Playgroud)


Pio*_*him 0

惯性矩的方程非常简单,您可以在这里找到它的解释: https: //en.wikipedia.org/wiki/Moment_of_inertia

例如,它被用来推导您引用的方程。

正如安迪·纽曼(Andy Newman)提到的,凸多边形可以被认为是由三角形组成的。但将它们各自的惯性相加并不是一个解决方案 - 它不会产生考虑旋转轴的有效方程。

因此,您基本上需要做的是导出多边形相对于您想要旋转它的旋转轴的方程。

您可能会发现以下定理之一很有帮助,具体取决于您想要的形状类型: