Common
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