Share via


Rect.Intersects and IsDefined

When working on the PriorityQuadTree, most of the code I was reading and writing revolved around rectangle intersection.  Rect defines an IntersectsWith method, but it doesn’t work with rectangles that are infinitely wide or tall like new Rect(Double.NegativeInfinity, Double.NegativeInfinity, Double.PositiveInfinity, Double.PositiveInfinity)), and asking whether anything intersects with Rect.Empty returns false.  This is opposite from set theory which says that the empty set intersects all other sets.  You can fix both of those issues by implementing it like this:

 public static bool Intersects(this Rect self, Rect rect)
{
    return (self.IsEmpty || rect.IsEmpty) ||
    (self.Width == Double.PositiveInfinity || self.Right >= rect.Left) &&
    (rect.Width == Double.PositiveInfinity || rect.Right >= self.Left) &&
    (self.Height == Double.PositiveInfinity || self.Bottom >= rect.Top) &&
    (rect.Height == Double.PositiveInfinity || rect.Bottom >= self.Top);
}

(If you prefer the old behavior where the empty rect doesn’t intersect with any rect then just modify the first line.)

Another issue when dealing with Rects is determining whether they’re valid when doing argument checking.  It’s easy for users to create Rects that make no sense: they can use Rect.Empty, they can set X or Y to PositiveInfinity, they can set any of the values to NaN, etc.  About the only thing they can’t do is set Width or Height to a negative number (since that’s what designates Rect.Empty internally).  So to determine whether a given Rect defines an actual point in finite space, you have to do a bunch of checks:

 public static bool IsDefined(this Rect rect)
{
    return rect.Width >= 0.0 && 
           rect.Height >= 0.0 &&
           rect.Top < Double.PositiveInfinity &&
           rect.Left < Double.PositiveInfinity &&
          (rect.Top > Double.NegativeInfinity ||
           rect.Height == Double.PositiveInfinity) && 
          (rect.Left > Double.NegativeInfinity ||
           rect.Width == Double.PositiveInfinity);
}

I’ve put both of these extension methods (and one called GetCenter) in a class called RectExtensions and attached the source code.  Enjoy!

RectExtensions.cs