FluidInfo ILineFluidAffectable.GetFluidInfo(GetTangentCallback callback, Line line)
        {
            if (polygons.Length == 1)
            {
                return(ShapeHelper.GetFluidInfo(Vertexes, callback, line));
            }
            List <Vector2D[]> submerged = new List <Vector2D[]>(polygons.Length);

            for (int index = 0; index < polygons.Length; ++index)
            {
                Vector2D[] vertexes = VertexHelper.GetIntersection(polygons[index], line);
                if (vertexes.Length >= 3)
                {
                    submerged.Add(vertexes);
                }
            }
            if (submerged.Count == 0)
            {
                return(null);
            }
            Vector2D[][] newPolygons = submerged.ToArray();
            Vector2D     centroid    = VertexHelper.GetCentroidOfRange(newPolygons);
            Scalar       area        = VertexHelper.GetAreaOfRange(newPolygons);
            Vector2D     tangent     = callback(centroid);
            Vector2D     dragCenter;
            Scalar       dragArea;

            ShapeHelper.GetFluidInfo(newPolygons, tangent, out dragCenter, out dragArea);
            return(new FluidInfo(dragCenter, dragArea, centroid, area));
        }
        DragInfo IGlobalFluidAffectable.GetFluidInfo(Vector2D tangent)
        {
            Vector2D dragCenter;
            Scalar   dragArea;

            ShapeHelper.GetFluidInfo(polygons, tangent, out dragCenter, out dragArea);
            return(new DragInfo(dragCenter, dragArea));
        }
        DragInfo IGlobalFluidAffectable.GetFluidInfo(Vector2D tangent)
        {
            Scalar min, max;

            ShapeHelper.GetProjectedBounds(this.Vertexes, tangent, out min, out max);
            Scalar avg = (max + min) / 2;

            return(new DragInfo(tangent * avg, max - min));
        }
 /// <summary>
 /// Creates a new Circle Instance.
 /// </summary>
 /// <param name="radius">how large the circle is.</param>
 /// <param name="vertexCount">
 /// The number or vertex that will be generated along the perimeter of the circle.
 /// This is for collision detection.
 /// </param>
 /// <param name="momentOfInertiaMultiplier">
 /// How hard it is to turn the shape. Depending on the construtor in the
 /// Body this will be multiplied with the mass to determine the moment of inertia.
 /// </param>
 public CircleShape(Scalar radius, int vertexCount, Scalar momentOfInertiaMultiplier)
     : base(CreateCircle(radius, vertexCount), momentOfInertiaMultiplier)
 {
     if (radius <= 0)
     {
         throw new ArgumentOutOfRangeException("radius", "must be larger then zero");
     }
     this.radius  = radius;
     this.Normals = ShapeHelper.CalculateNormals(this.Vertexes);
 }
        private Vector2D[] CalculateNormals()
        {
            Vector2D[] result = new Vector2D[Vertexes.Length];
            int        offset = 0;

            for (int index = 0; index < polygons.Length; ++index)
            {
                Vector2D[] polygon = polygons[index];
                ShapeHelper.CalculateNormals(polygon, result, offset);
                offset += polygon.Length;
            }
            return(result);
        }
        public static void GetFluidInfo(Vector2D[][] polygons, Vector2D tangent, out Vector2D dragCenter, out Scalar dragArea)
        {
            Scalar min, max;
            Scalar avg;

            if (polygons.Length == 1)
            {
                ShapeHelper.GetProjectedBounds(
                    polygons[0],
                    tangent, out min, out max);
                avg        = (max + min) / 2;
                dragCenter = tangent * avg;
                dragArea   = max - min;
                return;
            }
            SAPNode[] sapNodes = new SAPNode[polygons.Length * 2];
            for (int index = 0; index < polygons.Length; ++index)
            {
                ShapeHelper.GetProjectedBounds(polygons[index], tangent, out min, out max);
                sapNodes[index * 2]       = new SAPNode(min, true);
                sapNodes[(index * 2) + 1] = new SAPNode(max, false);
            }
            Array.Sort <SAPNode>(sapNodes, comparer);
            int    depth  = 0;
            Scalar result = 0;
            Scalar start  = 0;

            for (int index = 0; index < sapNodes.Length; ++index)
            {
                SAPNode node = sapNodes[index];
                if (node.begin)
                {
                    if (depth == 0)
                    {
                        start = node.value;
                    }
                    depth++;
                }
                else
                {
                    depth--;
                    if (depth == 0)
                    {
                        result += node.value - start;
                    }
                }
            }
            avg        = (sapNodes[0].value + sapNodes[sapNodes.Length - 1].value) / 2;
            dragCenter = tangent * avg;
            dragArea   = result;
        }
 /// <summary>
 /// Creates a new Polygon Instance.
 /// </summary>
 /// <param name="vertexes">the vertexes that make up the shape of the Polygon</param>
 /// <param name="gridSpacing">
 /// How large a grid cell is. Usualy you will want at least 2 cells between major vertexes.
 /// The smaller this is the better precision you get, but higher cost in memory.
 /// The larger the less precision and if it's to high collision detection may fail completely.
 /// </param>
 /// <param name="momentOfInertiaMultiplier">
 /// How hard it is to turn the shape. Depending on the construtor in the
 /// Body this will be multiplied with the mass to determine the moment of inertia.
 /// </param>
 public PolygonShape(Vector2D[] vertexes, Scalar gridSpacing, Scalar momentOfInertiaMultiplier)
     : base(vertexes, momentOfInertiaMultiplier)
 {
     if (vertexes == null)
     {
         throw new ArgumentNullException("vertexes");
     }
     if (vertexes.Length < 3)
     {
         throw new ArgumentException("too few", "vertexes");
     }
     if (gridSpacing <= 0)
     {
         throw new ArgumentOutOfRangeException("gridSpacing");
     }
     this.Normals = ShapeHelper.CalculateNormals(this.Vertexes);
     this.grid    = new DistanceGrid(this, gridSpacing);
 }
        DragInfo IExplosionAffectable.GetExplosionInfo(Matrix2x3 matrix, Scalar radius, GetTangentCallback callback)
        {
            Vector2D[] vertexes2 = new Vector2D[Vertexes.Length];
            for (int index = 0; index < vertexes2.Length; ++index)
            {
                vertexes2[index] = matrix * Vertexes[index];
            }
            Vector2D[] inter = ShapeHelper.GetIntersection(vertexes2, radius);
            if (inter.Length < 3)
            {
                return(null);
            }
            Vector2D centroid = PolygonShape.GetCentroid(inter);
            Vector2D tangent = callback(centroid);
            Scalar   min, max;

            ShapeHelper.GetProjectedBounds(inter, tangent, out min, out max);
            Scalar avg = (max + min) / 2;

            return(new DragInfo(tangent * avg, max - min));
        }
        public static FluidInfo GetFluidInfo(Vector2D[] vertexes2, GetTangentCallback callback, Line line)
        {
            Vector2D centroid;
            Scalar   area;
            Vector2D dragCenter;
            Scalar   dragArea;

            Vector2D[] vertexes = ShapeHelper.GetIntersection(vertexes2, line);
            if (vertexes.Length < 3)
            {
                return(null);
            }
            centroid = PolygonShape.GetCentroid(vertexes);
            area     = PolygonShape.GetArea(vertexes);
            Vector2D tangent = callback(centroid);
            Scalar   min, max;

            ShapeHelper.GetProjectedBounds(vertexes, tangent, out min, out max);
            Scalar avg = (max + min) / 2;

            dragCenter = tangent * avg;
            dragArea   = max - min;
            return(new FluidInfo(dragCenter, dragArea, centroid, area));
        }
 FluidInfo ILineFluidAffectable.GetFluidInfo(GetTangentCallback callback, Line line)
 {
     return(ShapeHelper.GetFluidInfo(Vertexes, callback, line));
 }