Calculate moment of inertia given an arbitrary convex 2D polygon
Asked Answered
L

2

10

I've been researching this question for hours and for some reason I haven't been able to find the solution.

Given a convex polygon that is defined as an array of points in clockwise order around the polygon's centroid, how can I calculate the polygon's moment of inertia?

I've been able to find the equation for various shapes such as rectangles or circles, but not for an arbitrary convex polygon.

For example, the moment of inertia of a rectangle rotating about its centroid with mass m, height h, and width w is calculated as:

Moment of Inertia for a Rectangle

I am looking for a similar fomula / algorithm but for a convex polygon instead.

Letha answered 29/6, 2015 at 1:8 Comment(3)
Find one of the (many) algorithms for subdividing a convex polygon into triangles (graphics needs to do this a lot). Calculate the moment of each triangle. Add them all up.Duffel
Juts for clarification you want the mass moment of inertia used for dynamics and not the second moment of area used in beam deflections?Sclerite
Does this answer your question? Computing tensor of Inertia in 2DSclerite
S
9

There is method to analyze a 2D polygon using vector algebra that is in my opinion easier to implement programmatically than the methods relying on trigonometry.

Each Vector quantity has two components .x and .y as well as methods vector algebra vectors including for dot and cross product

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)

The method below goes through all the sides of a polygon and sum up the area, the center and the mass moment of inertia about the coordinate origin of each triangle defined by the side and the origin. The final sum takes care of adding or subtracting areas near or far from the origin and yield the accurate results.

Finally, the mass moment is transferred from the origin to the center of mass.

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));
}

The above is a similar process as outlined in this answer. More details are included in the linked answer.


Below is a c# implementation of the above, but with specifying the mass, instead of the density and thickness.

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);
}

In testing I used the following shape

shape

and the results of center = [1.0, 0.75] and mmoi = 687.5 match with analysis done in CAD package

CAD

Here is the unit test that checks against the CAD data:

[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);
}
Sclerite answered 21/11, 2019 at 20:58 Comment(4)
I can't do an edit of just one character, but the MMOI is 687.5, not 787.5 - there's a typo in the answer.Fishbein
@JohnAaron - good catch, thank you.Sclerite
I know this is old, but there seem to be a bug if you use a Vector2(0, 0) somewhere in your points test for the C# implementation. Then you get center(NaN, NaN) (Dividing by 0).Falda
@Falda - check if step_area is zero. If yes, proceed to the next iteration. Otherwise, you are dividing by zero if the zero area element is the first element to consider (and area=0)Sclerite
G
0

The equation for a moment of inertia is pretty straightforward, and you can find it explained here: https://en.wikipedia.org/wiki/Moment_of_inertia

It was used for example to derive the equation you quoted.

As Andy Newman mentioned, a convex polygon can be considered as comprised of triangles. But summing their individual inertias up is not an solution - it won't produce a valid equation that takes the rotation axis into account.

So what you would need to do basically is derive an equation for your polygon with respect to the rotation axis you want to rotate it about.

You may find one of the following theorems helpful, depending on the type of shape you have in mind:

Godderd answered 13/3, 2017 at 16:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.