FarseerPhysics.Collision.Shapes.PolygonShape.computeProperties C# (CSharp) Метод

computeProperties() защищенный Метод

protected computeProperties ( ) : void
Результат void
		protected override void computeProperties()
		{
			// Polygon mass, centroid, and inertia.
			// Let rho be the polygon density in mass per unit area.
			// Then:
			// mass = rho * int(dA)
			// centroid.X = (1/mass) * rho * int(x * dA)
			// centroid.Y = (1/mass) * rho * int(y * dA)
			// I = rho * int((x*x + y*y) * dA)
			//
			// We can compute these integrals by summing all the integrals
			// for each triangle of the polygon. To evaluate the integral
			// for a single triangle, we make a change of variables to
			// the (u,v) coordinates of the triangle:
			// x = x0 + e1x * u + e2x * v
			// y = y0 + e1y * u + e2y * v
			// where 0 <= u && 0 <= v && u + v <= 1.
			//
			// We integrate u from [0,1-v] and then v from [0,1].
			// We also need to use the Jacobian of the transformation:
			// D = cross(e1, e2)
			//
			// Simplification: triangle centroid = (1/3) * (p1 + p2 + p3)
			//
			// The rest of the derivation is handled by computer algebra.

			Debug.Assert( vertices.Count >= 3 );

			//FPE optimization: Early exit as polygons with 0 density does not have any properties.
			if( _density <= 0 )
				return;

			//FPE optimization: Consolidated the calculate centroid and mass code to a single method.
			var center = Vector2.Zero;
			float area = 0.0f;
			float I = 0.0f;

			// pRef is the reference point for forming triangles.
			// It's location doesn't change the result (except for rounding error).
			var s = Vector2.Zero;

			// This code would put the reference point inside the polygon.
			for( int i = 0; i < vertices.Count; ++i )
			{
				s += vertices[i];
			}
			s *= 1.0f / vertices.Count;

			const float k_inv3 = 1.0f / 3.0f;

			for( int i = 0; i < vertices.Count; ++i )
			{
				// Triangle vertices.
				Vector2 e1 = vertices[i] - s;
				Vector2 e2 = i + 1 < vertices.Count ? vertices[i + 1] - s : vertices[0] - s;

				float D = MathUtils.cross( e1, e2 );

				float triangleArea = 0.5f * D;
				area += triangleArea;

				// Area weighted centroid
				center += triangleArea * k_inv3 * ( e1 + e2 );

				float ex1 = e1.X, ey1 = e1.Y;
				float ex2 = e2.X, ey2 = e2.Y;

				float intx2 = ex1 * ex1 + ex2 * ex1 + ex2 * ex2;
				float inty2 = ey1 * ey1 + ey2 * ey1 + ey2 * ey2;

				I += ( 0.25f * k_inv3 * D ) * ( intx2 + inty2 );
			}

			//The area is too small for the engine to handle.
			Debug.Assert( area > Settings.epsilon );

			// We save the area
			massData.area = area;

			// Total mass
			massData.mass = _density * area;

			// Center of mass
			center *= 1.0f / area;
			massData.centroid = center + s;

			// Inertia tensor relative to the local origin (point s).
			massData.inertia = _density * I;

			// Shift to center of mass then to original body origin.
			massData.inertia += massData.mass * ( Vector2.Dot( massData.centroid, massData.centroid ) - Vector2.Dot( center, center ) );
		}