@flighthq/binpack 0.3.0-next.906.07cea63 → 0.3.1-next.209.43ef1bc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/contract.d.ts +1 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +1 -0
- package/dist/contract.js.map +1 -1
- package/dist/explainUnpackedRectangles.d.ts +3 -0
- package/dist/explainUnpackedRectangles.d.ts.map +1 -0
- package/dist/explainUnpackedRectangles.js +51 -0
- package/dist/explainUnpackedRectangles.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/packRectangles.d.ts +2 -0
- package/dist/packRectangles.d.ts.map +1 -1
- package/dist/packRectangles.js +62 -16
- package/dist/packRectangles.js.map +1 -1
- package/package.json +5 -3
- package/src/explainUnpackedRectangles.test.ts +56 -0
- package/src/packRectangles.test.ts +146 -7
package/dist/contract.d.ts
CHANGED
package/dist/contract.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kBAAkB,CAAC"}
|
package/dist/contract.js
CHANGED
package/dist/contract.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { BinPackOptions, PackableRectangle, UnpackedRectangleExplanation } from '@flighthq/types/contract';
|
|
2
|
+
export declare function explainUnpackedRectangles(rectangles: readonly Readonly<PackableRectangle>[], options?: Readonly<BinPackOptions>): UnpackedRectangleExplanation[];
|
|
3
|
+
//# sourceMappingURL=explainUnpackedRectangles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainUnpackedRectangles.d.ts","sourceRoot":"","sources":["../src/explainUnpackedRectangles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,4BAA4B,EAE7B,MAAM,0BAA0B,CAAC;AAalC,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,SAAS,QAAQ,CAAC,iBAAiB,CAAC,EAAE,EAClD,OAAO,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,GACjC,4BAA4B,EAAE,CAqBhC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { BIN_PACK_DEFAULT_MAX_EXTENT, packRectangles } from './packRectangles';
|
|
2
|
+
// Says WHY each unplaced rectangle did not fit. `packRectangles` reports `unpacked` as bare ids, which is
|
|
3
|
+
// the right shape for the hot path but tells a caller nothing about the remedy — and the three causes have
|
|
4
|
+
// three different ones: raise the cap, fix the border, or accept that the bin filled.
|
|
5
|
+
//
|
|
6
|
+
// Separately importable so the packer's own bundle pays nothing for it. It re-runs the pack rather than
|
|
7
|
+
// instrumenting it, which costs a second pass but keeps the packing loop free of reporting concerns and
|
|
8
|
+
// guarantees the explanation describes the same options the caller actually used.
|
|
9
|
+
//
|
|
10
|
+
// Returns an entry only for rectangles that failed; an all-placed input yields an empty array.
|
|
11
|
+
export function explainUnpackedRectangles(rectangles, options) {
|
|
12
|
+
const border = options?.border ?? 0;
|
|
13
|
+
const allowRotation = options?.allowRotation ?? false;
|
|
14
|
+
const usableWidth = (options?.maxWidth ?? BIN_PACK_DEFAULT_MAX_EXTENT) - 2 * border;
|
|
15
|
+
const usableHeight = (options?.maxHeight ?? BIN_PACK_DEFAULT_MAX_EXTENT) - 2 * border;
|
|
16
|
+
const result = packRectangles(rectangles, options);
|
|
17
|
+
if (result.unpacked.length === 0)
|
|
18
|
+
return [];
|
|
19
|
+
const unpacked = new Set(result.unpacked);
|
|
20
|
+
const explanations = [];
|
|
21
|
+
for (const rectangle of rectangles) {
|
|
22
|
+
if (!unpacked.has(rectangle.id))
|
|
23
|
+
continue;
|
|
24
|
+
explanations.push({
|
|
25
|
+
id: rectangle.id,
|
|
26
|
+
reason: getUnpackedReason(rectangle, usableWidth, usableHeight, allowRotation),
|
|
27
|
+
usableWidth,
|
|
28
|
+
usableHeight,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return explanations;
|
|
32
|
+
}
|
|
33
|
+
// Region collapse is checked before size, because when the usable region is non-positive EVERY rectangle
|
|
34
|
+
// fails for that one reason and reporting each as "oversized" would send the caller after the pieces
|
|
35
|
+
// instead of after the border.
|
|
36
|
+
function getUnpackedReason(rectangle, usableWidth, usableHeight, allowRotation) {
|
|
37
|
+
if (usableWidth <= 0 || usableHeight <= 0)
|
|
38
|
+
return 'regionCollapsed';
|
|
39
|
+
if (!fitsWithin(rectangle.width, rectangle.height, usableWidth, usableHeight)) {
|
|
40
|
+
if (!allowRotation)
|
|
41
|
+
return 'oversized';
|
|
42
|
+
// Rotation is a real second chance, so a piece is only oversized when NEITHER orientation fits.
|
|
43
|
+
if (!fitsWithin(rectangle.height, rectangle.width, usableWidth, usableHeight))
|
|
44
|
+
return 'oversized';
|
|
45
|
+
}
|
|
46
|
+
return 'binExhausted';
|
|
47
|
+
}
|
|
48
|
+
function fitsWithin(width, height, usableWidth, usableHeight) {
|
|
49
|
+
return width <= usableWidth && height <= usableHeight;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=explainUnpackedRectangles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainUnpackedRectangles.js","sourceRoot":"","sources":["../src/explainUnpackedRectangles.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,2BAA2B,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE/E,0GAA0G;AAC1G,2GAA2G;AAC3G,sFAAsF;AACtF,EAAE;AACF,wGAAwG;AACxG,wGAAwG;AACxG,kFAAkF;AAClF,EAAE;AACF,+FAA+F;AAC/F,MAAM,UAAU,yBAAyB,CACvC,UAAkD,EAClD,OAAkC;IAElC,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC;IACpC,MAAM,aAAa,GAAG,OAAO,EAAE,aAAa,IAAI,KAAK,CAAC;IACtD,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,QAAQ,IAAI,2BAA2B,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;IACpF,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,SAAS,IAAI,2BAA2B,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;IAEtF,MAAM,MAAM,GAAG,cAAc,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACnD,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE5C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAmC,EAAE,CAAC;IACxD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAAE,SAAS;QAC1C,YAAY,CAAC,IAAI,CAAC;YAChB,EAAE,EAAE,SAAS,CAAC,EAAE;YAChB,MAAM,EAAE,iBAAiB,CAAC,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,CAAC;YAC9E,WAAW;YACX,YAAY;SACb,CAAC,CAAC;IACL,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,yGAAyG;AACzG,qGAAqG;AACrG,+BAA+B;AAC/B,SAAS,iBAAiB,CACxB,SAAsC,EACtC,WAAmB,EACnB,YAAoB,EACpB,aAAsB;IAEtB,IAAI,WAAW,IAAI,CAAC,IAAI,YAAY,IAAI,CAAC;QAAE,OAAO,iBAAiB,CAAC;IACpE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,YAAY,CAAC,EAAE,CAAC;QAC9E,IAAI,CAAC,aAAa;YAAE,OAAO,WAAW,CAAC;QACvC,gGAAgG;QAChG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,CAAC;YAAE,OAAO,WAAW,CAAC;IACpG,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,SAAS,UAAU,CAAC,KAAa,EAAE,MAAc,EAAE,WAAmB,EAAE,YAAoB;IAC1F,OAAO,KAAK,IAAI,WAAW,IAAI,MAAM,IAAI,YAAY,CAAC;AACxD,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { packRectangles } from './contract';
|
|
1
|
+
export { explainUnpackedRectangles, getPackResultOccupancy, packRectangles } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { packRectangles } from './contract';
|
|
1
|
+
export { explainUnpackedRectangles, getPackResultOccupancy, packRectangles } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/packRectangles.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { BinPackOptions, PackableRectangle, PackResult } from '@flighthq/types/contract';
|
|
2
|
+
export declare function getPackResultOccupancy(result: Readonly<PackResult>): number;
|
|
2
3
|
export declare function packRectangles(rects: readonly Readonly<PackableRectangle>[], options?: Readonly<BinPackOptions>): PackResult;
|
|
4
|
+
export declare const BIN_PACK_DEFAULT_MAX_EXTENT = 16384;
|
|
3
5
|
//# sourceMappingURL=packRectangles.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packRectangles.d.ts","sourceRoot":"","sources":["../src/packRectangles.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EAEjB,UAAU,
|
|
1
|
+
{"version":3,"file":"packRectangles.d.ts","sourceRoot":"","sources":["../src/packRectangles.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EAEjB,UAAU,EAGX,MAAM,0BAA0B,CAAC;AAQlC,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,MAAM,CAM3E;AAiBD,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,QAAQ,CAAC,iBAAiB,CAAC,EAAE,EAC7C,OAAO,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,GACjC,UAAU,CAgFZ;AA6QD,eAAO,MAAM,2BAA2B,QAAQ,CAAC"}
|
package/dist/packRectangles.js
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import { intersectsRectangle } from '@flighthq/geometry/contract';
|
|
2
|
+
// Fraction of the reported bin actually covered by placements, in [0, 1]. Placed area over
|
|
3
|
+
// `width · height`; 0 for an empty or zero-extent result rather than NaN, since "nothing packed" is an
|
|
4
|
+
// expected outcome and not a division error the caller should have to guard.
|
|
5
|
+
//
|
|
6
|
+
// Measures the REPORTED extent, so power-of-two or square rounding shows up as the padding waste it is —
|
|
7
|
+
// which is usually the number a caller comparing packings wants to see.
|
|
8
|
+
export function getPackResultOccupancy(result) {
|
|
9
|
+
const area = result.width * result.height;
|
|
10
|
+
if (area <= 0)
|
|
11
|
+
return 0;
|
|
12
|
+
let placed = 0;
|
|
13
|
+
for (const placement of result.placements)
|
|
14
|
+
placed += placement.width * placement.height;
|
|
15
|
+
return placed / area;
|
|
16
|
+
}
|
|
2
17
|
// Places a set of rectangles without overlap into a bin using the MaxRects algorithm with the
|
|
3
18
|
// Best-Short-Side-Fit (BSSF) heuristic, and reports each placement, the used bin extent, and any ids
|
|
4
19
|
// that did not fit.
|
|
@@ -18,11 +33,12 @@ export function packRectangles(rects, options) {
|
|
|
18
33
|
const padding = options?.padding ?? 0;
|
|
19
34
|
const border = options?.border ?? 0;
|
|
20
35
|
const allowRotation = options?.allowRotation ?? false;
|
|
36
|
+
const heuristic = options?.heuristic ?? 'bestShortSideFit';
|
|
21
37
|
const growable = options?.growable ?? true;
|
|
22
38
|
const powerOfTwo = options?.powerOfTwo ?? false;
|
|
23
39
|
const square = options?.square ?? false;
|
|
24
|
-
const maxWidth = options?.maxWidth ??
|
|
25
|
-
const maxHeight = options?.maxHeight ??
|
|
40
|
+
const maxWidth = options?.maxWidth ?? BIN_PACK_DEFAULT_MAX_EXTENT;
|
|
41
|
+
const maxHeight = options?.maxHeight ?? BIN_PACK_DEFAULT_MAX_EXTENT;
|
|
26
42
|
if (rects.length === 0) {
|
|
27
43
|
return {
|
|
28
44
|
placements: [],
|
|
@@ -31,7 +47,27 @@ export function packRectangles(rects, options) {
|
|
|
31
47
|
unpacked: [],
|
|
32
48
|
};
|
|
33
49
|
}
|
|
34
|
-
|
|
50
|
+
// A rectangle with a non-positive side has no placeable area, and placing one produced real nonsense:
|
|
51
|
+
// a placement reporting `width: -8` that also overlapped its neighbour, because a negative extent
|
|
52
|
+
// consumes no space in the free-rectangle split. `unpacked` is the existing sentinel for "could not be
|
|
53
|
+
// placed", so degenerate input goes there rather than into the output as a malformed placement.
|
|
54
|
+
const degenerate = [];
|
|
55
|
+
const placeable = [];
|
|
56
|
+
for (const rect of rects) {
|
|
57
|
+
if (rect.width > 0 && rect.height > 0)
|
|
58
|
+
placeable.push(rect);
|
|
59
|
+
else
|
|
60
|
+
degenerate.push(rect.id);
|
|
61
|
+
}
|
|
62
|
+
if (placeable.length === 0) {
|
|
63
|
+
return {
|
|
64
|
+
placements: [],
|
|
65
|
+
width: finalizeExtent(0, powerOfTwo),
|
|
66
|
+
height: finalizeExtent(0, powerOfTwo),
|
|
67
|
+
unpacked: degenerate,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const sorted = sortRectanglesForPacking(placeable);
|
|
35
71
|
// The smallest bin each dimension must reach for a rectangle to fit at all, accounting for the
|
|
36
72
|
// border on both sides. A rectangle wider than `maxWidth` (and, if rotatable, taller than
|
|
37
73
|
// `maxHeight` in its other orientation) can never be placed and lands in `unpacked`.
|
|
@@ -51,7 +87,7 @@ export function packRectangles(rects, options) {
|
|
|
51
87
|
const seed = Math.ceil(Math.sqrt(totalArea)) + 2 * border;
|
|
52
88
|
let binWidth = growable ? Math.min(Math.max(seed, needWidth), maxWidth) : maxWidth;
|
|
53
89
|
let binHeight = growable ? Math.min(Math.max(seed, needHeight), maxHeight) : maxHeight;
|
|
54
|
-
let attempt = packIntoBin(sorted, binWidth, binHeight, padding, border, allowRotation);
|
|
90
|
+
let attempt = packIntoBin(sorted, binWidth, binHeight, padding, border, allowRotation, heuristic);
|
|
55
91
|
while (attempt.unpacked.length > 0 && growable && (binWidth < maxWidth || binHeight < maxHeight)) {
|
|
56
92
|
if (binWidth <= binHeight && binWidth < maxWidth) {
|
|
57
93
|
binWidth = Math.min(binWidth * 2, maxWidth);
|
|
@@ -62,9 +98,9 @@ export function packRectangles(rects, options) {
|
|
|
62
98
|
else {
|
|
63
99
|
binWidth = Math.min(binWidth * 2, maxWidth);
|
|
64
100
|
}
|
|
65
|
-
attempt = packIntoBin(sorted, binWidth, binHeight, padding, border, allowRotation);
|
|
101
|
+
attempt = packIntoBin(sorted, binWidth, binHeight, padding, border, allowRotation, heuristic);
|
|
66
102
|
}
|
|
67
|
-
return finalizeResult(attempt, border, powerOfTwo, square);
|
|
103
|
+
return finalizeResult({ placements: attempt.placements, unpacked: [...degenerate, ...attempt.unpacked] }, border, powerOfTwo, square);
|
|
68
104
|
}
|
|
69
105
|
// Rounds `value` up to the next power of two (>= 1). Used only for the final `powerOfTwo` adjustment.
|
|
70
106
|
function ceilToPowerOfTwo(value) {
|
|
@@ -98,7 +134,9 @@ function finalizeResult(packed, border, powerOfTwo, square) {
|
|
|
98
134
|
height = width;
|
|
99
135
|
}
|
|
100
136
|
return {
|
|
101
|
-
|
|
137
|
+
// packIntoBin builds this array fresh and never retains it, so copying the ARRAY is enough to hand
|
|
138
|
+
// the caller an owned, mutable list; cloning each placement object again was pure allocation slack.
|
|
139
|
+
placements: [...packed.placements],
|
|
102
140
|
width,
|
|
103
141
|
height,
|
|
104
142
|
unpacked: [...packed.unpacked],
|
|
@@ -115,10 +153,10 @@ function finalizeExtent(value, powerOfTwo) {
|
|
|
115
153
|
//
|
|
116
154
|
// `pieceWidth`/`pieceHeight` are the effective footprint (rectangle size plus the trailing padding
|
|
117
155
|
// gutter) in the unrotated orientation.
|
|
118
|
-
function findBestPlacement(free, pieceWidth, pieceHeight, allowRotation) {
|
|
156
|
+
function findBestPlacement(free, pieceWidth, pieceHeight, allowRotation, heuristic) {
|
|
119
157
|
let best = null;
|
|
120
|
-
let
|
|
121
|
-
let
|
|
158
|
+
let bestPrimary = Number.POSITIVE_INFINITY;
|
|
159
|
+
let bestSecondary = Number.POSITIVE_INFINITY;
|
|
122
160
|
for (const node of free) {
|
|
123
161
|
// Two candidate orientations: unrotated, then (optionally) the 90° turn.
|
|
124
162
|
for (let rotated = 0; rotated <= (allowRotation ? 1 : 0); rotated++) {
|
|
@@ -130,10 +168,15 @@ function findBestPlacement(free, pieceWidth, pieceHeight, allowRotation) {
|
|
|
130
168
|
const leftoverVertical = node.height - height;
|
|
131
169
|
const shortSide = Math.min(leftoverHorizontal, leftoverVertical);
|
|
132
170
|
const longSide = Math.max(leftoverHorizontal, leftoverVertical);
|
|
133
|
-
|
|
171
|
+
// Both heuristics rank on a primary score and break ties on a secondary one; only which is which
|
|
172
|
+
// differs. Area-fit still falls back to the short side, so a tie in leftover area resolves the same
|
|
173
|
+
// way short-side-fit would rather than by free-rectangle order alone.
|
|
174
|
+
const primary = heuristic === 'bestAreaFit' ? node.width * node.height - width * height : shortSide;
|
|
175
|
+
const secondary = heuristic === 'bestAreaFit' ? shortSide : longSide;
|
|
176
|
+
if (best === null || primary < bestPrimary || (primary === bestPrimary && secondary < bestSecondary)) {
|
|
134
177
|
best = { x: node.x, y: node.y, footprintWidth: width, footprintHeight: height, rotated: rotated === 1 };
|
|
135
|
-
|
|
136
|
-
|
|
178
|
+
bestPrimary = primary;
|
|
179
|
+
bestSecondary = secondary;
|
|
137
180
|
}
|
|
138
181
|
}
|
|
139
182
|
}
|
|
@@ -153,7 +196,7 @@ function isFreeRectangleContained(inner, outer) {
|
|
|
153
196
|
// `(binWidth - 2*border + padding) x (binHeight - 2*border + padding)`. This construction makes the
|
|
154
197
|
// actual placement satisfy `x >= border` and `x + width <= binWidth - border` (likewise vertically),
|
|
155
198
|
// so `border` is respected on every side while the last row/column's gutter costs no real space.
|
|
156
|
-
function packIntoBin(sorted, binWidth, binHeight, padding, border, allowRotation) {
|
|
199
|
+
function packIntoBin(sorted, binWidth, binHeight, padding, border, allowRotation, heuristic) {
|
|
157
200
|
const usableWidth = binWidth - 2 * border + padding;
|
|
158
201
|
const usableHeight = binHeight - 2 * border + padding;
|
|
159
202
|
const placements = [];
|
|
@@ -167,7 +210,7 @@ function packIntoBin(sorted, binWidth, binHeight, padding, border, allowRotation
|
|
|
167
210
|
for (const rect of sorted) {
|
|
168
211
|
const pieceWidth = rect.width + padding;
|
|
169
212
|
const pieceHeight = rect.height + padding;
|
|
170
|
-
const placement = findBestPlacement(free, pieceWidth, pieceHeight, allowRotation);
|
|
213
|
+
const placement = findBestPlacement(free, pieceWidth, pieceHeight, allowRotation, heuristic);
|
|
171
214
|
if (placement === null) {
|
|
172
215
|
unpacked.push(rect.id);
|
|
173
216
|
continue;
|
|
@@ -265,5 +308,8 @@ function compareRectangleId(a, b) {
|
|
|
265
308
|
}
|
|
266
309
|
// The default width/height cap when `maxWidth`/`maxHeight` are unset — large enough to be effectively
|
|
267
310
|
// unbounded for typical inputs while keeping growth from running away.
|
|
268
|
-
|
|
311
|
+
// The cap applied when the caller names none — large enough to read as "unbounded" for typical inputs
|
|
312
|
+
// while still bounding the growth loop. Exported because a caller computing its own usable region (or
|
|
313
|
+
// explaining a failure) must use the same number the packer did.
|
|
314
|
+
export const BIN_PACK_DEFAULT_MAX_EXTENT = 16384;
|
|
269
315
|
//# sourceMappingURL=packRectangles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packRectangles.js","sourceRoot":"","sources":["../src/packRectangles.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"packRectangles.js","sourceRoot":"","sources":["../src/packRectangles.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/binpack",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1-next.209.43ef1bc",
|
|
4
|
+
"author": "Joshua Granick and other contributors",
|
|
5
|
+
"license": "MIT",
|
|
4
6
|
"repository": {
|
|
5
7
|
"type": "git",
|
|
6
8
|
"url": "https://github.com/flighthq/flight.git",
|
|
@@ -36,8 +38,8 @@
|
|
|
36
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
37
39
|
},
|
|
38
40
|
"dependencies": {
|
|
39
|
-
"@flighthq/geometry": "0.3.
|
|
40
|
-
"@flighthq/types": "0.3.
|
|
41
|
+
"@flighthq/geometry": "0.3.1-next.209.43ef1bc",
|
|
42
|
+
"@flighthq/types": "0.3.1-next.209.43ef1bc"
|
|
41
43
|
},
|
|
42
44
|
"devDependencies": {
|
|
43
45
|
"typescript": "^5.3.0"
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { explainUnpackedRectangles } from './explainUnpackedRectangles';
|
|
4
|
+
|
|
5
|
+
describe('explainUnpackedRectangles', () => {
|
|
6
|
+
it('returns nothing when everything was placed', () => {
|
|
7
|
+
expect(explainUnpackedRectangles([{ id: 'a', width: 8, height: 8 }])).toEqual([]);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('separates oversized from binExhausted, which have different remedies', () => {
|
|
11
|
+
// 'huge' can never fit any bin within the caps; 'filler' fits in principle and loses the race.
|
|
12
|
+
const explanations = explainUnpackedRectangles(
|
|
13
|
+
[
|
|
14
|
+
{ id: 'huge', width: 500, height: 10 },
|
|
15
|
+
{ id: 'filler', width: 90, height: 90 },
|
|
16
|
+
{ id: 'filler2', width: 90, height: 90 },
|
|
17
|
+
],
|
|
18
|
+
{ maxWidth: 100, maxHeight: 100, growable: false },
|
|
19
|
+
);
|
|
20
|
+
const byId = new Map(explanations.map((e) => [e.id, e.reason]));
|
|
21
|
+
expect(byId.get('huge')).toBe('oversized');
|
|
22
|
+
expect(byId.get('filler2')).toBe('binExhausted');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('blames the collapsed region rather than the pieces when border eats the caps', () => {
|
|
26
|
+
// Every piece fails for ONE reason here; calling each 'oversized' would send the caller after the
|
|
27
|
+
// rectangles instead of after the border.
|
|
28
|
+
const explanations = explainUnpackedRectangles(
|
|
29
|
+
[
|
|
30
|
+
{ id: 'a', width: 2, height: 2 },
|
|
31
|
+
{ id: 'b', width: 2, height: 2 },
|
|
32
|
+
],
|
|
33
|
+
{ maxWidth: 10, maxHeight: 10, border: 6, growable: false },
|
|
34
|
+
);
|
|
35
|
+
expect(explanations.map((e) => e.reason)).toEqual(['regionCollapsed', 'regionCollapsed']);
|
|
36
|
+
expect(explanations[0].usableWidth).toBeLessThanOrEqual(0);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('counts rotation as a real second chance before calling a piece oversized', () => {
|
|
40
|
+
const rects = [{ id: 'tall', width: 10, height: 200 }];
|
|
41
|
+
const options = { maxWidth: 300, maxHeight: 100, growable: false } as const;
|
|
42
|
+
expect(explainUnpackedRectangles(rects, options)[0].reason).toBe('oversized');
|
|
43
|
+
// Rotated it is 200x10, which fits inside 300x100 — so it is not oversized, it merely lost.
|
|
44
|
+
expect(explainUnpackedRectangles(rects, { ...options, allowRotation: true })).toEqual([]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('reports the usable extent it measured against, net of border', () => {
|
|
48
|
+
const [explanation] = explainUnpackedRectangles([{ id: 'a', width: 999, height: 4 }], {
|
|
49
|
+
maxWidth: 100,
|
|
50
|
+
maxHeight: 100,
|
|
51
|
+
border: 5,
|
|
52
|
+
growable: false,
|
|
53
|
+
});
|
|
54
|
+
expect(explanation).toMatchObject({ id: 'a', usableWidth: 90, usableHeight: 90 });
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -1,7 +1,42 @@
|
|
|
1
1
|
import type { PackableRectangle, PackedRectangle } from '@flighthq/types/contract';
|
|
2
2
|
import { describe, expect, it } from 'vitest';
|
|
3
3
|
|
|
4
|
-
import { packRectangles } from './packRectangles';
|
|
4
|
+
import { BIN_PACK_DEFAULT_MAX_EXTENT, getPackResultOccupancy, packRectangles } from './packRectangles';
|
|
5
|
+
|
|
6
|
+
describe('BIN_PACK_DEFAULT_MAX_EXTENT', () => {
|
|
7
|
+
it('is the cap the packer actually applies when the caller names none', () => {
|
|
8
|
+
// A rectangle one unit past the default must not fit; one exactly at it must.
|
|
9
|
+
expect(packRectangles([{ id: 'over', width: BIN_PACK_DEFAULT_MAX_EXTENT + 1, height: 4 }]).unpacked).toEqual([
|
|
10
|
+
'over',
|
|
11
|
+
]);
|
|
12
|
+
expect(packRectangles([{ id: 'at', width: BIN_PACK_DEFAULT_MAX_EXTENT, height: 4 }]).unpacked).toEqual([]);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
function isPowerOfTwo(value: number): boolean {
|
|
17
|
+
return value > 0 && (value & (value - 1)) === 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function rectanglesOverlap(a: Readonly<PackedRectangle>, b: Readonly<PackedRectangle>): boolean {
|
|
21
|
+
return !(a.x + a.width <= b.x || b.x + b.width <= a.x || a.y + a.height <= b.y || b.y + b.height <= a.y);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
describe('getPackResultOccupancy', () => {
|
|
25
|
+
it('reports covered fraction of the REPORTED extent, so rounding waste is visible', () => {
|
|
26
|
+
const exact = packRectangles([{ id: 'a', width: 16, height: 16 }]);
|
|
27
|
+
expect(getPackResultOccupancy(exact)).toBe(1);
|
|
28
|
+
// powerOfTwo rounds 24 up to 32, and the occupancy must show that as waste rather than hide it.
|
|
29
|
+
const rounded = packRectangles([{ id: 'a', width: 24, height: 24 }], { powerOfTwo: true });
|
|
30
|
+
expect(rounded.width).toBe(32);
|
|
31
|
+
expect(getPackResultOccupancy(rounded)).toBeCloseTo((24 * 24) / (32 * 32), 10);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('returns 0 rather than NaN for an empty result, since nothing-packed is expected', () => {
|
|
35
|
+
const empty = packRectangles([]);
|
|
36
|
+
expect(empty.width * empty.height).toBe(0);
|
|
37
|
+
expect(getPackResultOccupancy(empty)).toBe(0);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
5
40
|
|
|
6
41
|
describe('packRectangles', () => {
|
|
7
42
|
it('places ~20 varied rectangles with no pairwise overlap, inside the bin, at their input size', () => {
|
|
@@ -180,10 +215,114 @@ describe('packRectangles', () => {
|
|
|
180
215
|
});
|
|
181
216
|
});
|
|
182
217
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
218
|
+
describe('packRectangles edge cases', () => {
|
|
219
|
+
it('rejects zero and negative dimensions to unpacked rather than placing a degenerate rect', () => {
|
|
220
|
+
const result = packRectangles([
|
|
221
|
+
{ id: 'zeroW', width: 0, height: 10 },
|
|
222
|
+
{ id: 'zeroH', width: 10, height: 0 },
|
|
223
|
+
{ id: 'negative', width: -8, height: 10 },
|
|
224
|
+
{ id: 'ok', width: 10, height: 10 },
|
|
225
|
+
]);
|
|
226
|
+
expect(result.placements.map((p) => p.id)).toEqual(['ok']);
|
|
227
|
+
expect([...result.unpacked].sort()).toEqual(['negative', 'zeroH', 'zeroW']);
|
|
228
|
+
});
|
|
186
229
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
230
|
+
it('treats duplicate ids as distinct rectangles, placing both without overlap', () => {
|
|
231
|
+
const result = packRectangles([
|
|
232
|
+
{ id: 'same', width: 10, height: 10 },
|
|
233
|
+
{ id: 'same', width: 10, height: 10 },
|
|
234
|
+
]);
|
|
235
|
+
expect(result.placements).toHaveLength(2);
|
|
236
|
+
const [a, b] = result.placements;
|
|
237
|
+
expect(a.x !== b.x || a.y !== b.y).toBe(true);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('places non-integer sizes without rounding them', () => {
|
|
241
|
+
const result = packRectangles([{ id: 'frac', width: 10.5, height: 4.25 }]);
|
|
242
|
+
expect(result.placements[0]).toMatchObject({ width: 10.5, height: 4.25 });
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('sends everything to unpacked when border collapses the usable region', () => {
|
|
246
|
+
const result = packRectangles([{ id: 'a', width: 4, height: 4 }], {
|
|
247
|
+
maxWidth: 10,
|
|
248
|
+
maxHeight: 10,
|
|
249
|
+
border: 6, // 2*6 = 12 > 10, so there is no usable region at all
|
|
250
|
+
growable: false,
|
|
251
|
+
});
|
|
252
|
+
expect(result.placements).toEqual([]);
|
|
253
|
+
expect(result.unpacked).toEqual(['a']);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it('keeps padding larger than the pieces from overlapping them', () => {
|
|
257
|
+
const result = packRectangles(
|
|
258
|
+
[
|
|
259
|
+
{ id: 'a', width: 2, height: 2 },
|
|
260
|
+
{ id: 'b', width: 2, height: 2 },
|
|
261
|
+
],
|
|
262
|
+
{ padding: 20 },
|
|
263
|
+
);
|
|
264
|
+
expect(result.placements).toHaveLength(2);
|
|
265
|
+
const [a, b] = result.placements;
|
|
266
|
+
const gapX = Math.abs(a.x - b.x) >= 2 + 20;
|
|
267
|
+
const gapY = Math.abs(a.y - b.y) >= 2 + 20;
|
|
268
|
+
expect(gapX || gapY).toBe(true);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
describe('packRectangles properties', () => {
|
|
273
|
+
// Deterministic LCG: seeded so a failure is reproducible from the seed alone, and no Math.random —
|
|
274
|
+
// which the portability gate forbids and which would make a red run unreproducible anyway.
|
|
275
|
+
function makeRandom(seed: number): () => number {
|
|
276
|
+
let state = seed >>> 0;
|
|
277
|
+
return () => {
|
|
278
|
+
state = (state * 1664525 + 1013904223) >>> 0;
|
|
279
|
+
return state / 0x100000000;
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
it('holds its invariants across 40 seeded inputs and both heuristics', () => {
|
|
284
|
+
for (let seed = 1; seed <= 40; seed++) {
|
|
285
|
+
const random = makeRandom(seed);
|
|
286
|
+
const count = 1 + Math.floor(random() * 25);
|
|
287
|
+
const rects: PackableRectangle[] = [];
|
|
288
|
+
for (let i = 0; i < count; i++) {
|
|
289
|
+
rects.push({ id: i, width: 1 + Math.floor(random() * 60), height: 1 + Math.floor(random() * 60) });
|
|
290
|
+
}
|
|
291
|
+
const padding = Math.floor(random() * 4);
|
|
292
|
+
const border = Math.floor(random() * 4);
|
|
293
|
+
const heuristic = seed % 2 === 0 ? 'bestAreaFit' : 'bestShortSideFit';
|
|
294
|
+
const options = { padding, border, heuristic, allowRotation: seed % 3 === 0 } as const;
|
|
295
|
+
|
|
296
|
+
const result = packRectangles(rects, options);
|
|
297
|
+
const label = `seed ${seed} (${heuristic})`;
|
|
298
|
+
|
|
299
|
+
// Every input is accounted for exactly once.
|
|
300
|
+
expect(result.placements.length + result.unpacked.length, label).toBe(rects.length);
|
|
301
|
+
|
|
302
|
+
for (const placement of result.placements) {
|
|
303
|
+
// Inside the bin, honouring the border on every side.
|
|
304
|
+
expect(placement.x >= border, label).toBe(true);
|
|
305
|
+
expect(placement.y >= border, label).toBe(true);
|
|
306
|
+
expect(placement.x + placement.width <= result.width - border, label).toBe(true);
|
|
307
|
+
expect(placement.y + placement.height <= result.height - border, label).toBe(true);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Pairwise non-overlap, with padding respected as a real gap.
|
|
311
|
+
for (let i = 0; i < result.placements.length; i++) {
|
|
312
|
+
for (let j = i + 1; j < result.placements.length; j++) {
|
|
313
|
+
const a = result.placements[i];
|
|
314
|
+
const b = result.placements[j];
|
|
315
|
+
const apart =
|
|
316
|
+
a.x + a.width + padding <= b.x ||
|
|
317
|
+
b.x + b.width + padding <= a.x ||
|
|
318
|
+
a.y + a.height + padding <= b.y ||
|
|
319
|
+
b.y + b.height + padding <= a.y;
|
|
320
|
+
expect(apart, `${label}: ${String(a.id)} vs ${String(b.id)}`).toBe(true);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Deterministic: the same input re-packs identically.
|
|
325
|
+
expect(packRectangles(rects, options), label).toEqual(result);
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
});
|