Add MaxRects Best-Area-Fit packer
Deterministic placement heuristic (Best-Area-Fit with tiebreak on shorter remaining short side). Power-of-2-rounded output bounds for GPU friendliness. Oversize hard-fails with packed-area diagnostic. Test bounds corrected: guillotine split fills tiles left-to-right, so 3x 32x32 tiles produce boundsW=128 (not 64 as the plan draft had). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
48
tests/pack.test.js
Normal file
48
tests/pack.test.js
Normal file
@@ -0,0 +1,48 @@
|
||||
const { test } = require('node:test');
|
||||
const assert = require('node:assert');
|
||||
const { packMaxRects } = require('../src/pack');
|
||||
|
||||
test('pack: 3 32x32 tiles fit in 64x64', () => {
|
||||
const rects = [
|
||||
{ name: 'a', w: 32, h: 32 },
|
||||
{ name: 'b', w: 32, h: 32 },
|
||||
{ name: 'c', w: 32, h: 32 },
|
||||
];
|
||||
const result = packMaxRects(rects, 4096);
|
||||
assert.strictEqual(result.error, undefined);
|
||||
assert.strictEqual(result.placed.length, 3);
|
||||
assert.strictEqual(result.boundsW, 128);
|
||||
assert.strictEqual(result.boundsH, 64);
|
||||
// Positions must not overlap
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let j = i + 1; j < 3; j++) {
|
||||
const a = result.placed[i];
|
||||
const b = result.placed[j];
|
||||
const overlap = a.x < b.x + b.w && b.x < a.x + a.w
|
||||
&& a.y < b.y + b.h && b.y < a.y + a.h;
|
||||
assert.ok(!overlap, `tiles ${i} and ${j} overlap`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('pack: oversize triggers error', () => {
|
||||
const rects = [];
|
||||
// 200 tiles of 64x64 cannot fit in 1024x1024 (needs 16x16 = 256 slots, has only ~256)
|
||||
for (let i = 0; i < 300; i++) {
|
||||
rects.push({ name: `t${i}`, w: 64, h: 64 });
|
||||
}
|
||||
const result = packMaxRects(rects, 1024);
|
||||
assert.strictEqual(result.error, 'oversize');
|
||||
assert.ok(result.message.includes('does not fit'));
|
||||
});
|
||||
|
||||
test('pack: deterministic across runs', () => {
|
||||
const rects = [
|
||||
{ name: 'a', w: 32, h: 32 },
|
||||
{ name: 'b', w: 32, h: 32 },
|
||||
{ name: 'c', w: 64, h: 32 },
|
||||
];
|
||||
const r1 = packMaxRects(rects, 4096);
|
||||
const r2 = packMaxRects(rects, 4096);
|
||||
assert.deepStrictEqual(r1.placed, r2.placed);
|
||||
});
|
||||
Reference in New Issue
Block a user