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

PolygonTools.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using FarseerPhysics.Common.TextureTools;
using Microsoft.Xna.Framework;

namespace FarseerPhysics.Common
{
    public static clast PolygonTools
    {
        /// 
        /// Build vertices to represent an axis-aligned box.
        /// 
        /// the half-width.
        /// the half-height.
        public static Vertices CreateRectangle(float hx, float hy)
        {
            Vertices vertices = new Vertices(4);
            vertices.Add(new Vector2(-hx, -hy));
            vertices.Add(new Vector2(hx, -hy));
            vertices.Add(new Vector2(hx, hy));
            vertices.Add(new Vector2(-hx, hy));

            return vertices;
        }

        /// 
        /// Build vertices to represent an oriented box.
        /// 
        /// the half-width.
        /// the half-height.
        /// the center of the box in local coordinates.
        /// the rotation of the box in local coordinates.
        public static Vertices CreateRectangle(float hx, float hy, Vector2 center, float angle)
        {
            Vertices vertices = CreateRectangle(hx, hy);

            Transform xf = new Transform();
            xf.p = center;
            xf.q.Set(angle);

            // Transform vertices
            for (int i = 0; i < 4; ++i)
            {
                vertices[i] = MathUtils.Mul(ref xf, vertices[i]);
            }

            return vertices;
        }

        //Rounded rectangle contributed by Jonathan Smars - [email protected]

        /// 
        /// Creates a rounded rectangle with the specified width and height.
        /// 
        /// The width.
        /// The height.
        /// The rounding X radius.
        /// The rounding Y radius.
        /// The number of segments to subdivide the edges.
        /// 
        public static Vertices CreateRoundedRectangle(float width, float height, float xRadius, float yRadius,
                                                      int segments)
        {
            if (yRadius > height / 2 || xRadius > width / 2)
                throw new Exception("Rounding amount can't be more than half the height and width respectively.");
            if (segments < 0)
                throw new Exception("Segments must be zero or more.");

            //We need at least 8 vertices to create a rounded rectangle
            Debug.astert(Settings.MaxPolygonVertices >= 8);

            Vertices vertices = new Vertices();
            if (segments == 0)
            {
                vertices.Add(new Vector2(width * .5f - xRadius, -height * .5f));
                vertices.Add(new Vector2(width * .5f, -height * .5f + yRadius));

                vertices.Add(new Vector2(width * .5f, height * .5f - yRadius));
                vertices.Add(new Vector2(width * .5f - xRadius, height * .5f));

                vertices.Add(new Vector2(-width * .5f + xRadius, height * .5f));
                vertices.Add(new Vector2(-width * .5f, height * .5f - yRadius));

                vertices.Add(new Vector2(-width * .5f, -height * .5f + yRadius));
                vertices.Add(new Vector2(-width * .5f + xRadius, -height * .5f));
            }
            else
            {
                int numberOfEdges = (segments * 4 + 8);

                float stepSize = MathHelper.TwoPi / (numberOfEdges - 4);
                int perPhase = numberOfEdges / 4;

                Vector2 posOffset = new Vector2(width / 2 - xRadius, height / 2 - yRadius);
                vertices.Add(posOffset + new Vector2(xRadius, -yRadius + yRadius));
                short phase = 0;
                for (int i = 1; i < numberOfEdges; i++)
                {
                    if (i - perPhase == 0 || i - perPhase * 3 == 0)
                    {
                        posOffset.X *= -1;
                        phase--;
                    }
                    else if (i - perPhase * 2 == 0)
                    {
                        posOffset.Y *= -1;
                        phase--;
                    }

                    vertices.Add(posOffset + new Vector2(xRadius * (float)Math.Cos(stepSize * -(i + phase)),
                                                         -yRadius * (float)Math.Sin(stepSize * -(i + phase))));
                }
            }

            return vertices;
        }

        /// 
        /// Set this as a single edge.
        /// 
        /// The first point.
        /// The second point.
        public static Vertices CreateLine(Vector2 start, Vector2 end)
        {
            Vertices vertices = new Vertices(2);
            vertices.Add(start);
            vertices.Add(end);

            return vertices;
        }

        /// 
        /// Creates a circle with the specified radius and number of edges.
        /// 
        /// The radius.
        /// The number of edges. The more edges, the more it resembles a circle
        /// 
        public static Vertices CreateCircle(float radius, int numberOfEdges)
        {
            return CreateEllipse(radius, radius, numberOfEdges);
        }

        /// 
        /// Creates a ellipse with the specified width, height and number of edges.
        /// 
        /// Width of the ellipse.
        /// Height of the ellipse.
        /// The number of edges. The more edges, the more it resembles an ellipse
        /// 
        public static Vertices CreateEllipse(float xRadius, float yRadius, int numberOfEdges)
        {
            Vertices vertices = new Vertices();

            float stepSize = MathHelper.TwoPi / numberOfEdges;

            vertices.Add(new Vector2(xRadius, 0));
            for (int i = numberOfEdges - 1; i > 0; --i)
                vertices.Add(new Vector2(xRadius * (float)Math.Cos(stepSize * i),
                                         -yRadius * (float)Math.Sin(stepSize * i)));

            return vertices;
        }

        public static Vertices CreateArc(float radians, int sides, float radius)
        {
            Debug.astert(radians > 0, "The arc needs to be larger than 0");
            Debug.astert(sides > 1, "The arc needs to have more than 1 sides");
            Debug.astert(radius > 0, "The arc needs to have a radius larger than 0");

            Vertices vertices = new Vertices();

            float stepSize = radians / sides;
            for (int i = sides - 1; i > 0; i--)
            {
                vertices.Add(new Vector2(radius * (float)Math.Cos(stepSize * i),
                                         radius * (float)Math.Sin(stepSize * i)));
            }

            return vertices;
        }

        //Capsule contributed by Yobiv

        /// 
        /// Creates an capsule with the specified height, radius and number of edges.
        /// A capsule has the same form as a pill capsule.
        /// 
        /// Height (inner height + 2 * radius) of the capsule.
        /// Radius of the capsule ends.
        /// The number of edges of the capsule ends. The more edges, the more it resembles an capsule
        /// 
        public static Vertices CreateCapsule(float height, float endRadius, int edges)
        {
            if (endRadius >= height / 2)
                throw new ArgumentException(
                    "The radius must be lower than height / 2. Higher values of radius would create a circle, and not a half circle.",
                    "endRadius");

            return CreateCapsule(height, endRadius, edges, endRadius, edges);
        }

        /// 
        /// Creates an capsule with the specified  height, radius and number of edges.
        /// A capsule has the same form as a pill capsule.
        /// 
        /// Height (inner height + radii) of the capsule.
        /// Radius of the top.
        /// The number of edges of the top. The more edges, the more it resembles an capsule
        /// Radius of bottom.
        /// The number of edges of the bottom. The more edges, the more it resembles an capsule
        /// 
        public static Vertices CreateCapsule(float height, float topRadius, int topEdges, float bottomRadius,
                                             int bottomEdges)
        {
            if (height