Rectangle.Extensions.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using System;
  2. using Microsoft.Xna.Framework;
  3. namespace MonoGame.Extended;
  4. /// <summary>
  5. /// Provides extension methods for the <see cref="Rectangle"/> structure.
  6. /// </summary>
  7. public static class RectangleExtensions
  8. {
  9. /// <summary>
  10. /// Gets the corners of the rectangle in a clockwise direction starting at the top left.
  11. /// </summary>
  12. /// <param name="rectangle">The rectangle to get the corners of.</param>
  13. /// <returns>An array of <see cref="Point"/> elements representing the corners of the rectangle.</returns>
  14. public static Point[] GetCorners(this Rectangle rectangle)
  15. {
  16. var corners = new Point[4];
  17. corners[0] = new Point(rectangle.Left, rectangle.Top);
  18. corners[1] = new Point(rectangle.Right, rectangle.Top);
  19. corners[2] = new Point(rectangle.Right, rectangle.Bottom);
  20. corners[3] = new Point(rectangle.Left, rectangle.Bottom);
  21. return corners;
  22. }
  23. /// <summary>
  24. /// Converts the specified <see cref="Rectangle"/> to a <see cref="RectangleF"/>.
  25. /// </summary>
  26. /// <param name="rectangle">The rectangle to convert.</param>
  27. /// <returns>The converted <see cref="RectangleF"/>.</returns>
  28. public static RectangleF ToRectangleF(this Rectangle rectangle)
  29. {
  30. return new RectangleF(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
  31. }
  32. /// <summary>
  33. /// Clips the specified rectangle against the specified clipping rectangle.
  34. /// </summary>
  35. /// <param name="rectangle">The rectangle to clip.</param>
  36. /// <param name="clippingRectangle">The rectangle to clip against.</param>
  37. /// <returns>The clipped rectangle, or <see cref="Rectangle.Empty"/> if the rectangles do not intersect.</returns>
  38. public static Rectangle Clip(this Rectangle rectangle, Rectangle clippingRectangle)
  39. {
  40. int left = Math.Max(rectangle.Left, clippingRectangle.Left);
  41. int top = Math.Max(rectangle.Top, clippingRectangle.Top);
  42. int right = Math.Min(rectangle.Right, clippingRectangle.Right);
  43. int bottom = Math.Min(rectangle.Bottom, clippingRectangle.Bottom);
  44. int width = right - left;
  45. int height = bottom - top;
  46. if (width <= 0 || height <= 0)
  47. return Rectangle.Empty;
  48. return new Rectangle(left, top, width, height);
  49. }
  50. /// <summary>
  51. /// Gets a rectangle that is relative to the specified source rectangle, with the specified offsets and dimensions.
  52. /// </summary>
  53. /// <param name="source">The source rectangle.</param>
  54. /// <param name="x">The x-coordinate of the relative rectangle, relative to the source rectangle.</param>
  55. /// <param name="y">The y-coordinate of the relative rectangle, relative to the source rectangle.</param>
  56. /// <param name="width">The width, in pixels, of the relative rectangle.</param>
  57. /// <param name="height">The height, in pixels, of the relative rectangle.</param>
  58. /// <returns>The relative rectangle, clipped to the source rectangle.</returns>
  59. public static Rectangle GetRelativeRectangle(this Rectangle source, int x, int y, int width, int height)
  60. {
  61. int absoluteX = source.X + x;
  62. int absoluteY = source.Y + y;
  63. Rectangle relative;
  64. relative.X = (int)MathHelper.Clamp(absoluteX, source.Left, source.Right);
  65. relative.Y = (int)MathHelper.Clamp(absoluteY, source.Top, source.Bottom);
  66. relative.Width = Math.Max(Math.Min(absoluteX + width, source.Right) - relative.X, 0);
  67. relative.Height = Math.Max(Math.Min(absoluteY + height, source.Bottom) - relative.Y, 0);
  68. return relative;
  69. }
  70. #if FNA
  71. // MomoGame compatibility layer
  72. /// <summary>
  73. /// Deconstruction method for Rectangle.
  74. /// </summary>
  75. public static void Deconstruct(this Rectangle rectangle, out int x, out int y, out int width, out int height)
  76. {
  77. x = rectangle.X;
  78. y = rectangle.Y;
  79. width = rectangle.Width;
  80. height = rectangle.Height;
  81. }
  82. #endif
  83. /// <summary>
  84. /// Normalizes the specified <see cref="Rectangle"/> so that the <see cref="Rectangle.Width"/> and
  85. /// <see cref="Rectangle.Height"/> are positive without changing the location of the rectangle.
  86. /// </summary>
  87. /// <param name="rectangle">The <see cref="Rectangle"/> to normalize.</param>
  88. /// <returns>A <see cref="Rectangle"/> with positive width and height.</returns>
  89. public static Rectangle Normalize(Rectangle rectangle)
  90. {
  91. if (rectangle.Width < 0)
  92. {
  93. rectangle.X += rectangle.Width;
  94. rectangle.Width = -rectangle.Width;
  95. }
  96. if (rectangle.Height < 0)
  97. {
  98. rectangle.Y += rectangle.Height;
  99. rectangle.Height = -rectangle.Height;
  100. }
  101. return rectangle;
  102. }
  103. /// <summary>
  104. /// Normalizes a <see cref="Rectangle"/> so that the <see cref="Rectangle.Width"/> and
  105. /// <see cref="Rectangle.Height"/> are positive without changing the location of the rectangle.
  106. /// </summary>
  107. /// <param name="rectangle">The source <see cref="Rectangle"/>.</param>
  108. /// <param name="result">
  109. /// When this method returns, contains the a normalized <see cref="Rectangle"/> with positive width and height.
  110. /// </param>
  111. public static void Normalize(ref this Rectangle rectangle, out Rectangle result)
  112. {
  113. result.X = rectangle.X;
  114. result.Width = rectangle.Width;
  115. if (result.Width < 0)
  116. {
  117. result.X += result.Width;
  118. result.Width = -result.Width;
  119. }
  120. result.Y = rectangle.Y;
  121. result.Height = rectangle.Height;
  122. if (result.Height < 0)
  123. {
  124. result.Y += result.Height;
  125. result.Height = -result.Height;
  126. }
  127. }
  128. }