daika7ana/smallest-box

Calculate the smallest rectangular box (W x L x H) that fits a set of rectangular items, using axis-aligned 3D bin packing with rotation support.

Maintainers

Package info

github.com/daika7ana/smallest-box

pkg:composer/daika7ana/smallest-box

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-05-30 18:38 UTC

This package is auto-updated.

Last update: 2026-05-30 18:44:53 UTC


README

CI PHP 7.4+ PHPUnit PHPStan License

Calculate the smallest rectangular box that fits a set of rectangular items, using axis-aligned 3D bin packing with rotation support.

Zero dependencies, fully typed, three packing algorithms, and rotation-aware candidate generation.

Table of Contents

Features

Core Strengths

  • Smallest Box Finding — Greedy 3D bin packing with rotation support
  • Six Axis-Aligned Rotations — Items tested in all orientations for optimal fit
  • Three Packing Algorithms — Guillotine, MaxRects, and ExtremePoint
  • Custom Sort & Pack Orders — Fine-tune item ordering via closures
  • Fluent API — Build item lists incrementally with add(), remove(), clear()
  • Immutable Value ObjectsItem and Box with type-safe accessors
  • Static Analysis with PHPStan — Strict type checks across the codebase
  • Zero Dependencies — Only requires PHP 7.4+

Perfect For

  • 🎯 Logistics and shipping box optimisation
  • 🎯 Warehouse packing calculations
  • 🎯 3D layout and spatial planning
  • 🎯 Any scenario needing the smallest bounding box for rectangular items

Requirements

  • PHP 7.4+

Installation

Via Composer

composer require daika7ana/smallest-box

Quick Start

Pass items directly

use Daika7ana\SmallestBox\Item;
use Daika7ana\SmallestBox\SmallestBoxFinder;

$items = [
    new Item(5.0, 3.0, 2.0),
    new Item(3.0, 3.0, 3.0),
    new Item(2.0, 2.0, 1.0),
];

$finder = new SmallestBoxFinder();
$box = $finder->find($items);

echo $box;           // "5.00 x 5.00 x 3.00"
echo $box->volume(); // 75.0

Build item list incrementally

$finder = new SmallestBoxFinder();

$finder
    ->add(new Item(5.0, 3.0, 2.0))
    ->add(new Item(3.0, 3.0, 3.0))
    ->add(new Item(2.0, 2.0, 1.0));

$box = $finder->find();

Choose a packing algorithm

// Default: guillotine (fast, ~65% efficiency for diverse items)
$finder = new SmallestBoxFinder();

// MaxRects (slower, ~100% efficiency for diverse items)
$finder = new SmallestBoxFinder(SmallestBoxFinder::ALGO_MAXRECTS);

// ExtremePoint (medium speed, ~75% efficiency for diverse items)
$finder = new SmallestBoxFinder(SmallestBoxFinder::ALGO_EXTREMEPOINT);

That's it! You've got the smallest box that fits all your items.

Packing Algorithms

Algorithm Efficiency Speed Best For
ALGO_GUILLOTINE (default) ~65% Fast Uniform items, speed-critical
ALGO_EXTREMEPOINT ~75% Medium Balanced efficiency and speed
ALGO_MAXRECTS ~100% Slower Diverse items, best fit

How It Works

  1. Sort items by multiple heuristics (volume, dimensions, footprint).
  2. Generate candidate box dimensions from item dimension permutations and sums.
  3. Test each candidate with the selected packing algorithm and all six rotations.
  4. Return the smallest box that successfully fits all items.

Custom Sort & Pack Orders

Fine-tune packing behaviour for your specific use case:

$finder = new SmallestBoxFinder();

// Sort items by height ascending (build layers from bottom up)
$finder->addSortOrder(function (Item $a, Item $b): int {
    return $a->height() <=> $b->height();
});

// Pack widest items first
$finder->addPackOrder(function (Item $a, Item $b): int {
    return $b->width() <=> $a->width();
});

$box = $finder->find($items);

Custom orders are tried after the built-in ones. Both methods support fluent chaining.

Testing

Run Static Analysis

composer stan

PHPStan is configured via phpstan.neon and analyses the src/ directory.

Run Code Style Checks

composer pint

Run Full Test Suite

composer test

Run The Same Checks As CI

composer ci

Available Composer scripts:

  • composer pint — Check code style (Laravel Pint)
  • composer stan — Run static analysis (PHPStan)
  • composer test — Run the test suite (PHPUnit)
  • composer ci — Run all checks in sequence

Documentation

Guide Purpose
📖 Usage & Examples Working examples and patterns
🔧 Installation Detailed setup instructions
📋 API Reference Complete class and method reference
⚙️ Algorithm Details How the packing algorithms work

Made with ❤️

Questions? Check the docs or open an issue