ShapeF.cs 4.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. using System;
  2. using Microsoft.Xna.Framework;
  3. namespace MonoGame.Extended
  4. {
  5. /// <summary>
  6. /// Base class for shapes.
  7. /// </summary>
  8. /// <remakarks>
  9. /// Created to allow checking intersection between shapes of different types.
  10. /// </remakarks>
  11. public interface IShapeF
  12. {
  13. /// <summary>
  14. /// Gets or sets the position of the shape.
  15. /// </summary>
  16. Vector2 Position { get; set; }
  17. /// <summary>
  18. /// Gets escribed rectangle, which lying outside the shape
  19. /// </summary>
  20. RectangleF BoundingRectangle { get; }
  21. }
  22. /// <summary>
  23. /// Class that implements methods for shared <see cref="IShapeF" /> methods.
  24. /// </summary>
  25. public static class Shape
  26. {
  27. /// <summary>
  28. /// Check if two shapes intersect.
  29. /// </summary>
  30. /// <param name="a">The first shape.</param>
  31. /// <param name="b">The second shape.</param>
  32. /// <returns>True if the two shapes intersect.</returns>
  33. public static bool Intersects(this IShapeF a, IShapeF b)
  34. {
  35. return a switch
  36. {
  37. CircleF circleA when b is CircleF circleB => circleA.Intersects(circleB),
  38. CircleF circleA when b is RectangleF rectangleB => circleA.Intersects(rectangleB),
  39. CircleF circleA when b is OrientedRectangle orientedRectangleB => Intersects(circleA, orientedRectangleB),
  40. RectangleF rectangleA when b is CircleF circleB => Intersects(circleB, rectangleA),
  41. RectangleF rectangleA when b is RectangleF rectangleB => rectangleA.Intersects(rectangleB),
  42. RectangleF rectangleA when b is OrientedRectangle orientedRectangleB => Intersects(rectangleA, orientedRectangleB).Intersects,
  43. OrientedRectangle orientedRectangleA when b is CircleF circleB => Intersects(circleB, orientedRectangleA),
  44. OrientedRectangle orientedRectangleA when b is RectangleF rectangleB => Intersects(rectangleB, orientedRectangleA).Intersects,
  45. OrientedRectangle orientedRectangleA when b is OrientedRectangle orientedRectangleB
  46. => OrientedRectangle.Intersects(orientedRectangleA, orientedRectangleB).Intersects,
  47. _ => throw new ArgumentOutOfRangeException(nameof(a))
  48. };
  49. }
  50. /// <summary>
  51. /// Checks if a circle and rectangle intersect.
  52. /// </summary>
  53. /// <param name="circle">Circle to check intersection with rectangle.</param>
  54. /// <param name="rectangle">Rectangle to check intersection with circle.</param>
  55. /// <returns>True if the circle and rectangle intersect.</returns>
  56. public static bool Intersects(CircleF circle, RectangleF rectangle)
  57. {
  58. var closestPoint = rectangle.ClosestPointTo(circle.Center);
  59. return circle.Contains(closestPoint);
  60. }
  61. /// <summary>
  62. /// Checks whether a <see cref="CircleF"/> and <see cref="OrientedRectangle"/> intersects.
  63. /// </summary>
  64. /// <param name="circle"><see cref="CircleF"/>to use in intersection test.</param>
  65. /// <param name="orientedRectangle"><see cref="OrientedRectangle"/>to use in intersection test.</param>
  66. /// <returns>True if the circle and oriented bounded rectangle intersects, otherwise false.</returns>
  67. public static bool Intersects(CircleF circle, OrientedRectangle orientedRectangle)
  68. {
  69. var rotation = Matrix3x2.CreateRotationZ(orientedRectangle.Orientation.Rotation);
  70. var circleCenterInRectangleSpace = rotation.Transform(circle.Center - orientedRectangle.Center);
  71. var circleInRectangleSpace = new CircleF(circleCenterInRectangleSpace, circle.Radius);
  72. var boundingRectangle = new BoundingRectangle(new Vector2(), orientedRectangle.Radii);
  73. return circleInRectangleSpace.Intersects(boundingRectangle);
  74. }
  75. /// <summary>
  76. /// Checks if a <see cref="RectangleF"/> and <see cref="OrientedRectangle"/> intersects.
  77. /// </summary>
  78. /// <param name="rectangleF"></param>
  79. /// <param name="orientedRectangle"></param>
  80. /// <returns>True if objects are intersecting, otherwise false.</returns>
  81. public static (bool Intersects, Vector2 MinimumTranslationVector) Intersects(RectangleF rectangleF, OrientedRectangle orientedRectangle)
  82. {
  83. return OrientedRectangle.Intersects(orientedRectangle, (OrientedRectangle)rectangleF);
  84. }
  85. }
  86. }