RectangleF.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Runtime.Serialization;
  5. using Microsoft.Xna.Framework;
  6. namespace MonoGame.Extended
  7. {
  8. // Real-Time Collision Detection, Christer Ericson, 2005. Chapter 4.2; Bounding Volumes - Axis-aligned Bounding Boxes (AABBs). pg 77
  9. /// <summary>
  10. /// An axis-aligned, four sided, two dimensional box defined by a top-left position (<see cref="X" /> and
  11. /// <see cref="Y" />) and a size (<see cref="Width" /> and <see cref="Height" />).
  12. /// </summary>
  13. /// <remarks>
  14. /// <para>
  15. /// An <see cref="RectangleF" /> is categorized by having its faces oriented in such a way that its
  16. /// face normals are at all times parallel with the axes of the given coordinate system.
  17. /// </para>
  18. /// <para>
  19. /// The bounding <see cref="RectangleF" /> of a rotated <see cref="RectangleF" /> will be equivalent or larger
  20. /// in size than the original depending on the angle of rotation.
  21. /// </para>
  22. /// </remarks>
  23. /// <seealso cref="IEquatable{T}" />
  24. /// <seealso cref="IEquatableByRef{T}" />
  25. [DataContract]
  26. [DebuggerDisplay("{DebugDisplayString,nq}")]
  27. public struct RectangleF : IEquatable<RectangleF>, IEquatableByRef<RectangleF>, IShapeF
  28. {
  29. /// <summary>
  30. /// The <see cref="RectangleF" /> with <see cref="X" />, <see cref="Y" />, <see cref="Width" /> and
  31. /// <see cref="Height" /> all set to <code>0.0f</code>.
  32. /// </summary>
  33. public static readonly RectangleF Empty = new RectangleF();
  34. /// <summary>
  35. /// The x-coordinate of the top-left corner position of this <see cref="RectangleF" />.
  36. /// </summary>
  37. [DataMember] public float X;
  38. /// <summary>
  39. /// The y-coordinate of the top-left corner position of this <see cref="RectangleF" />.
  40. /// </summary>
  41. [DataMember] public float Y;
  42. /// <summary>
  43. /// The width of this <see cref="RectangleF" />.
  44. /// </summary>
  45. [DataMember] public float Width;
  46. /// <summary>
  47. /// The height of this <see cref="RectangleF" />.
  48. /// </summary>
  49. [DataMember] public float Height;
  50. /// <summary>
  51. /// Gets the x-coordinate of the left edge of this <see cref="RectangleF" />.
  52. /// </summary>
  53. public float Left => X;
  54. /// <summary>
  55. /// Gets the x-coordinate of the right edge of this <see cref="RectangleF" />.
  56. /// </summary>
  57. public float Right => X + Width;
  58. /// <summary>
  59. /// Gets the y-coordinate of the top edge of this <see cref="RectangleF" />.
  60. /// </summary>
  61. public float Top => Y;
  62. /// <summary>
  63. /// Gets the y-coordinate of the bottom edge of this <see cref="RectangleF" />.
  64. /// </summary>
  65. public float Bottom => Y + Height;
  66. /// <summary>
  67. /// Gets a value indicating whether this <see cref="RectangleF" /> has a <see cref="X" />, <see cref="Y" />,
  68. /// <see cref="Width" />,
  69. /// <see cref="Height" /> all equal to <code>0.0f</code>.
  70. /// </summary>
  71. /// <value>
  72. /// <c>true</c> if this instance is empty; otherwise, <c>false</c>.
  73. /// </value>
  74. public bool IsEmpty => Width.Equals(0) && Height.Equals(0) && X.Equals(0) && Y.Equals(0);
  75. /// <summary>
  76. /// Gets the <see cref="Vector2" /> representing the the top-left of this <see cref="RectangleF" />.
  77. /// </summary>
  78. public Vector2 Position
  79. {
  80. get { return new Vector2(X, Y); }
  81. set
  82. {
  83. X = value.X;
  84. Y = value.Y;
  85. }
  86. }
  87. public RectangleF BoundingRectangle => this;
  88. /// <summary>
  89. /// Gets the <see cref="SizeF" /> representing the extents of this <see cref="RectangleF" />.
  90. /// </summary>
  91. public SizeF Size
  92. {
  93. get { return new SizeF(Width, Height); }
  94. set
  95. {
  96. Width = value.Width;
  97. Height = value.Height;
  98. }
  99. }
  100. /// <summary>
  101. /// Gets the <see cref="Vector2" /> representing the center of this <see cref="RectangleF" />.
  102. /// </summary>
  103. public Vector2 Center => new Vector2(X + Width * 0.5f, Y + Height * 0.5f);
  104. /// <summary>
  105. /// Gets the <see cref="Vector2" /> representing the top-left of this <see cref="RectangleF" />.
  106. /// </summary>
  107. public Vector2 TopLeft => new Vector2(X, Y);
  108. /// <summary>
  109. /// Gets the <see cref="Vector2" /> representing the top-right of this <see cref="RectangleF" />.
  110. /// </summary>
  111. public Vector2 TopRight => new Vector2(X + Width, Y);
  112. /// <summary>
  113. /// Gets the <see cref="Vector2" /> representing the bottom-left of this <see cref="RectangleF" />.
  114. /// </summary>
  115. public Vector2 BottomLeft => new Vector2(X, Y + Height);
  116. /// <summary>
  117. /// Gets the <see cref="Vector2" /> representing the bottom-right of this <see cref="RectangleF" />.
  118. /// </summary>
  119. public Vector2 BottomRight => new Vector2(X + Width, Y + Height);
  120. /// <summary>
  121. /// Initializes a new instance of the <see cref="RectangleF" /> structure from the specified top-left xy-coordinate
  122. /// <see cref="float" />s, width <see cref="float" /> and height <see cref="float" />.
  123. /// </summary>
  124. /// <param name="x">The x-coordinate.</param>
  125. /// <param name="y">The y-coordinate.</param>
  126. /// <param name="width">The width.</param>
  127. /// <param name="height">The height.</param>
  128. public RectangleF(float x, float y, float width, float height)
  129. {
  130. X = x;
  131. Y = y;
  132. Width = width;
  133. Height = height;
  134. }
  135. /// <summary>
  136. /// Initializes a new instance of the <see cref="RectangleF" /> structure from the specified top-left
  137. /// <see cref="Vector2" /> and the extents <see cref="SizeF" />.
  138. /// </summary>
  139. /// <param name="position">The top-left point.</param>
  140. /// <param name="size">The extents.</param>
  141. public RectangleF(Vector2 position, SizeF size)
  142. {
  143. X = position.X;
  144. Y = position.Y;
  145. Width = size.Width;
  146. Height = size.Height;
  147. }
  148. /// <summary>
  149. /// Computes the <see cref="RectangleF" /> from a minimum <see cref="Vector2" /> and maximum
  150. /// <see cref="Vector2" />.
  151. /// </summary>
  152. /// <param name="minimum">The minimum point.</param>
  153. /// <param name="maximum">The maximum point.</param>
  154. /// <param name="result">The resulting rectangle.</param>
  155. public static void CreateFrom(Vector2 minimum, Vector2 maximum, out RectangleF result)
  156. {
  157. result.X = minimum.X;
  158. result.Y = minimum.Y;
  159. result.Width = maximum.X - minimum.X;
  160. result.Height = maximum.Y - minimum.Y;
  161. }
  162. /// <summary>
  163. /// Computes the <see cref="RectangleF" /> from a minimum <see cref="Vector2" /> and maximum
  164. /// <see cref="Vector2" />.
  165. /// </summary>
  166. /// <param name="minimum">The minimum point.</param>
  167. /// <param name="maximum">The maximum point.</param>
  168. /// <returns>The resulting <see cref="RectangleF" />.</returns>
  169. public static RectangleF CreateFrom(Vector2 minimum, Vector2 maximum)
  170. {
  171. RectangleF result;
  172. CreateFrom(minimum, maximum, out result);
  173. return result;
  174. }
  175. /// <summary>
  176. /// Computes the <see cref="RectangleF" /> from a list of <see cref="Vector2" /> structures.
  177. /// </summary>
  178. /// <param name="points">The points.</param>
  179. /// <param name="result">The resulting rectangle.</param>
  180. public static void CreateFrom(IReadOnlyList<Vector2> points, out RectangleF result)
  181. {
  182. Vector2 minimum;
  183. Vector2 maximum;
  184. PrimitivesHelper.CreateRectangleFromPoints(points, out minimum, out maximum);
  185. CreateFrom(minimum, maximum, out result);
  186. }
  187. /// <summary>
  188. /// Computes the <see cref="RectangleF" /> from a list of <see cref="Vector2" /> structures.
  189. /// </summary>
  190. /// <param name="points">The points.</param>
  191. /// <returns>The resulting <see cref="RectangleF" />.</returns>
  192. public static RectangleF CreateFrom(IReadOnlyList<Vector2> points)
  193. {
  194. RectangleF result;
  195. CreateFrom(points, out result);
  196. return result;
  197. }
  198. /// <summary>
  199. /// Computes the <see cref="RectangleF" /> from the specified <see cref="RectangleF" /> transformed by
  200. /// the specified <see cref="Matrix3x2" />.
  201. /// </summary>
  202. /// <param name="rectangle">The rectangle to be transformed.</param>
  203. /// <param name="transformMatrix">The transform matrix.</param>
  204. /// <param name="result">The resulting transformed rectangle.</param>
  205. /// <returns>
  206. /// The <see cref="Extended.BoundingRectangle" /> from the <paramref name="rectangle" /> transformed by the
  207. /// <paramref name="transformMatrix" />.
  208. /// </returns>
  209. /// <remarks>
  210. /// <para>
  211. /// If a transformed <see cref="Extended.BoundingRectangle" /> is used for <paramref name="rectangle" /> then the
  212. /// resulting <see cref="Extended.BoundingRectangle" /> will have the compounded transformation, which most likely is
  213. /// not desired.
  214. /// </para>
  215. /// </remarks>
  216. public static void Transform(ref RectangleF rectangle,
  217. ref Matrix3x2 transformMatrix, out RectangleF result)
  218. {
  219. var center = rectangle.Center;
  220. var halfExtents = (Vector2)rectangle.Size * 0.5f;
  221. PrimitivesHelper.TransformRectangle(ref center, ref halfExtents, ref transformMatrix);
  222. result.X = center.X - halfExtents.X;
  223. result.Y = center.Y - halfExtents.Y;
  224. result.Width = halfExtents.X * 2;
  225. result.Height = halfExtents.Y * 2;
  226. }
  227. /// <summary>
  228. /// Computes the <see cref="RectangleF" /> from the specified <see cref="Extended.BoundingRectangle" /> transformed by
  229. /// the
  230. /// specified <see cref="Matrix3x2" />.
  231. /// </summary>
  232. /// <param name="rectangle">The bounding rectangle.</param>
  233. /// <param name="transformMatrix">The transform matrix.</param>
  234. /// <returns>
  235. /// The <see cref="Extended.BoundingRectangle" /> from the <paramref name="rectangle" /> transformed by the
  236. /// <paramref name="transformMatrix" />.
  237. /// </returns>
  238. /// <remarks>
  239. /// <para>
  240. /// If a transformed <see cref="Extended.BoundingRectangle" /> is used for <paramref name="rectangle" /> then the
  241. /// resulting <see cref="Extended.BoundingRectangle" /> will have the compounded transformation, which most likely is
  242. /// not desired.
  243. /// </para>
  244. /// </remarks>
  245. public static RectangleF Transform(RectangleF rectangle, ref Matrix3x2 transformMatrix)
  246. {
  247. RectangleF result;
  248. Transform(ref rectangle, ref transformMatrix, out result);
  249. return result;
  250. }
  251. /// <summary>
  252. /// Computes the <see cref="RectangleF" /> that contains the two specified
  253. /// <see cref="RectangleF" /> structures.
  254. /// </summary>
  255. /// <param name="first">The first rectangle.</param>
  256. /// <param name="second">The second rectangle.</param>
  257. /// <param name="result">The resulting rectangle that contains both the <paramref name="first" /> and the
  258. /// <paramref name="second" />.</param>
  259. public static void Union(ref RectangleF first, ref RectangleF second, out RectangleF result)
  260. {
  261. result.X = Math.Min(first.X, second.X);
  262. result.Y = Math.Min(first.Y, second.Y);
  263. result.Width = Math.Max(first.Right, second.Right) - result.X;
  264. result.Height = Math.Max(first.Bottom, second.Bottom) - result.Y;
  265. }
  266. /// <summary>
  267. /// Computes the <see cref="RectangleF" /> that contains the two specified
  268. /// <see cref="RectangleF" /> structures.
  269. /// </summary>
  270. /// <param name="first">The first rectangle.</param>
  271. /// <param name="second">The second rectangle.</param>
  272. /// <returns>
  273. /// An <see cref="RectangleF" /> that contains both the <paramref name="first" /> and the
  274. /// <paramref name="second" />.
  275. /// </returns>
  276. public static RectangleF Union(RectangleF first, RectangleF second)
  277. {
  278. RectangleF result;
  279. Union(ref first, ref second, out result);
  280. return result;
  281. }
  282. /// <summary>
  283. /// Computes the <see cref="RectangleF" /> that contains both the specified <see cref="RectangleF" /> and this <see cref="RectangleF" />.
  284. /// </summary>
  285. /// <param name="rectangle">The rectangle.</param>
  286. /// <returns>
  287. /// An <see cref="RectangleF" /> that contains both the <paramref name="rectangle" /> and
  288. /// this <see cref="RectangleF" />.
  289. /// </returns>
  290. public RectangleF Union(RectangleF rectangle)
  291. {
  292. RectangleF result;
  293. Union(ref this, ref rectangle, out result);
  294. return result;
  295. }
  296. [Obsolete("RectangleF.Intersection() will be removed in the next update. Use Intersect() instead.")]
  297. public static void Intersection(ref RectangleF first,
  298. ref RectangleF second, out RectangleF result)
  299. {
  300. Intersect(ref first, ref second, out result);
  301. }
  302. [Obsolete("RectangleF.Intersection() will be removed in the next update. Use Intersect() instead.")]
  303. public static RectangleF Intersection(RectangleF first,
  304. RectangleF second)
  305. {
  306. return Intersect(first, second);
  307. }
  308. [Obsolete("RectangleF.Intersection() will be removed in the next update. Use Intersect() instead.")]
  309. public RectangleF Intersection(RectangleF rectangle)
  310. {
  311. return Intersect(rectangle);
  312. }
  313. /// <summary>
  314. /// Computes the <see cref="RectangleF"/> that represents the intersection of two <see cref="RectangleF"/>
  315. /// structures.
  316. /// </summary>
  317. /// <param name="value1">The first rectangle to intersect.</param>
  318. /// <param name="value2">The second rectangle to intersect.</param>
  319. /// <returns>
  320. /// A <see cref="RectangleF"/> that represents the intersection of <paramref name="value1"/> and
  321. /// <paramref name="value2"/>, if there is an intersection; otherwise, <see cref="RectangleF.Empty"/>.
  322. /// </returns>
  323. public static RectangleF Intersect(RectangleF value1, RectangleF value2)
  324. {
  325. RectangleF rectangle;
  326. Intersect(ref value1, ref value2, out rectangle);
  327. return rectangle;
  328. }
  329. /// <summary>
  330. /// Computes the <see cref="RectangleF"/> that represents the intersection of two <see cref="RectangleF"/>
  331. /// structures.
  332. /// </summary>
  333. /// <param name="value1">The first rectangle to intersect.</param>
  334. /// <param name="value2">The second rectangle to intersect.</param>
  335. /// <param name="result">
  336. /// When this method returns, contains the <see cref="RectangleF"/> that represents the intersection of
  337. /// <paramref name="value1"/> and <paramref name="value2"/>, if there is an intersection; otherwise,
  338. /// <see cref="RectangleF.Empty"/>
  339. /// </param>
  340. public static void Intersect(ref RectangleF value1, ref RectangleF value2, out RectangleF result)
  341. {
  342. var firstMinimum = value1.TopLeft;
  343. var firstMaximum = value1.BottomRight;
  344. var secondMinimum = value2.TopLeft;
  345. var secondMaximum = value2.BottomRight;
  346. var minimum = MathExtended.CalculateMaximumVector2(firstMinimum, secondMinimum);
  347. var maximum = MathExtended.CalculateMinimumVector2(firstMaximum, secondMaximum);
  348. if ((maximum.X < minimum.X) || (maximum.Y < minimum.Y))
  349. result = new RectangleF();
  350. else
  351. result = CreateFrom(minimum, maximum);
  352. }
  353. /// <summary>
  354. /// Computes the <see cref="RectangleF"/> that represents the intersection of this <see cref="RectangleF"/> and
  355. /// another.
  356. /// </summary>
  357. /// <param name="rectangle">The other <see cref="RectangleF"/> to intersect.</param>
  358. /// <returns>
  359. /// A <see cref="RectangleF"/> that represents the intersection of this <see cref="RectangleF"/> and
  360. /// <paramref name="rectangle"/>, if there is an intersection; otherwise, <see cref="RectangleF.Empty"/>.
  361. /// </returns>
  362. public RectangleF Intersect(RectangleF rectangle)
  363. {
  364. RectangleF result;
  365. Intersect(ref this, ref rectangle, out result);
  366. return result;
  367. }
  368. /// <summary>
  369. /// Determines whether the two specified <see cref="RectangleF" /> structures intersect.
  370. /// </summary>
  371. /// <param name="first">The first rectangle.</param>
  372. /// <param name="second">The second rectangle.</param>
  373. /// <returns>
  374. /// <c>true</c> if the <paramref name="first" /> intersects with the <see cref="second" />; otherwise, <c>false</c>.
  375. /// </returns>
  376. public static bool Intersects(ref RectangleF first, ref RectangleF second)
  377. {
  378. return first.X < second.X + second.Width && first.X + first.Width > second.X &&
  379. first.Y < second.Y + second.Height && first.Y + first.Height > second.Y;
  380. }
  381. /// <summary>
  382. /// Determines whether the two specified <see cref="RectangleF" /> structures intersect.
  383. /// </summary>
  384. /// <param name="first">The first rectangle.</param>
  385. /// <param name="second">The second rectangle.</param>
  386. /// <returns>
  387. /// <c>true</c> if the <paramref name="first" /> intersects with the <see cref="second" />; otherwise, <c>false</c>.
  388. /// </returns>
  389. public static bool Intersects(RectangleF first, RectangleF second)
  390. {
  391. return Intersects(ref first, ref second);
  392. }
  393. /// <summary>
  394. /// Determines whether the specified <see cref="RectangleF" /> intersects with this
  395. /// <see cref="RectangleF" />.
  396. /// </summary>
  397. /// <param name="rectangle">The bounding rectangle.</param>
  398. /// <returns>
  399. /// <c>true</c> if the <paramref name="rectangle" /> intersects with this
  400. /// <see cref="RectangleF" />; otherwise,
  401. /// <c>false</c>.
  402. /// </returns>
  403. public bool Intersects(RectangleF rectangle)
  404. {
  405. return Intersects(ref this, ref rectangle);
  406. }
  407. /// <summary>
  408. /// Normalizes this <see cref="RectangleF"/> so that the <see cref="Width"/> and <see cref="Height"/> are
  409. /// positive without changing the location of the rectangle.
  410. /// </summary>
  411. public void Normalize()
  412. {
  413. if (Width < 0)
  414. {
  415. X += Width;
  416. Width = -Width;
  417. }
  418. if (Height < 0)
  419. {
  420. Y += Height;
  421. Height = -Height;
  422. }
  423. }
  424. /// <summary>
  425. /// Normalizes the specified <see cref="RectangleF"/> so that the <see cref="Width"/> and <see cref="Height"/>
  426. /// are positive without changing the location of the rectangle.
  427. /// </summary>
  428. /// <param name="rectangle">The <see cref="RectangleF"/> to normalize.</param>
  429. /// <returns>A <see cref="RectangleF"/> with positive width and height.</returns>
  430. public static RectangleF Normalize(RectangleF rectangle)
  431. {
  432. if (rectangle.Width < 0)
  433. {
  434. rectangle.X += rectangle.Width;
  435. rectangle.Width = -rectangle.Width;
  436. }
  437. if (rectangle.Height < 0)
  438. {
  439. rectangle.Y += rectangle.Height;
  440. rectangle.Height = -rectangle.Height;
  441. }
  442. return rectangle;
  443. }
  444. /// <summary>
  445. /// Normalizes a <see cref="RectangleF"/> so that the <see cref="Width"/> and <see cref="Height"/> are positive
  446. /// without changing the location of the rectangle.
  447. /// </summary>
  448. /// <param name="rectangle">The source <see cref="RectangleF"/>.</param>
  449. /// <param name="result">
  450. /// When this method returns, contains the a normalized <see cref="RectangleF"/> with positive width and height.
  451. /// </param>
  452. public static void Normalize(ref RectangleF rectangle, out RectangleF result)
  453. {
  454. result.X = rectangle.X;
  455. result.Width = rectangle.Width;
  456. if (result.Width < 0)
  457. {
  458. result.X += result.Width;
  459. result.Width = -result.Width;
  460. }
  461. result.Y = rectangle.Y;
  462. result.Height = rectangle.Height;
  463. if (result.Height < 0)
  464. {
  465. result.Y += result.Height;
  466. result.Height = -result.Height;
  467. }
  468. }
  469. /// <summary>
  470. /// Determines whether the specified <see cref="RectangleF" /> contains the specified
  471. /// <see cref="Vector2" />.
  472. /// </summary>
  473. /// <param name="rectangle">The rectangle.</param>
  474. /// <param name="point">The point.</param>
  475. /// <returns>
  476. /// <c>true</c> if the <paramref name="rectangle" /> contains the <paramref name="point" />; otherwise,
  477. /// <c>false</c>.
  478. /// </returns>
  479. public static bool Contains(ref RectangleF rectangle, ref Vector2 point)
  480. {
  481. return rectangle.X <= point.X && point.X < rectangle.X + rectangle.Width && rectangle.Y <= point.Y && point.Y < rectangle.Y + rectangle.Height;
  482. }
  483. /// <summary>
  484. /// Determines whether the specified <see cref="RectangleF" /> contains the specified
  485. /// <see cref="Vector2" />.
  486. /// </summary>
  487. /// <param name="rectangle">The rectangle.</param>
  488. /// <param name="point">The point.</param>
  489. /// <returns>
  490. /// <c>true</c> if the <paramref name="rectangle" /> contains the <paramref name="point" />; otherwise,
  491. /// <c>false</c>.
  492. /// </returns>
  493. public static bool Contains(RectangleF rectangle, Vector2 point)
  494. {
  495. return Contains(ref rectangle, ref point);
  496. }
  497. /// <summary>
  498. /// Determines whether this <see cref="RectangleF" /> contains the specified
  499. /// <see cref="Vector2" />.
  500. /// </summary>
  501. /// <param name="point">The point.</param>
  502. /// <returns>
  503. /// <c>true</c> if the this <see cref="RectangleF"/> contains the <paramref name="point" />; otherwise,
  504. /// <c>false</c>.
  505. /// </returns>
  506. public bool Contains(Vector2 point)
  507. {
  508. return Contains(ref this, ref point);
  509. }
  510. /// <summary>
  511. /// Updates this <see cref="RectangleF" /> from a list of <see cref="Vector2" /> structures.
  512. /// </summary>
  513. /// <param name="points">The points.</param>
  514. public void UpdateFromPoints(IReadOnlyList<Vector2> points)
  515. {
  516. var rectangle = CreateFrom(points);
  517. X = rectangle.X;
  518. Y = rectangle.Y;
  519. Width = rectangle.Width;
  520. Height = rectangle.Height;
  521. }
  522. /// <summary>
  523. /// Computes the squared distance from this <see cref="RectangleF"/> to a <see cref="Vector2"/>.
  524. /// </summary>
  525. /// <param name="point">The point.</param>
  526. /// <returns>The squared distance from this <see cref="RectangleF"/> to the <paramref name="point"/>.</returns>
  527. public float SquaredDistanceTo(Vector2 point)
  528. {
  529. return PrimitivesHelper.SquaredDistanceToPointFromRectangle(TopLeft, BottomRight, point);
  530. }
  531. /// <summary>
  532. /// Computes the distance from this <see cref="RectangleF"/> to a <see cref="Vector2"/>.
  533. /// </summary>
  534. /// <param name="point">The point.</param>
  535. /// <returns>The distance from this <see cref="RectangleF"/> to the <paramref name="point"/>.</returns>
  536. public float DistanceTo(Vector2 point)
  537. {
  538. return (float)Math.Sqrt(SquaredDistanceTo(point));
  539. }
  540. /// <summary>
  541. /// Computes the closest <see cref="Vector2" /> on this <see cref="RectangleF" /> to a specified
  542. /// <see cref="Vector2" />.
  543. /// </summary>
  544. /// <param name="point">The point.</param>
  545. /// <returns>The closest <see cref="Vector2" /> on this <see cref="RectangleF" /> to the <paramref name="point" />.</returns>
  546. public Vector2 ClosestPointTo(Vector2 point)
  547. {
  548. Vector2 result;
  549. PrimitivesHelper.ClosestPointToPointFromRectangle(TopLeft, BottomRight, point, out result);
  550. return result;
  551. }
  552. //TODO: Document this.
  553. public void Inflate(float horizontalAmount, float verticalAmount)
  554. {
  555. X -= horizontalAmount;
  556. Y -= verticalAmount;
  557. Width += horizontalAmount * 2;
  558. Height += verticalAmount * 2;
  559. }
  560. //TODO: Document this.
  561. public void Offset(float offsetX, float offsetY)
  562. {
  563. X += offsetX;
  564. Y += offsetY;
  565. }
  566. //TODO: Document this.
  567. public void Offset(Vector2 amount)
  568. {
  569. X += amount.X;
  570. Y += amount.Y;
  571. }
  572. /// <summary>
  573. /// Compares two <see cref="RectangleF" /> structures. The result specifies whether the values of the
  574. /// <see cref="X" />, <see cref="Y"/>, <see cref="Width"/> and <see cref="Height" /> fields of the two <see cref="RectangleF" /> structures
  575. /// are equal.
  576. /// </summary>
  577. /// <param name="first">The first rectangle.</param>
  578. /// <param name="second">The second rectangle.</param>
  579. /// <returns>
  580. /// <c>true</c> if the values of the
  581. /// <see cref="X" />, <see cref="Y"/>, <see cref="Width"/> and <see cref="Height" /> fields of the two <see cref="RectangleF" /> structures
  582. /// are equal; otherwise, <c>false</c>.
  583. /// </returns>
  584. public static bool operator ==(RectangleF first, RectangleF second)
  585. {
  586. return first.Equals(ref second);
  587. }
  588. /// <summary>
  589. /// Compares two <see cref="RectangleF" /> structures. The result specifies whether the values of the
  590. /// <see cref="X" />, <see cref="Y"/>, <see cref="Width"/> and <see cref="Height" /> fields of the two <see cref="RectangleF" /> structures
  591. /// are unequal.
  592. /// </summary>
  593. /// <param name="first">The first rectangle.</param>
  594. /// <param name="second">The second rectangle.</param>
  595. /// <returns>
  596. /// <c>true</c> if the values of the
  597. /// <see cref="X" />, <see cref="Y"/>, <see cref="Width"/> and <see cref="Height" /> fields of the two <see cref="RectangleF" /> structures
  598. /// are unequal; otherwise, <c>false</c>.
  599. /// </returns>
  600. public static bool operator !=(RectangleF first, RectangleF second)
  601. {
  602. return !(first == second);
  603. }
  604. /// <summary>
  605. /// Indicates whether this <see cref="RectangleF" /> is equal to another <see cref="RectangleF" />.
  606. /// </summary>
  607. /// <param name="rectangle">The rectangle.</param>
  608. /// <returns>
  609. /// <c>true</c> if this <see cref="RectangleF" /> is equal to the <paramref name="rectangle" />; otherwise, <c>false</c>.
  610. /// </returns>
  611. public bool Equals(RectangleF rectangle)
  612. {
  613. return Equals(ref rectangle);
  614. }
  615. /// <summary>
  616. /// Indicates whether this <see cref="RectangleF" /> is equal to another <see cref="RectangleF" />.
  617. /// </summary>
  618. /// <param name="rectangle">The rectangle.</param>
  619. /// <returns>
  620. /// <c>true</c> if this <see cref="RectangleF" /> is equal to the <paramref name="rectangle" />; otherwise, <c>false</c>.
  621. /// </returns>
  622. public bool Equals(ref RectangleF rectangle)
  623. {
  624. // ReSharper disable CompareOfFloatsByEqualityOperator
  625. return X == rectangle.X && Y == rectangle.Y && Width == rectangle.Width && Height == rectangle.Height;
  626. // ReSharper restore CompareOfFloatsByEqualityOperator
  627. }
  628. /// <summary>
  629. /// Returns a value indicating whether this <see cref="RectangleF" /> is equal to a specified object.
  630. /// </summary>
  631. /// <param name="obj">The object to make the comparison with.</param>
  632. /// <returns>
  633. /// <c>true</c> if this <see cref="RectangleF" /> is equal to <paramref name="obj" />; otherwise, <c>false</c>.
  634. /// </returns>
  635. public override bool Equals(object obj)
  636. {
  637. return obj is RectangleF && Equals((RectangleF)obj);
  638. }
  639. /// <summary>
  640. /// Returns a hash code of this <see cref="RectangleF" /> suitable for use in hashing algorithms and data
  641. /// structures like a hash table.
  642. /// </summary>
  643. /// <returns>
  644. /// A hash code of this <see cref="RectangleF" />.
  645. /// </returns>
  646. public override int GetHashCode()
  647. {
  648. unchecked
  649. {
  650. var hashCode = X.GetHashCode();
  651. hashCode = (hashCode * 397) ^ Y.GetHashCode();
  652. hashCode = (hashCode * 397) ^ Width.GetHashCode();
  653. hashCode = (hashCode * 397) ^ Height.GetHashCode();
  654. return hashCode;
  655. }
  656. }
  657. /// <summary>
  658. /// Performs an implicit conversion from a <see cref="Rectangle" /> to a <see cref="RectangleF" />.
  659. /// </summary>
  660. /// <param name="rectangle">The rectangle.</param>
  661. /// <returns>
  662. /// The resulting <see cref="RectangleF" />.
  663. /// </returns>
  664. public static implicit operator RectangleF(Rectangle rectangle)
  665. {
  666. return new RectangleF
  667. {
  668. X = rectangle.X,
  669. Y = rectangle.Y,
  670. Width = rectangle.Width,
  671. Height = rectangle.Height
  672. };
  673. }
  674. /// <summary>
  675. /// Performs an explicit conversion from a <see cref="Rectangle" /> to a <see cref="RectangleF" />.
  676. /// </summary>
  677. /// <param name="rectangle">The rectangle.</param>
  678. /// <returns>
  679. /// The resulting <see cref="RectangleF" />.
  680. /// </returns>
  681. /// <remarks>
  682. /// <para>A loss of precision may occur due to the truncation from <see cref="float" /> to <see cref="int" />.</para>
  683. /// </remarks>
  684. public static explicit operator Rectangle(RectangleF rectangle)
  685. {
  686. return new Rectangle((int)rectangle.X, (int)rectangle.Y, (int)rectangle.Width, (int)rectangle.Height);
  687. }
  688. /// <summary>
  689. /// Returns a <see cref="string" /> that represents this <see cref="RectangleF" />.
  690. /// </summary>
  691. /// <returns>
  692. /// A <see cref="string" /> that represents this <see cref="RectangleF" />.
  693. /// </returns>
  694. public override string ToString()
  695. {
  696. return $"X: {X}, Y: {Y}, Width: {Width}, Height: {Height}";
  697. }
  698. internal string DebugDisplayString => string.Concat(X, " ", Y, " ", Width, " ", Height);
  699. }
  700. }