Game physics 计算给定任意凸二维多边形的转动惯量

Game physics 计算给定任意凸二维多边形的转动惯量,game-physics,physics,Game Physics,Physics,我已经研究这个问题好几个小时了,由于某种原因,我没有找到解决办法 给定一个凸多边形,它被定义为围绕多边形质心按顺时针顺序排列的点,如何计算多边形的惯性矩 我已经能够找到各种形状的方程,比如矩形或圆形,但不能找到任意凸多边形的方程 例如,以质量m、高度h和宽度w围绕其质心旋转的矩形的惯性矩计算如下: 我正在寻找一个类似的公式/算法,但不是凸多边形。惯性矩的方程非常简单,你可以在这里找到解释: 例如,它被用来推导你引用的方程式 正如Andy Newman提到的,凸多边形可以被视为由三角形组成。但是

我已经研究这个问题好几个小时了,由于某种原因,我没有找到解决办法

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

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

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


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

惯性矩的方程非常简单,你可以在这里找到解释:

例如,它被用来推导你引用的方程式

正如Andy Newman提到的,凸多边形可以被视为由三角形组成。但是把它们各自的惯性加起来并不是一个解决办法——它不会产生一个考虑到旋转轴的有效方程

所以你需要做的基本上是推导一个关于你想要旋转它的旋转轴的多边形方程

根据您心目中的形状类型,您可能会发现以下定理之一很有用:


    • 我认为,有一种使用向量代数分析二维多边形的方法比依赖三角法的方法更易于编程实现

      每个
      向量
      数量有两个分量
      .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)
      
      下面的方法遍历多边形的所有边,并将由边和原点定义的每个三角形的坐标原点的面积、中心和质量惯性矩相加。最终总和负责添加或减去原点附近或远离原点的区域,产生准确的结果

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

      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));
      }
      
      在测试中,我使用了以下形状

      并且
      center=[1.0,0.75]
      mmoi=787.5
      的结果与CAD软件包中的分析结果相匹配

      以下是针对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);
      }
      

      找到将凸多边形细分为三角形的(许多)算法之一(图形需要经常这样做)。计算每个三角形的力矩。把它们全部加起来。为了澄清你想要的是用于动力学的质量惯性矩,而不是用于梁偏转的面积二阶矩?这能回答你的问题吗?
      [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);
      }