/// <summary> /// This looks long direction until a spot large enough to hold size is available /// </summary> /// <param name="size">The size of the rectangle to return</param> /// <param name="start">The point that the rectangle would like to be centered over</param> /// <param name="direction"> /// The direction to slide the rectangle until an empty space is found /// NOTE: Set dir.Y to be negative to match screen coords /// </param> public static Rect GetFreeSpot(Size size, Point desiredPos, Vector direction, List<Rect> existing) { double halfWidth = size.Width / 2d; double halfHeight = size.Height / 2d; if (existing.Count == 0) { // There is nothing blocking this, center the rectangle over the position return new Rect(desiredPos.X - halfWidth, desiredPos.Y - halfHeight, size.Width, size.Height); } // Direction unit Vector dirUnit = direction.ToUnit(); if (Math2D.IsInvalid(dirUnit)) { dirUnit = Math3D.GetRandomVector_Circular_Shell(1).ToVector2D(); } // Calculate step distance (5% of the average of all the sizes) double stepDist = UtilityCore.Iterate<Size>(size, existing.Select(o => o.Size)). SelectMany(o => new[] { o.Width, o.Height }). Average(); stepDist *= .05; // Keep walking along direction until the rectangle doesn't intersect any existing rectangles Point point = new Point(); Rect rect = new Rect(); for (int cntr = 0; cntr < 5000; cntr++) { point = desiredPos + (dirUnit * (stepDist * cntr)); rect = new Rect(point.X - halfWidth, point.Y - halfHeight, size.Width, size.Height); if (!existing.Any(o => o.IntersectsWith(rect))) { break; } } return rect; }