csharp/Alan-FGR/aelum/Farseer/Farseer%20Physics%20Engine%203.5/Common/PathManager.cs

PathManager.cs
using System;
using System.Collections.Generic;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Common.Decomposition;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;

namespace FarseerPhysics.Common
{
    /// 
    /// An easy to use manager for creating paths.
    /// 
    public static clast PathManager
    {
        #region LinkType enum

        public enum LinkType
        {
            Revolute,
            Slider
        }

        #endregion

        //Contributed by Matthew Bettcher

        /// 
        /// Convert a path into a set of edges and attaches them to the specified body.
        /// Note: use only for static edges.
        /// 
        /// The path.
        /// The body.
        /// The subdivisions.
        public static void ConvertPathToEdges(Path path, Body body, int subdivisions)
        {
            Vertices verts = path.GetVertices(subdivisions);

            if (path.Closed)
            {
                ChainShape chain = new ChainShape(verts, true);
                body.CreateFixture(chain);
            }
            else
            {
                for (int i = 1; i < verts.Count; i++)
                {
                    body.CreateFixture(new EdgeShape(verts[i], verts[i - 1]));
                }
            }
        }

        /// 
        /// Convert a closed path into a polygon.
        /// Convex decomposition is automatically performed.
        /// 
        /// The path.
        /// The body.
        /// The density.
        /// The subdivisions.
        public static void ConvertPathToPolygon(Path path, Body body, float density, int subdivisions)
        {
            if (!path.Closed)
                throw new Exception("The path must be closed to convert to a polygon.");

            List verts = path.GetVertices(subdivisions);

            List decomposedVerts = Triangulate.ConvexParsation(new Vertices(verts), TriangulationAlgorithm.Bayazit);

            foreach (Vertices item in decomposedVerts)
            {
                body.CreateFixture(new PolygonShape(item, density));
            }
        }

        /// 
        /// Duplicates the given Body along the given path for approximatly the given copies.
        /// 
        /// The world.
        /// The path.
        /// The shapes.
        /// The type.
        /// The copies.
        /// 
        /// 
        public static List EvenlyDistributeShapesAlongPath(World world, Path path, IEnumerable shapes, BodyType type, int copies, object userData = null)
        {
            List centers = path.SubdivideEvenly(copies);
            List bodyList = new List();

            for (int i = 0; i < centers.Count; i++)
            {
                Body b = new Body(world);

                // copy the type from original body
                b.BodyType = type;
                b.Position = new Vector2(centers[i].X, centers[i].Y);
                b.Rotation = centers[i].Z;
                b.UserData = userData;

                foreach (Shape shape in shapes)
                {
                    b.CreateFixture(shape);
                }

                bodyList.Add(b);
            }

            return bodyList;
        }


        /// 
        /// Duplicates the given Body along the given path for approximatly the given copies.
        /// 
        /// The world.
        /// The path.
        /// The shape.
        /// The type.
        /// The copies.
        /// The user data.
        /// 
        public static List EvenlyDistributeShapesAlongPath(World world, Path path, Shape shape, BodyType type,
                                                                 int copies, object userData)
        {
            List shapes = new List(1);
            shapes.Add(shape);

            return EvenlyDistributeShapesAlongPath(world, path, shapes, type, copies, userData);
        }

        public static List EvenlyDistributeShapesAlongPath(World world, Path path, Shape shape, BodyType type, int copies)
        {
            return EvenlyDistributeShapesAlongPath(world, path, shape, type, copies, null);
        }

        /// 
        /// Moves the given body along the defined path.
        /// 
        /// The path.
        /// The body.
        /// The time.
        /// The strength.
        /// The time step.
        public static void MoveBodyOnPath(Path path, Body body, float time, float strength, float timeStep)
        {
            Vector2 destination = path.GetPosition(time);
            Vector2 positionDelta = body.Position - destination;
            Vector2 velocity = (positionDelta / timeStep) * strength;

            body.LinearVelocity = -velocity;
        }

        /// 
        /// Attaches the bodies with revolute joints.
        /// 
        /// The world.
        /// The bodies.
        /// The local anchor A.
        /// The local anchor B.
        /// if set to true [connect first and last].
        /// if set to true [collide connected].
        public static List AttachBodiesWithRevoluteJoint(World world, List bodies, Vector2 localAnchorA, Vector2 localAnchorB, bool connectFirstAndLast, bool collideConnected)
        {
            List joints = new List(bodies.Count + 1);

            for (int i = 1; i < bodies.Count; i++)
            {
                RevoluteJoint joint = new RevoluteJoint(bodies[i], bodies[i - 1], localAnchorA, localAnchorB);
                joint.CollideConnected = collideConnected;
                world.AddJoint(joint);
                joints.Add(joint);
            }

            if (connectFirstAndLast)
            {
                RevoluteJoint lastjoint = new RevoluteJoint(bodies[0], bodies[bodies.Count - 1], localAnchorA, localAnchorB);
                lastjoint.CollideConnected = collideConnected;
                world.AddJoint(lastjoint);
                joints.Add(lastjoint);
            }

            return joints;
        }
    }
}