代码之家  ›  专栏  ›  技术社区  ›  Martijn Courteaux

计算凹形二维多边形相对于其原点的转动惯量

  •  4
  • Martijn Courteaux  · 技术社区  · 15 年前

    我想计算(二维)凹多边形的转动惯量。我在网上找到这个。但我不太确定如何解释这个公式…

    Formula http://img101.imageshack.us/img101/8141/92175941c14cadeeb956d8f.gif

    1)这个公式正确吗?
    2)如果是这样,我对C++的转换是否正确?

    float sum (0);
    for (int i = 0; i < N; i++) // N = number of vertices
    {
        int j = (i + 1) % N;
        sum += (p[j].y - p[i].y) * (p[j].x + p[i].x) * (pow(p[j].x, 2) + pow(p[i].x, 2)) - (p[j].x - p[i].x) * (p[j].y + p[i].y) * (pow(p[j].y, 2) + pow(p[i].y, 2));
    }
    float inertia = (1.f / 12.f * sum) * density;
    

    马蒂恩

    4 回复  |  直到 11 年前
        1
  •  4
  •   Larry Wang    15 年前
    #include <math.h> //for abs
    float dot (vec a, vec b) {
       return (a.x*b.x + a.y*b.y);
    }
    float lengthcross (vec a, vec b) {
       return (abs(a.x*b.y - a.y*b.x));
    }
    ...
    do stuff
    ...
    float sum1=0;
    float sum2=0;
    for (int n=0;n<N;++n)  { //equivalent of the Σ
       sum1 += lengthcross(P[n+1],P[n])* 
               (dot(P[n+1],P[n+1]) + dot(P[n+1],P[n]) + dot(P[n],P[n]));
       sum2 += lengthcross(P[n+1],P[n]);
    }
    return (m/6*sum1/sum2);
    

    编辑:许多小的数学变化

        2
  •  1
  •   duffymo    15 年前

    我认为你有更多的工作要做,仅仅是把公式翻译成代码。你需要准确理解这个公式的含义。

    当你有一个二维多边形,你有三个转动惯量,你可以计算相对于一个给定的坐标系:关于x的力矩,关于y的力矩,和极惯性矩。有一个平行轴定理,可以让你从一个坐标系转换到另一个坐标系。

    你知道这个公式适用于哪个力矩和坐标系吗?

    下面是一些可以帮助您的代码,以及一个JUnit测试来证明它是有效的:

    import java.awt.geom.Point2D;
    
    /**
     * PolygonInertiaCalculator
     * User: Michael
     * Date: Jul 25, 2010
     * Time: 9:51:47 AM
     */
    public class PolygonInertiaCalculator
    {
        private static final int MIN_POINTS = 2;
    
        public static double dot(Point2D u, Point2D v)
        {
            return u.getX()*v.getX() + u.getY()*v.getY();
        }
    
        public static double cross(Point2D u, Point2D v)
        {
            return u.getX()*v.getY() - u.getY()*v.getX();
        }
    
        /**
         * Calculate moment of inertia about x-axis
         * @param poly of 2D points defining a closed polygon
         * @return moment of inertia about x-axis
         */
        public static double ix(Point2D [] poly)
        {
            double ix = 0.0;
    
            if ((poly != null) && (poly.length > MIN_POINTS))
            {
                double sum = 0.0;
                for (int n = 0; n < (poly.length-1); ++n)
                {
                    double twiceArea = poly[n].getX()*poly[n+1].getY() - poly[n+1].getX()*poly[n].getY();
                    sum += (poly[n].getY()*poly[n].getY() + poly[n].getY()*poly[n+1].getY() + poly[n+1].getY()*poly[n+1].getY())*twiceArea;
                }
    
                ix = sum/12.0;
            }
    
            return ix;
        }
    
        /**
         * Calculate moment of inertia about y-axis
         * @param poly of 2D points defining a closed polygon
         * @return moment of inertia about y-axis
         * @link http://en.wikipedia.org/wiki/Second_moment_of_area
         */
        public static double iy(Point2D [] poly)
        {
            double iy = 0.0;
    
            if ((poly != null) && (poly.length > MIN_POINTS))
            {
                double sum = 0.0;
                for (int n = 0; n < (poly.length-1); ++n)
                {
                    double twiceArea = poly[n].getX()*poly[n+1].getY() - poly[n+1].getX()*poly[n].getY();
                    sum += (poly[n].getX()*poly[n].getX() + poly[n].getX()*poly[n+1].getX() + poly[n+1].getX()*poly[n+1].getX())*twiceArea;
                }
    
                iy = sum/12.0;
            }
    
            return iy;
        }
    
        /**
         * Calculate polar moment of inertia xy
         * @param poly of 2D points defining a closed polygon
         * @return polar moment of inertia xy
         * @link http://en.wikipedia.org/wiki/Second_moment_of_area
         */
        public static double ixy(Point2D [] poly)
        {
            double ixy = 0.0;
    
            if ((poly != null) && (poly.length > MIN_POINTS))
            {
                double sum = 0.0;
                for (int n = 0; n < (poly.length-1); ++n)
                {
                    double twiceArea = poly[n].getX()*poly[n+1].getY() - poly[n+1].getX()*poly[n].getY();
                    sum += (poly[n].getX()*poly[n+1].getY() + 2.0*poly[n].getX()*poly[n].getY() + 2.0*poly[n+1].getX()*poly[n+1].getY() + poly[n+1].getX()*poly[n].getY())*twiceArea;
                }
    
                ixy = sum/24.0;
            }
    
            return ixy;
        }
    
        /**
         * Calculate the moment of inertia of a 2D concave polygon
         * @param poly array of 2D points defining the perimeter of the polygon
         * @return moment of inertia
         * @link http://www.physicsforums.com/showthread.php?t=43071
         * @link http://www.physicsforums.com/showthread.php?t=25293
         * @link http://stackoverflow.com/questions/3329383/help-me-with-converting-latex-formula-to-code
         */
        public static double inertia(Point2D[] poly)
        {
            double inertia = 0.0;
    
            if ((poly != null) && (poly.length > MIN_POINTS))
            {
                double numer = 0.0;
                double denom = 0.0;
                double scale;
                double mag;
                for (int n = 0; n < (poly.length-1); ++n)
                {
                    scale = dot(poly[n + 1], poly[n + 1]) + dot(poly[n + 1], poly[n]) + dot(poly[n], poly[n]);
                    mag = Math.sqrt(cross(poly[n], poly[n+1]));
                    numer += mag * scale;
                    denom += mag;
                }
    
                inertia = numer / denom / 6.0;
            }
    
            return inertia;
        }
    }
    

    这是伴随它的JUnit测试:

    import org.junit.Test;
    
    import java.awt.geom.Point2D;
    
    import static org.junit.Assert.assertEquals;
    
    /**
     * PolygonInertiaCalculatorTest
     * User: Michael
     * Date: Jul 25, 2010
     * Time: 10:16:04 AM
     */
    public class PolygonInertiaCalculatorTest
    {
        @Test
        public void testTriangle()
        {
            Point2D[] poly =
            {
                new Point2D.Double(0.0, 0.0),
                new Point2D.Double(1.0, 0.0),
                new Point2D.Double(0.0, 1.0)
            };
    
    
            // Moment of inertia about the y1 axis
            // http://www.efunda.com/math/areas/triangle.cfm
            double expected = 1.0/3.0;
            double actual = PolygonInertiaCalculator.inertia(poly);
    
            assertEquals(expected, actual, 1.0e-6);
        }
    
        @Test
        public void testSquare()
        {
            Point2D[] poly =
            {
                new Point2D.Double(0.0, 0.0),
                new Point2D.Double(1.0, 0.0),
                new Point2D.Double(1.0, 1.0),
                new Point2D.Double(0.0, 1.0)
            };
    
            // Polar moment of inertia about z axis
            // http://www.efunda.com/math/areas/Rectangle.cfm
            double expected = 2.0/3.0;
            double actual = PolygonInertiaCalculator.inertia(poly);
    
            assertEquals(expected, actual, 1.0e-6);
        }
    
        @Test
        public void testRectangle()
        {
            // This gives the moment of inertia about the y axis for a coordinate system
            // through the centroid of the rectangle
            Point2D[] poly =
            {
                new Point2D.Double(0.0, 0.0),
                new Point2D.Double(4.0, 0.0),
                new Point2D.Double(4.0, 1.0),
                new Point2D.Double(0.0, 1.0)
            };
    
            double expected = 5.0 + 2.0/3.0;
            double actual = PolygonInertiaCalculator.inertia(poly);
    
            assertEquals(expected, actual, 1.0e-6);
    
            double ix = PolygonInertiaCalculator.ix(poly);
            double iy = PolygonInertiaCalculator.iy(poly);
            double ixy = PolygonInertiaCalculator.ixy(poly);
    
            assertEquals(ix, (1.0 + 1.0/3.0), 1.0e-6);
            assertEquals(iy, (21.0 + 1.0/3.0), 1.0e-6);
            assertEquals(ixy, 4.0, 1.0e-6);
        }
    }
    
        3
  •  0
  •   Community CDub    8 年前

    作为参考,这里有一个可变的2d org.gcs.kinetic.Vector 实现和更通用、不变 org.jscience.mathematics.vector 实施。本文就 Calculating a 2D Vector’s Cross Product 也很有帮助。

        4
  •  0
  •   Martijn Courteaux    14 年前

    我是用苔丝做的。把MOI的一切都拿在一起。