/// <summary> /// Somewhat optimized rectangle puller /// Courtesy http://www.drdobbs.com/database/the-maximal-rectangle-problem/184410529 /// </summary> /// <returns></returns> public HashSet<BoundingBox> GetAllRectangles(HashSet<Location> locations, BoundingBox boundingBox) { //Console.WriteLine("Entering GetAllRectangles"); DateTime start = DateTime.Now; HashSet<BoundingBox> result = new HashSet<BoundingBox>(); while (locations.Count > 0) { bool[,] boolArray = new bool[boundingBox.LowerRight.X + 1, boundingBox.LowerRight.Y + 1]; foreach (Location location in locations) { boolArray[location.Point.X, location.Point.Y] = true; } BoundingBox best = new BoundingBox(); for (int upperLeftX = BoundingBox.UpperLeft.X; upperLeftX < boundingBox.LowerRight.X + 1; upperLeftX++) { for (int upperLeftY = BoundingBox.UpperLeft.Y; upperLeftY < boundingBox.LowerRight.Y + 1; upperLeftY++) { if (!boolArray[upperLeftX, upperLeftY]) { continue; } BoundingBox candidate = GrowOnes(new SxzPoint(upperLeftX, upperLeftY), boundingBox, boolArray); if (candidate.Area() > best.Area()) { best = candidate; } } } if (best.UpperLeft.X == -1) { break; } result.Add(best); //Console.WriteLine("Have total rectangles " + result.Count); //Console.WriteLine("Have remaining locations " + locations.Count); foreach (Location location in new HashSet<Location>(locations)) { if (best.Contains(location.Point.X, location.Point.Y)) { locations.Remove(location); } } } //Console.WriteLine("Leaving GetAllRectangles with time " + (DateTime.Now - start).Milliseconds + " ms"); return result; }
private static BoundingBox GrowOnes(SxzPoint upperLeft, BoundingBox boundingBox, bool[,] boolArray) { SxzPoint lowerRight = new SxzPoint(upperLeft.X, upperLeft.Y); BoundingBox best = new BoundingBox(); best.UpperLeft = upperLeft; best.LowerRight = upperLeft; int maxX = boundingBox.LowerRight.X; int y = upperLeft.Y - 1; while ((y + 1) < (boundingBox.LowerRight.Y + 1) && boolArray[upperLeft.X, y + 1]) { y++; int x = upperLeft.X; while ((x + 1) <= maxX && boolArray[x + 1, y]) { x++; } maxX = x; BoundingBox candidate = new BoundingBox(); candidate.UpperLeft = upperLeft; candidate.LowerRight.X = x; candidate.LowerRight.Y = y; if (candidate.Area() > best.Area()) { best = candidate; } } return best; }