context: using System;
  using System.Runtime.Serialization;
  using System.Diagnostics;
  using Microsoft.Xna.Framework;
  
  
  namespace Nez
  {
  	/// <summary>
  	/// Describes a 2D-rectangle. 
  	/// </summary>
  	[DebuggerDisplay( "{DebugDisplayString,nq}" )]
  	public struct RectangleF : IEquatable<RectangleF>
  	{
  		private static RectangleF emptyRectangle = new RectangleF();
  
  		/// <summary>
  		/// The x coordinate of the top-left corner of this <see cref="RectangleF"/>.
  		/// </summary>
  		public float x;
  
  		/// <summary>
  		/// The y coordinate of the top-left corner of this <see cref="RectangleF"/>.
  		/// </summary>
  		public float y;
  
  		/// <summary>
  		/// The width of this <see cref="RectangleF"/>.
  		/// </summary>
  		public float width;
  
  		/// <summary>
  		/// The height of this <see cref="RectangleF"/>.
  		/// </summary>
  		public float height;
  
  
  		#region Public Properties
  
  		/// <summary>
  		/// Returns a <see cref="RectangleF"/> with X=0, Y=0, Width=0, Height=0.
  		/// </summary>
  		public static RectangleF empty
  		{
  			get { return emptyRectangle; }
  		}
  
  		/// <summary>
  		/// Returns the x coordinate of the left edge of this <see cref="RectangleF"/>.
  		/// </summary>
  		public float left
  		{
  			get { return this.x; }
  		}
  
  		/// <summary>
  		/// Returns the x coordinate of the right edge of this <see cref="RectangleF"/>.
  		/// </summary>
  		public float right
  		{
  			get { return ( this.x + this.width ); }
  		}
  
  		/// <summary>
  		/// Returns the y coordinate of the top edge of this <see cref="RectangleF"/>.
  		/// </summary>
  		public float top
  		{
  			get { return this.y; }
  		}
  
  		/// <summary>
  		/// Returns the y coordinate of the bottom edge of this <see cref="RectangleF"/>.
  		/// </summary>
  		public float bottom
  		{
  			get { return ( this.y + this.height ); }
  		}
  
  		/// <summary>
  		/// gets the max point of the rectangle, the bottom-right corner
  		/// </summary>
  		/// <value>The max.</value>
  		public Vector2 max { get { return new Vector2( right, bottom ); } }
  
  		/// <summary>
  		/// Whether or not this <see cref="RectangleF"/> has a <see cref="Width"/> and
  		/// <see cref="Height"/> of 0, and a <see cref="Location"/> of (0, 0).
  		/// </summary>
  		public bool isEmpty
  		{
  			get
  			{
  				return ( ( ( ( this.width == 0 ) && ( this.height == 0 ) ) && ( this.x == 0 ) ) && ( this.y == 0 ) );
  			}
  		}
  
  		/// <summary>
  		/// The top-left coordinates of this <see cref="RectangleF"/>.
  		/// </summary>
  		public Vector2 location
  		{
  			get
  			{
  				return new Vector2( this.x, this.y );
  			}
  			set
  			{
  				x = value.X;
  				y = value.Y;
  			}
  		}
  
  		/// <summary>
  		/// The width-height coordinates of this <see cref="RectangleF"/>.
  		/// </summary>
  		public Vector2 size
  		{
  			get
  			{
  				return new Vector2( this.width, this.height );
  			}
  			set
  			{
  				width = value.X;
  				height = value.Y;
  			}
  		}
  
  		/// <summary>
  		/// A <see cref="Point"/> located in the center of this <see cref="RectangleF"/>.
  		/// </summary>
  		/// <remarks>
  		/// If <see cref="Width"/> or <see cref="Height"/> is an odd number,
  		/// the center point will be rounded down.
  		/// </remarks>
  		public Vector2 center
  		{
  			get { return new Vector2( this.x + ( this.width / 2 ), this.y + ( this.height / 2 ) ); }
  		}
  
  		#endregion
  
  
  		internal string DebugDisplayString
  		{
  			get
  			{
  				return string.Concat(
  					this.x, "  ",
  					this.y, "  ",
  					this.width, "  ",
  					this.height
  				);
  			}
  		}
  
  
  		/// <summary>
  		/// Creates a new instance of <see cref="RectangleF"/> struct, with the specified
  		/// position, width, and height.
  		/// </summary>
  		/// <param name="x">The x coordinate of the top-left corner of the created <see cref="RectangleF"/>.</param>
  		/// <param name="y">The y coordinate of the top-left corner of the created <see cref="RectangleF"/>.</param>
  		/// <param name="width">The width of the created <see cref="RectangleF"/>.</param>
  		/// <param name="height">The height of the created <see cref="RectangleF"/>.</param>
  		public RectangleF( float x, float y, float width, float height )
  		{
  			this.x = x;
  			this.y = y;
  			this.width = width;
  			this.height = height;
  		}
  
  
  		/// <summary>
  		/// Creates a new instance of <see cref="RectangleF"/> struct, with the specified
  		/// location and size.
  		/// </summary>
  		/// <param name="location">The x and y coordinates of the top-left corner of the created <see cref="RectangleF"/>.</param>
  		/// <param name="size">The width and height of the created <see cref="RectangleF"/>.</param>
  		public RectangleF( Vector2 location, Vector2 size )
  		{
  			this.x = location.X;
  			this.y = location.Y;
  			this.width = size.X;
  			this.height = size.Y;
  		}
  
  
  		/// <summary>
  		/// creates a RectangleF given min/max points (top-left, bottom-right points)
  		/// </summary>
  		/// <returns>The minimum max points.</returns>
  		/// <param name="min">Minimum.</param>
  		/// <param name="max">Max.</param>
  		public static RectangleF fromMinMax( Vector2 min, Vector2 max )
  		{
  			return new RectangleF( min.X, min.Y, max.X - min.X, max.Y - min.Y );
  		}
  
  
  		/// <summary>
  		/// creates a RectangleF given min/max points (top-left, bottom-right points)
  		/// </summary>
  		/// <returns>The minimum max points.</returns>
  		/// <param name="min">Minimum.</param>
  		/// <param name="max">Max.</param>
  		public static RectangleF fromMinMax( float minX, float minY, float maxX, float maxY )
  		{
  			return new RectangleF( minX, minY, maxX - minX, maxY - minY );
  		}
  
  
  		/// <summary>
  		/// given the points of a polygon calculates the bounds
  		/// </summary>
  		/// <returns>The from polygon points.</returns>
  		/// <param name="points">Points.</param>
  		public static RectangleF rectEncompassingPoints( Vector2[] points )
  		{
  			// we need to find the min/max x/y values
  			var minX = float.PositiveInfinity;
  			var minY = float.PositiveInfinity;
  			var maxX = float.NegativeInfinity;
  			var maxY = float.NegativeInfinity;
  
  			for( var i = 0; i < points.Length; i++ )
  			{
  				var pt = points[i];
  
  				if( pt.X < minX )
  					minX = pt.X;
  				if( pt.X > maxX )
  					maxX = pt.X;
  
  				if( pt.Y < minY )
  					minY = pt.Y;
  				if( pt.Y > maxY )
  					maxY = pt.Y;
  			}
  
  			return RectangleF.fromMinMax( minX, minY, maxX, maxY );
  		}
  
  
  		#region Public Methods
  
  		/// <summary>
  		/// gets the position of the specified edge
  		/// </summary>
  		/// <returns>The side.</returns>
  		/// <param name="edge">Side.</param>
  		public float getSide( Edge edge )
  		{
  			switch( edge )
  			{
  				case Edge.Top:
  					return top;
  				case Edge.Bottom:
  					return bottom;
  				case Edge.Left:
  					return left;
  				case Edge.Right:
  					return right;
  				default:
  					throw new ArgumentOutOfRangeException();
  			}
  		}
  
  
  		/// <summary>
  		/// Gets whether or not the provided coordinates lie within the bounds of this <see cref="RectangleF"/>.
  		/// </summary>
  		/// <param name="x">The x coordinate of the point to check for containment.</param>
  		/// <param name="y">The y coordinate of the point to check for containment.</param>
  		/// <returns><c>true</c> if the provided coordinates lie inside this <see cref="RectangleF"/>; <c>false</c> otherwise.</returns>
  		public bool contains( int x, int y )
  		{
  			return ( ( ( ( this.x <= x ) && ( x < ( this.x + this.width ) ) ) && ( this.y <= y ) ) && ( y < ( this.y + this.height ) ) );
  		}
  
  
  		/// <summary>
  		/// Gets whether or not the provided coordinates lie within the bounds of this <see cref="RectangleF"/>.
  		/// </summary>
  		/// <param name="x">The x coordinate of the point to check for containment.</param>
  		/// <param name="y">The y coordinate of the point to check for containment.</param>
  		/// <returns><c>true</c> if the provided coordinates lie inside this <see cref="RectangleF"/>; <c>false</c> otherwise.</returns>
  		public bool contains( float x, float y )
  		{
  			return ( ( ( ( this.x <= x ) && ( x < ( this.x + this.width ) ) ) && ( this.y <= y ) ) && ( y < ( this.y + this.height ) ) );
  		}
  
  
  		/// <summary>
  		/// Gets whether or not the provided <see cref="Point"/> lies within the bounds of this <see cref="RectangleF"/>.
  		/// </summary>
  		/// <param name="value">The coordinates to check for inclusion in this <see cref="RectangleF"/>.</param>
  		/// <returns><c>true</c> if the provided <see cref="Point"/> lies inside this <see cref="RectangleF"/>; <c>false</c> otherwise.</returns>
  		public bool contains( Point value )
  		{
  			return ( ( ( ( this.x <= value.X ) && ( value.X < ( this.x + this.width ) ) ) && ( this.y <= value.Y ) ) && ( value.Y < ( this.y + this.height ) ) );
  		}
  
  
  		/// <summary>
  		/// Gets whether or not the provided <see cref="Point"/> lies within the bounds of this <see cref="RectangleF"/>.
  		/// </summary>
  		/// <param name="value">The coordinates to check for inclusion in this <see cref="RectangleF"/>.</param>
  		/// <param name="result"><c>true</c> if the provided <see cref="Point"/> lies inside this <see cref="RectangleF"/>; <c>false</c> otherwise. As an output parameter.</param>
  		public void contains( ref Point value, out bool result )
  		{
  			result = ( ( ( ( this.x <= value.X ) && ( value.X < ( this.x + this.width ) ) ) && ( this.y <= value.Y ) ) && ( value.Y < ( this.y + this.height ) ) );
  		}
  
  
  		/// <summary>
  		/// Gets whether or not the provided <see cref="Vector2"/> lies within the bounds of this <see cref="RectangleF"/>.
  		/// </summary>
  		/// <param name="value">The coordinates to check for inclusion in this <see cref="RectangleF"/>.</param>
  		/// <returns><c>true</c> if the provided <see cref="Vector2"/> lies inside this <see cref="RectangleF"/>; <c>false</c> otherwise.</returns>
  		public bool contains( Vector2 value )
  		{
  			return ( ( ( ( this.x <= value.X ) && ( value.X < ( this.x + this.width ) ) ) && ( this.y <= value.Y ) ) && ( value.Y < ( this.y + this.height ) ) );
  		}
  
  
  		/// <summary>
  		/// Gets whether or not the provided <see cref="Vector2"/> lies within the bounds of this <see cref="RectangleF"/>.
  		/// </summary>
  		/// <param name="value">The coordinates to check for inclusion in this <see cref="RectangleF"/>.</param>
  		/// <param name="result"><c>true</c> if the provided <see cref="Vector2"/> lies inside this <see cref="RectangleF"/>; <c>false</c> otherwise. As an output parameter.</param>
  		public void contains( ref Vector2 value, out bool result )
  		{
  			result = ( ( ( ( this.x <= value.X ) && ( value.X < ( this.x + this.width ) ) ) && ( this.y <= value.Y ) ) && ( value.Y < ( this.y + this.height ) ) );
  		}
  
  
  		/// <summary>
  		/// Gets whether or not the provided <see cref="RectangleF"/> lies within the bounds of this <see cref="RectangleF"/>.
  		/// </summary>
  		/// <param name="value">The <see cref="RectangleF"/> to check for inclusion in this <see cref="RectangleF"/>.</param>
  		/// <returns><c>true</c> if the provided <see cref="RectangleF"/>'s bounds lie entirely inside this <see cref="RectangleF"/>; <c>false</c> otherwise.</returns>
  		public bool contains( RectangleF value )
  		{
  			return ( ( ( ( this.x <= value.x ) && ( ( value.x + value.width ) <= ( this.x + this.width ) ) ) && ( this.y <= value.y ) ) && ( ( value.y + value.height ) <= ( this.y + this.height ) ) );
  		}
  
  
  		/// <summary>
  		/// Gets whether or not the provided <see cref="RectangleF"/> lies within the bounds of this <see cref="RectangleF"/>.
  		/// </summary>
  		/// <param name="value">The <see cref="RectangleF"/> to check for inclusion in this <see cref="RectangleF"/>.</param>
  		/// <param name="result"><c>true</c> if the provided <see cref="RectangleF"/>'s bounds lie entirely inside this <see cref="RectangleF"/>; <c>false</c> otherwise. As an output parameter.</param>
  		public void contains( ref RectangleF value, out bool result )
  		{
  			result = ( ( ( ( this.x <= value.x ) && ( ( value.x + value.width ) <= ( this.x + this.width ) ) ) && ( this.y <= value.y ) ) && ( ( value.y + value.height ) <= ( this.y + this.height ) ) );
  		}
  
  
  		/// <summary>
  		/// Adjusts the edges of this <see cref="RectangleF"/> by specified horizontal and vertical amounts. 
  		/// </summary>
  		/// <param name="horizontalAmount">Value to adjust the left and right edges.</param>
  		/// <param name="verticalAmount">Value to adjust the top and bottom edges.</param>
  		public void inflate( int horizontalAmount, int verticalAmount )
  		{
  			x -= horizontalAmount;
  			y -= verticalAmount;
  			width += horizontalAmount * 2;
  			height += verticalAmount * 2;
  		}
  
  
  		/// <summary>
  		/// Adjusts the edges of this <see cref="RectangleF"/> by specified horizontal and vertical amounts. 
  		/// </summary>
  		/// <param name="horizontalAmount">Value to adjust the left and right edges.</param>
  		/// <param name="verticalAmount">Value to adjust the top and bottom edges.</param>
  		public void inflate( float horizontalAmount, float verticalAmount )
  		{
  			x -= horizontalAmount;
  			y -= verticalAmount;
  			width += horizontalAmount * 2;
  			height += verticalAmount * 2;
  		}
  
  
  		/// <summary>
  		/// Gets whether or not the other <see cref="RectangleF"/> intersects with this rectangle.
  		/// </summary>
  		/// <param name="value">The other rectangle for testing.</param>
  		/// <returns><c>true</c> if other <see cref="RectangleF"/> intersects with this rectangle; <c>false</c> otherwise.</returns>
  		public bool intersects( RectangleF value )
  		{
  			return value.left < right &&
  			left < value.right &&
  			value.top < bottom &&
  			top < value.bottom;
  		}
  
  
  		/// <summary>
  		/// Gets whether or not the other <see cref="RectangleF"/> intersects with this rectangle.
  		/// </summary>
  		/// <param name="value">The other rectangle for testing.</param>
  		/// <param name="result"><c>true</c> if other <see cref="RectangleF"/> intersects with this rectangle; <c>false</c> otherwise. As an output parameter.</param>
  		public void intersects( ref RectangleF value, out bool result )
  		{
  			result = value.left < right &&
  			left < value.right &&
  			value.top < bottom &&
  			top < value.bottom;
  		}
  
  
  		/// <summary>
  		/// returns true if other intersects rect
  		/// </summary>
  		/// <param name="other">other.</param>
  		public bool intersects( ref RectangleF other )
  		{
  			bool result;
  			intersects( ref other, out result );
  			return result;
  		}
  
  
  		public bool rayIntersects( ref Ray2D ray, out float distance )
  		{
  			distance = 0f;
  			var maxValue = float.MaxValue;
  
  			if( Math.Abs( ray.direction.X ) < 1E-06f )
  			{
  				if( ( ray.start.X < x ) || ( ray.start.X > x + width ) )
  					return false;
  			}
  			else
  			{
  				var num11 = 1f / ray.direction.X;
  				var num8 = ( x - ray.start.X ) * num11;
  				var num7 = ( x + width - ray.start.X ) * num11;
  				if( num8 > num7 )
  				{
  					var num14 = num8;
  					num8 = num7;
  					num7 = num14;
  				}
  
  				distance = MathHelper.Max( num8, distance );
  				maxValue = MathHelper.Min( num7, maxValue );
  				if( distance > maxValue )
  					return false;
  			}
  
  			if( Math.Abs( ray.direction.Y ) < 1E-06f )
  			{
  				if( ( ray.start.Y < y ) || ( ray.start.Y > y + height ) )
  				{
  					return false;
  				}
  			}
  			else
  			{
  				var num10 = 1f / ray.direction.Y;
  				var num6 = ( y - ray.start.Y ) * num10;
  				var num5 = ( y + height - ray.start.Y ) * num10;
  				if( num6 > num5 )
  				{
  					var num13 = num6;
  					num6 = num5;
  					num5 = num13;
  				}
  
  				distance = MathHelper.Max( num6, distance );
  				maxValue = MathHelper.Min( num5, maxValue );
  				if( distance > maxValue )
  					return false;
  			}
  
  			return true;
  		}
  
  
  		public float? rayIntersects( Ray ray )
  		{
  			var num = 0f;
  			var maxValue = float.MaxValue;
  
  			if( Math.Abs( ray.Direction.X ) < 1E-06f )
  			{
  				if( ( ray.Position.X < left ) || ( ray.Position.X > right ) )
  					return null;
  			}
  			else
  			{
  				float num11 = 1f / ray.Direction.X;
  				float num8 = ( left - ray.Position.X ) * num11;
  				float num7 = ( right - ray.Position.X ) * num11;
  				if( num8 > num7 )
  				{
  					float num14 = num8;
  					num8 = num7;
  					num7 = num14;
  				}
  
  				num = MathHelper.Max( num8, num );
  				maxValue = MathHelper.Min( num7, maxValue );
  				if( num > maxValue )
  				{
  					return null;  
  				}  
  			}
  
  			if( Math.Abs( ray.Direction.Y ) < 1E-06f )
  			{
  				if( ( ray.Position.Y < top ) || ( ray.Position.Y > bottom ) )
  				{
  					return null;
  				}
  			}
  			else
  			{
  				float num10 = 1f / ray.Direction.Y;
  				float num6 = ( top - ray.Position.Y ) * num10;
  				float num5 = ( bottom - ray.Position.Y ) * num10;
  				if( num6 > num5 )
  				{
  					float num13 = num6;
  					num6 = num5;
  					num5 = num13;
  				}
  
  				num = MathHelper.Max( num6, num );
  				maxValue = MathHelper.Min( num5, maxValue );
  				if( num > maxValue )
  					return null;
  			}
  
  			return new float?( num );
  		}
  
  
  		public Vector2 getClosestPointOnBoundsToOrigin()
  		{
  			var max = this.max;
  			var minDist = Math.Abs( location.X );
  			var boundsPoint = new Vector2( location.X, 0 );
  
  			if( Math.Abs( max.X ) < minDist )
  			{
  				minDist = Math.Abs( max.X );
  				boundsPoint.X = max.X;
  				boundsPoint.Y = 0f;
  			}
  
  			if( Math.Abs( max.Y ) < minDist )
  			{
  				minDist = Math.Abs( max.Y );
  				boundsPoint.X = 0f;
  				boundsPoint.Y = max.Y;
  			}
  
  			if( Math.Abs( location.Y ) < minDist )
  			{
  				minDist = Math.Abs( location.Y );
  				boundsPoint.X = 0;
  				boundsPoint.Y = location.Y;
  			}
  
  			return boundsPoint;
  		}
  
  
  		/// <summary>
  		/// returns the closest point that is in or on the RectangleF to the given point
  		/// </summary>
  		/// <returns>The closest point on rectangle to point.</returns>
  		/// <param name="point">Point.</param>
  		public Vector2 getClosestPointOnRectangleFToPoint( Vector2 point )
  		{
  			// for each axis, if the point is outside the box clamp it to the box else leave it alone
  			var res = new Vector2();
  			res.X = MathHelper.Clamp( point.X, left, right );
  			res.Y = MathHelper.Clamp( point.Y, top, bottom );
  
  			return res;
  		}
  
  
  		/// <summary>
  		/// gets the closest point that is on the rectangle border to the given point
  		/// </summary>
  		/// <returns>The closest point on rectangle border to point.</returns>
  		/// <param name="point">Point.</param>
  		public Vector2 getClosestPointOnRectangleBorderToPoint( Vector2 point )
  		{
  			// for each axis, if the point is outside the box clamp it to the box else leave it alone
  			var res = new Vector2();
  			res.X = MathHelper.Clamp( point.X, left, right );
  			res.Y = MathHelper.Clamp( point.Y, top, bottom );
  
  			// if point is inside the rectangle we need to push res to the border since it will be inside the rect
  			if( contains( res ) )
  			{
  				var dl = res.X - left;
  				var dr = right - res.X;
  
gt: 				var dt = res.Y - top;