private void filterSelfSubAreas(List <IntegerRectangle> areas) { for (int i = areas.Count - 1; i >= 0; i--) { IntegerRectangle filtered = areas[i]; for (int j = areas.Count - 1; j >= 0; j--) { if (i != j) { IntegerRectangle area = areas[j]; if (filtered.x >= area.x && filtered.y >= area.y && filtered.right <= area.right && filtered.bottom <= area.bottom) { freeRectangle(filtered); IntegerRectangle topOfStack = areas.Pop(); if (i < areas.Count) { // Move the one on the top to the freed position areas[i] = topOfStack; } break; } } } } }
public IntegerRectangle getRectangle(int index, IntegerRectangle rectangle) { IntegerRectangle inserted = mInsertedRectangles[index]; rectangle.x = inserted.x; rectangle.y = inserted.y; rectangle.width = inserted.width; rectangle.height = inserted.height; return(rectangle); }
private IntegerRectangle allocateRectangle(int x, int y, int width, int height) { if (mRectangleStack.Count > 0) { IntegerRectangle rectangle = mRectangleStack.Pop(); rectangle.x = x; rectangle.y = y; rectangle.width = width; rectangle.height = height; rectangle.right = x + width; rectangle.bottom = y + height; return(rectangle); } return(new IntegerRectangle(x, y, width, height)); }
private void generateDividedAreas(IntegerRectangle divider, IntegerRectangle area, List <IntegerRectangle> results) { int count = 0; int rightDelta = area.right - divider.right; if (rightDelta > 0) { results.Add(allocateRectangle(divider.right, area.y, rightDelta, area.height)); count++; } int leftDelta = divider.x - area.x; if (leftDelta > 0) { results.Add(allocateRectangle(area.x, area.y, leftDelta, area.height)); count++; } int bottomDelta = area.bottom - divider.bottom; if (bottomDelta > 0) { results.Add(allocateRectangle(area.x, divider.bottom, area.width, bottomDelta)); count++; } int topDelta = divider.y - area.y; if (topDelta > 0) { results.Add(allocateRectangle(area.x, area.y, area.width, topDelta)); count++; } if (count == 0 && (divider.width < area.width || divider.height < area.height)) { // Only touching the area, store the area itself results.Add(area); } else { freeRectangle(area); } }
public int packRectangles(bool sort = true) { if (sort) { mInsertList.Sort((emp1, emp2) => emp1.width.CompareTo(emp2.width)); } while (mInsertList.Count > 0) { SortableSize sortableSize = mInsertList.Pop(); int width = sortableSize.width; int height = sortableSize.height; int index = getFreeAreaIndex(width, height); if (index >= 0) { IntegerRectangle freeArea = mFreeAreas[index]; IntegerRectangle target = allocateRectangle(freeArea.x, freeArea.y, width, height); target.id = sortableSize.id; // Generate the new free areas, these are parts of the old ones intersected or touched by the target generateNewFreeAreas(target, mFreeAreas, mNewFreeAreas); while (mNewFreeAreas.Count > 0) { mFreeAreas.Add(mNewFreeAreas.Pop()); } mInsertedRectangles.Add(target); if (target.right > mPackedWidth) { mPackedWidth = target.right; } if (target.bottom > mPackedHeight) { mPackedHeight = target.bottom; } } freeSize(sortableSize); } return(rectangleCount); }
private int getFreeAreaIndex(int width, int height) { IntegerRectangle best = mOutsideRectangle; int index = -1; int paddedWidth = width + mPadding; int paddedHeight = height + mPadding; int count = mFreeAreas.Count; for (int i = count - 1; i >= 0; i--) { IntegerRectangle free = mFreeAreas[i]; if (free.x < mPackedWidth || free.y < mPackedHeight) { // Within the packed area, padding required if (free.x < best.x && paddedWidth <= free.width && paddedHeight <= free.height) { index = i; if ((paddedWidth == free.width && free.width <= free.height && free.right < mWidth) || (paddedHeight == free.height && free.height <= free.width)) { break; } best = free; } } else { // Outside the current packed area, no padding required if (free.x < best.x && width <= free.width && height <= free.height) { index = i; if ((width == free.width && free.width <= free.height && free.right < mWidth) || (height == free.height && free.height <= free.width)) { break; } best = free; } } } return(index); }
private void generateNewFreeAreas(IntegerRectangle target, List <IntegerRectangle> areas, List <IntegerRectangle> results) { // Increase dimensions by one to get the areas on right / bottom this rectangle touches // Also add the padding here int x = target.x; int y = target.y; int right = target.right + 1 + mPadding; int bottom = target.bottom + 1 + mPadding; IntegerRectangle targetWithPadding = null; if (mPadding == 0) { targetWithPadding = target; } for (int i = areas.Count - 1; i >= 0; i--) { IntegerRectangle area = areas[i]; if (!(x >= area.right || right <= area.x || y >= area.bottom || bottom <= area.y)) { if (targetWithPadding == null) { targetWithPadding = allocateRectangle(target.x, target.y, target.width + mPadding, target.height + mPadding); } generateDividedAreas(targetWithPadding, area, results); IntegerRectangle topOfStack = areas.Pop(); if (i < areas.Count) { // Move the one on the top to the freed position areas[i] = topOfStack; } } } if (targetWithPadding != null && targetWithPadding != target) { freeRectangle(targetWithPadding); } filterSelfSubAreas(results); }
private void freeRectangle(IntegerRectangle rectangle) { mRectangleStack.Add(rectangle); }
public int getRectangleId(int index) { IntegerRectangle inserted = mInsertedRectangles[index]; return(inserted.id); }