/// <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; }
/// <summary> /// To return a RectangleChunk we will need the bounding box and a check for missing locations /// </summary> /// <returns></returns> public override HashSet<ChunkContainer> GetChunks(LocationPool locationPool) { HashSet<ChunkContainer> result = new HashSet<ChunkContainer>(); if (IsRectangle()) { MonoRectangleChunk rectangleChunk = new MonoRectangleChunk(); rectangleChunk.Origin = BoundingBox.UpperLeft; rectangleChunk.Width = BoundingBox.Width(); rectangleChunk.Height = BoundingBox.Height(); MonoRectangleChunkContainer container = new MonoRectangleChunkContainer(); container.Chunk = rectangleChunk; container.Locations = GetLocations(BoundingBox); //container.AdditionalSize = NewColorCount(locationPool.Palette); container.Color = Color; result.Add(container); return result; } //break up into many rectangles and return rest here HashSet<Location> locations = new HashSet<Location>(Locations); HashSet<BoundingBox> rectangles = GetAllRectangles(locations, BoundingBox); foreach (BoundingBox rectangle in rectangles) { MonoRectangleChunk rectangleChunk = new MonoRectangleChunk(); rectangleChunk.Origin = rectangle.UpperLeft; rectangleChunk.Width = rectangle.Width(); rectangleChunk.Height = rectangle.Height(); MonoRectangleChunkContainer container = new MonoRectangleChunkContainer(); container.Chunk = rectangleChunk; container.Color = Color; //container.AdditionalSize = NewColorCount(locationPool.Palette); container.Locations = GetLocations(rectangle); result.Add(container); } //now for the remaining locations, create monocolorchunks BoundingBox remaining = new BoundingBox(); foreach (Location location in locations) { remaining.Add(location.Point); } MonoBitPlaneChunk monoColorChunk = new MonoBitPlaneChunk(); monoColorChunk.Width = remaining.Width(); monoColorChunk.Height = remaining.Height(); monoColorChunk.Initialize(); monoColorChunk.Origin = remaining.UpperLeft; foreach (Location location in locations) { monoColorChunk.SetColor(location.Point.X, location.Point.Y); } MonoBitPlaneChunkContainer monoContainer = new MonoBitPlaneChunkContainer(); monoContainer.Chunk = monoColorChunk; monoContainer.Locations = GetLocations(remaining); monoContainer.Color = Color; result.Add(monoContainer); return result; }
public HashSet<Location> GetUnmarkedByBoundingBox(BoundingBox boundingBox) { HashSet<Location> result = new HashSet<Location>(); foreach (Location location in Unmarked) { if (boundingBox.Contains(location.Point.X, location.Point.Y)) { result.Add(location); } } return result; }
public BoundingBox(BoundingBox input) { UpperLeft = new SxzPoint(input.UpperLeft.X, input.UpperLeft.Y); LowerRight = new SxzPoint(input.LowerRight.X, input.LowerRight.Y); }
public Region() { Locations = new HashSet<Location>(); BoundingBox = new BoundingBox(); }
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; }
public bool IsRectangle(HashSet<Location> locations, BoundingBox boundingBox) { bool[,] boolArray = new bool[boundingBox.Width(), boundingBox.Height()]; foreach (Location location in locations) { if (boundingBox.Contains(location.Point.X, location.Point.Y)) { boolArray[location.Point.X - boundingBox.UpperLeft.X, location.Point.Y - boundingBox.UpperLeft.Y] = true; } } for (int x = 0; x < boolArray.GetLength(0); x++) { for (int y = 0; y < boolArray.GetLength(1); y++) { if (!boolArray[x, y]) { return false; } } } return true; }