我已经花了几个小时研究这个问题,但不知何故,我找不到解决方案。
给定一个凸多边形,该多边形以顺时针顺序围绕多边形的质心定义为点数组,如何计算多边形的惯性矩?
我已经能够找到各种形状的公式,例如矩形或圆形,但没有针对任意凸多边形的公式。
例如,质量为m,高度为h,宽度为w的矩形绕其质心旋转的惯性矩可计算为:
我正在寻找一个类似的公式/算法,但适用于凸多边形。
我已经花了几个小时研究这个问题,但不知何故,我找不到解决方案。
给定一个凸多边形,该多边形以顺时针顺序围绕多边形的质心定义为点数组,如何计算多边形的惯性矩?
我已经能够找到各种形状的公式,例如矩形或圆形,但没有针对任意凸多边形的公式。
例如,质量为m,高度为h,宽度为w的矩形绕其质心旋转的惯性矩可计算为:
我正在寻找一个类似的公式/算法,但适用于凸多边形。
我认为使用矢量代数分析2D多边形的方法比依赖三角学的方法更容易在程序中实现。
每个向量
量都有两个分量.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));
}
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);
}
在测试中,我使用了以下形状:
并且当 center = [1.0, 0.75]
和 mmoi = 687.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);
}
step_area
是否为零。如果是,则继续下一次迭代。否则,如果零面积元素是要考虑的第一个元素(且 area=0
),则会除以零。 - John Alexiou惯性矩的公式相当简单,您可以在此处找到解释:https://en.wikipedia.org/wiki/Moment_of_inertia
例如,它被用于推导您引用的方程式。
正如安迪·纽曼提到的那样,凸多边形可以被认为是由三角形组成。 但是将它们各自的惯性累加起来并不是一个解决方案——它不会产生考虑旋转轴的有效方程式。
所以基本上你需要做的就是针对你想要绕其旋转的旋转轴得出多边形的方程式。
根据您所考虑的形状类型,您可能会发现以下定理之一有用: