mirror of
https://github.com/AlexMacocian/MonoGame.Extended.git
synced 2026-07-15 15:09:29 +00:00
Add Points property to OrientedBoundingRectangle
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
@@ -45,6 +46,28 @@ namespace MonoGame.Extended
|
||||
Orientation = orientation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of points defining the corner points of the oriented rectangle.
|
||||
/// </summary>
|
||||
public IReadOnlyList<Vector2> Points
|
||||
{
|
||||
get
|
||||
{
|
||||
var topLeft = -Radii;
|
||||
var bottomLeft = -new Vector2(Radii.X, -Radii.Y);
|
||||
var topRight = (Vector2)new Point2(Radii.X, -Radii.Y);
|
||||
var bottomRight = Radii;
|
||||
|
||||
return new List<Vector2>
|
||||
{
|
||||
Vector2.Transform(topRight, Orientation) + Center,
|
||||
Vector2.Transform(topLeft, Orientation) + Center,
|
||||
Vector2.Transform(bottomLeft, Orientation) + Center,
|
||||
Vector2.Transform(bottomRight, Orientation) + Center
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the <see cref="OrientedBoundingRectangle"/> from the specified <paramref name="rectangle"/>
|
||||
/// transformed by <paramref name="transformMatrix"/>.
|
||||
@@ -62,7 +85,6 @@ namespace MonoGame.Extended
|
||||
{
|
||||
PrimitivesHelper.TransformOrientedBoundingRectangle(
|
||||
ref rectangle.Center,
|
||||
ref rectangle.Radii,
|
||||
ref rectangle.Orientation,
|
||||
ref transformMatrix);
|
||||
result.Center = rectangle.Center;
|
||||
@@ -127,6 +149,14 @@ namespace MonoGame.Extended
|
||||
return HashCode.Combine(Center, Radii, Orientation);
|
||||
}
|
||||
|
||||
public static explicit operator OrientedBoundingRectangle(RectangleF rectangle)
|
||||
{
|
||||
var radii = new Size2(rectangle.Width * 0.5f, rectangle.Height * 0.5f);
|
||||
var centre = new Point2(rectangle.X + radii.Width, rectangle.Y + radii.Height);
|
||||
|
||||
return new OrientedBoundingRectangle(centre, radii, Matrix2.Identity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="string" /> that represents this <see cref="OrientedBoundingRectangle" />.
|
||||
/// </summary>
|
||||
|
||||
@@ -74,17 +74,12 @@ namespace MonoGame.Extended
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static void TransformOrientedBoundingRectangle(
|
||||
ref Point2 center,
|
||||
ref Vector2 radii,
|
||||
ref Matrix2 orientation,
|
||||
ref Matrix2 transformMatrix)
|
||||
{
|
||||
// Real-Time Collision Detection, Christer Ericson, 2005. Chapter 4.4; Oriented Bounding Boxes (OBBs), pg 101-105.
|
||||
|
||||
center = transformMatrix.Transform(center);
|
||||
var xRadius = radii.X;
|
||||
var yRadius = radii.Y;
|
||||
radii.X = xRadius * Math.Abs(transformMatrix.M11) + yRadius * Math.Abs(transformMatrix.M12);
|
||||
radii.Y = xRadius * Math.Abs(transformMatrix.M21) + yRadius * Math.Abs(transformMatrix.M22);
|
||||
orientation *= transformMatrix;
|
||||
// Reset the translation since orientation is only about rotation
|
||||
orientation.M31 = 0;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace MonoGame.Extended.Tests;
|
||||
|
||||
public static class CollectionAssert
|
||||
{
|
||||
public static void Equal<T>(IReadOnlyList<T> expected, IReadOnlyList<T> actual)
|
||||
{
|
||||
Assert.True(expected.Count == actual.Count, "The number of items in the collections does not match.");
|
||||
|
||||
Assert.All(actual, x => Assert.Contains(x, expected));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Xunit;
|
||||
using Vector2 = Microsoft.Xna.Framework.Vector2;
|
||||
@@ -11,11 +10,20 @@ public class OrientedBoundingRectangleTests
|
||||
[Fact]
|
||||
public void Initializes_oriented_bounding_rectangle()
|
||||
{
|
||||
var rect = new OrientedBoundingRectangle(new Point2(1, 2), new Size2(3, 4), new Matrix2(5, 6, 7, 8, 9, 10));
|
||||
var rectangle = new OrientedBoundingRectangle(new Point2(1, 2), new Size2(3, 4), new Matrix2(5, 6, 7, 8, 9, 10));
|
||||
|
||||
Assert.Equal(new Point2(1, 2), rect.Center);
|
||||
Assert.Equal(new Vector2(3, 4), rect.Radii);
|
||||
Assert.Equal(new Matrix2(5, 6, 7, 8, 9, 10), rect.Orientation);
|
||||
Assert.Equal(new Point2(1, 2), rectangle.Center);
|
||||
Assert.Equal(new Vector2(3, 4), rectangle.Radii);
|
||||
Assert.Equal(new Matrix2(5, 6, 7, 8, 9, 10), rectangle.Orientation);
|
||||
CollectionAssert.Equal(
|
||||
new List<Vector2>
|
||||
{
|
||||
new(-3, -2),
|
||||
new(-33, -38),
|
||||
new(23, 26),
|
||||
new(53, 62)
|
||||
},
|
||||
rectangle.Points);
|
||||
}
|
||||
|
||||
public static readonly IEnumerable<object[]> _equalsComparisons = new[]
|
||||
@@ -49,7 +57,7 @@ public class OrientedBoundingRectangleTests
|
||||
[Fact]
|
||||
public void Center_point_is_not_translated()
|
||||
{
|
||||
var rectangle = new OrientedBoundingRectangle(new Point2(1, 2), new Size2(), new Matrix2());
|
||||
var rectangle = new OrientedBoundingRectangle(new Point2(1, 2), new Size2(), Matrix2.Identity);
|
||||
var transform = Matrix2.Identity;
|
||||
|
||||
var result = OrientedBoundingRectangle.Transform(rectangle, ref transform);
|
||||
@@ -91,7 +99,7 @@ public class OrientedBoundingRectangleTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rotate_45_degrees_left()
|
||||
public void Orientation_is_rotated_45_degrees_left()
|
||||
{
|
||||
var rectangle = new OrientedBoundingRectangle(new Point2(), new Size2(), Matrix2.Identity);
|
||||
var transform = Matrix2.CreateRotationZ(MathHelper.PiOver4);
|
||||
@@ -104,7 +112,7 @@ public class OrientedBoundingRectangleTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rotate_to_45_degrees_from_180()
|
||||
public void Orientation_is_rotated_to_45_degrees_from_180()
|
||||
{
|
||||
var rectangle = new OrientedBoundingRectangle(new Point2(), new Size2(), Matrix2.CreateRotationZ(MathHelper.Pi));
|
||||
var transform = Matrix2.CreateRotationZ(-3 * MathHelper.PiOver4);
|
||||
@@ -122,6 +130,44 @@ public class OrientedBoundingRectangleTests
|
||||
Assert.Equal(expectedOrientation.M32, result.Orientation.M32, 6);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Points_are_same_as_center()
|
||||
{
|
||||
var rectangle = new OrientedBoundingRectangle(new Point2(1, 2), new Size2(), Matrix2.Identity);
|
||||
var transform = Matrix2.Identity;
|
||||
|
||||
var result = OrientedBoundingRectangle.Transform(rectangle, ref transform);
|
||||
|
||||
CollectionAssert.Equal(
|
||||
new List<Vector2>
|
||||
{
|
||||
new(1, 2),
|
||||
new(1, 2),
|
||||
new(1, 2),
|
||||
new(1, 2)
|
||||
},
|
||||
result.Points);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Points_are_translated()
|
||||
{
|
||||
var rectangle = new OrientedBoundingRectangle(new Point2(0, 0), new Size2(2, 4), Matrix2.Identity);
|
||||
var transform = Matrix2.CreateTranslation(10, 20);
|
||||
|
||||
var result = OrientedBoundingRectangle.Transform(rectangle, ref transform);
|
||||
|
||||
CollectionAssert.Equal(
|
||||
new List<Vector2>
|
||||
{
|
||||
new(8, 16),
|
||||
new(8, 24),
|
||||
new(12, 24),
|
||||
new(12, 16)
|
||||
},
|
||||
result.Points);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Applies_rotation_and_translation()
|
||||
{
|
||||
@@ -169,11 +215,20 @@ public class OrientedBoundingRectangleTests
|
||||
|
||||
var result = OrientedBoundingRectangle.Transform(rectangle, ref transform);
|
||||
|
||||
Assert.Equal(-2 + 10, result.Center.X, 6);
|
||||
Assert.Equal(1 + 20, result.Center.Y, 6);
|
||||
Assert.Equal(4, result.Radii.X, 6);
|
||||
Assert.Equal(2, result.Radii.Y, 6);
|
||||
Assert.Equal(8, result.Center.X, 6);
|
||||
Assert.Equal(21, result.Center.Y, 6);
|
||||
Assert.Equal(2, result.Radii.X, 6);
|
||||
Assert.Equal(4, result.Radii.Y, 6);
|
||||
Assert.Equal(Matrix2.CreateRotationZ(MathHelper.PiOver2), result.Orientation);
|
||||
CollectionAssert.Equal(
|
||||
new List<Vector2>
|
||||
{
|
||||
new(4, 23),
|
||||
new(4, 19),
|
||||
new(12, 19),
|
||||
new(12, 23)
|
||||
},
|
||||
result.Points);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user