/** For each rectangle, packs each one then chooses the best and packs that. Slow! */ public Page pack(Array<Rect> rects, FreeRectChoiceHeuristic method) { rects = new Array(rects); while (rects.size > 0) { int bestRectIndex = -1; Rect bestNode = new Rect(); bestNode.score1 = Integer.MAX_VALUE; bestNode.score2 = Integer.MAX_VALUE; // Find the next rectangle that packs best. for (int i = 0; i < rects.size; i++) { Rect newNode = scoreRect(rects.get(i), method); if (newNode.score1 < bestNode.score1 || (newNode.score1 == bestNode.score1 && newNode.score2 < bestNode.score2)) { bestNode.set(rects.get(i)); bestNode.score1 = newNode.score1; bestNode.score2 = newNode.score2; bestNode.x = newNode.x; bestNode.y = newNode.y; bestNode.width = newNode.width; bestNode.height = newNode.height; bestNode.rotated = newNode.rotated; bestRectIndex = i; } } if (bestRectIndex == -1) break; placeRect(bestNode); rects.removeIndex(bestRectIndex); } Page result = getResult(); result.remainingRects = rects; return result; }
public Page getResult() { int w = 0, h = 0; for (int i = 0; i < usedRectangles.size; i++) { Rect rect = usedRectangles.get(i); w = Math.max(w, rect.x + rect.width); h = Math.max(h, rect.y + rect.height); } Page result = new Page(); result.outputRects = new Array(usedRectangles); result.occupancy = getOccupancy(); result.width = w; result.height = h; return result; }
/** * @param fully If true, the only results that pack all rects will be considered. If false, all * results are considered, not all rects may be packed. */ private Page packAtSize(boolean fully, int width, int height, Array<Rect> inputRects) { Page bestResult = null; for (int i = 0, n = methods.length; i < n; i++) { maxRects.init(width, height); Page result; if (!settings.fast) { result = maxRects.pack(inputRects, methods[i]); } else { Array<Rect> remaining = new Array(); for (int ii = 0, nn = inputRects.size; ii < nn; ii++) { Rect rect = inputRects.get(ii); if (maxRects.insert(rect, methods[i]) == null) { while (ii < nn) remaining.add(inputRects.get(ii++)); } } result = maxRects.getResult(); result.remainingRects = remaining; } if (fully && result.remainingRects.size > 0) continue; if (result.outputRects.size == 0) continue; bestResult = getBest(bestResult, result); } return bestResult; }
private Page packPage(Array<Rect> inputRects) { int edgePaddingX = 0, edgePaddingY = 0; if (!settings.duplicatePadding) { // if duplicatePadding, edges get only half padding. edgePaddingX = settings.paddingX; edgePaddingY = settings.paddingY; } // Find min size. int minWidth = Integer.MAX_VALUE; int minHeight = Integer.MAX_VALUE; for (int i = 0, nn = inputRects.size; i < nn; i++) { Rect rect = inputRects.get(i); minWidth = Math.min(minWidth, rect.width); minHeight = Math.min(minHeight, rect.height); if (settings.rotation) { if ((rect.width > settings.maxWidth || rect.height > settings.maxHeight) && (rect.width > settings.maxHeight || rect.height > settings.maxWidth)) { throw new RuntimeException( "Image does not fit with max page size " + settings.maxWidth + "x" + settings.maxHeight + " and padding " + settings.paddingX + "," + settings.paddingY + ": " + rect); } } else { if (rect.width > settings.maxWidth) { throw new RuntimeException( "Image does not fit with max page width " + settings.maxWidth + " and paddingX " + settings.paddingX + ": " + rect); } if (rect.height > settings.maxHeight && (!settings.rotation || rect.width > settings.maxHeight)) { throw new RuntimeException( "Image does not fit in max page height " + settings.maxHeight + " and paddingY " + settings.paddingY + ": " + rect); } } } minWidth = Math.max(minWidth, settings.minWidth); minHeight = Math.max(minHeight, settings.minHeight); if (!settings.silent) System.out.print("Packing"); // Find the minimal page size that fits all rects. Page bestResult = null; if (settings.square) { int minSize = Math.max(minWidth, minHeight); int maxSize = Math.min(settings.maxWidth, settings.maxHeight); BinarySearch sizeSearch = new BinarySearch(minSize, maxSize, settings.fast ? 25 : 15, settings.pot); int size = sizeSearch.reset(), i = 0; while (size != -1) { Page result = packAtSize(true, size - edgePaddingX, size - edgePaddingY, inputRects); if (!settings.silent) { if (++i % 70 == 0) System.out.println(); System.out.print("."); } bestResult = getBest(bestResult, result); size = sizeSearch.next(result == null); } if (!settings.silent) System.out.println(); // Rects don't fit on one page. Fill a whole page and return. if (bestResult == null) bestResult = packAtSize(false, maxSize - edgePaddingX, maxSize - edgePaddingY, inputRects); sort.sort(bestResult.outputRects, rectComparator); bestResult.width = Math.max(bestResult.width, bestResult.height); bestResult.height = Math.max(bestResult.width, bestResult.height); return bestResult; } else { BinarySearch widthSearch = new BinarySearch(minWidth, settings.maxWidth, settings.fast ? 25 : 15, settings.pot); BinarySearch heightSearch = new BinarySearch(minHeight, settings.maxHeight, settings.fast ? 25 : 15, settings.pot); int width = widthSearch.reset(), i = 0; int height = settings.square ? width : heightSearch.reset(); while (true) { Page bestWidthResult = null; while (width != -1) { Page result = packAtSize(true, width - edgePaddingX, height - edgePaddingY, inputRects); if (!settings.silent) { if (++i % 70 == 0) System.out.println(); System.out.print("."); } bestWidthResult = getBest(bestWidthResult, result); width = widthSearch.next(result == null); if (settings.square) height = width; } bestResult = getBest(bestResult, bestWidthResult); if (settings.square) break; height = heightSearch.next(bestWidthResult == null); if (height == -1) break; width = widthSearch.reset(); } if (!settings.silent) System.out.println(); // Rects don't fit on one page. Fill a whole page and return. if (bestResult == null) bestResult = packAtSize( false, settings.maxWidth - edgePaddingX, settings.maxHeight - edgePaddingY, inputRects); sort.sort(bestResult.outputRects, rectComparator); return bestResult; } }