Skip to content

Commit 09d47b8

Browse files
author
dcmox
committed
binpacking
1 parent b4e1ca5 commit 09d47b8

File tree

4 files changed

+118
-43
lines changed

4 files changed

+118
-43
lines changed

README.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,32 @@
1-
# binpacking
1+
# binpacking
2+
Simple binpacking algorithm for packing items in a 3D space.
3+
4+
## Usage
5+
```typescript
6+
const items: IBinItem[] = [
7+
{length: 2, width: 2, height: 2, id: 'A'},
8+
{length: 1, width: 2, height: 3, id: 'B'},
9+
{length: 3, width: 1, height: 1, id: 'C'},
10+
{length: 2, width: 2, height: 2, id: 'D'},
11+
{length: 2, width: 4, height: 4, id: 'E'},
12+
{length: 1, width: 5, height: 1, id: 'F'},
13+
{length: 1, width: 2, height: 2, id: 'G'},
14+
{length: 1, width: 1, height: 3, id: 'H'},
15+
{length: 1, width: 3, height: 1, id: 'J'},
16+
{length: 1, width: 1, height: 1, id: 'K'},
17+
{length: 1, width: 3, height: 1, id: 'L'},
18+
{length: 1, width: 1, height: 3, id: 'M'},
19+
{length: 1, width: 1, height: 3, id: 'N'},
20+
{length: 1, width: 3, height: 1, id: 'O'},
21+
{length: 1, width: 2, height: 1, id: 'P'},
22+
{length: 1, width: 1, height: 2, id: 'Q'},
23+
{length: 2, width: 1, height: 1, id: 'R'},
24+
]
25+
26+
const bin = {width: 5, height: 5, length: 3}
27+
28+
console.time('BinPack time')
29+
const results = binpack(bin, items)
30+
console.log(results)
31+
console.timeEnd('BinPack time')
32+
```

binpack.ts

Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,46 @@
1-
interface IBinSize {
1+
export interface IBinSize {
22
height: number,
33
length: number,
44
width: number,
55
}
66

7-
interface IBinItem {
7+
export interface IBinItem {
88
length: number,
99
width: number,
1010
height: number,
1111
id: string,
1212
}
1313

14-
interface IBinResult {
14+
export interface IBinResult {
1515
box: TBin,
1616
results: IBinItemResult[],
1717
rotations: number,
1818
unfit: number,
1919
}
2020

21-
interface IBinItemResult {
21+
export interface IBinItemResult {
2222
code: string,
2323
desc: string,
2424
id: string,
2525
success: boolean,
2626
}
2727

28-
interface IBinItemSolution {
28+
export interface IBinItemSolution {
2929
pos: IBinItemPosition,
3030
item: IBinItem,
3131
desc: string,
3232
rotation: boolean,
3333
}
3434

35-
interface IBinItemPosition {
35+
export interface IBinItemPosition {
3636
x: number,
3737
y: number,
3838
z: number
3939
}
4040

41-
type TBin = string[][][]
41+
export type TBin = string[][][]
4242

43-
const generateMatrix = (height: number, width: number, depth: number): TBin => {
43+
export const generateEmptyBin = (height: number, width: number, depth: number): TBin => {
4444
const layers = []
4545
for (let j = 0; j < depth; j++) {
4646
const matrix = new Array(height)
@@ -52,8 +52,7 @@ const generateMatrix = (height: number, width: number, depth: number): TBin => {
5252
return layers
5353
}
5454

55-
// todo - add 3d visualization
56-
const getPosition = (matrix: any, item: any): IBinItemPosition => {
55+
export const getPosition = (matrix: any, item: any): IBinItemPosition => {
5756
let solution: any = {x: false, y: false, z: false}
5857

5958
il:
@@ -89,7 +88,7 @@ const getPosition = (matrix: any, item: any): IBinItemPosition => {
8988
return solution
9089
}
9190

92-
const bestFit = (matrix: any[][][], solutions: any[]) => {
91+
export const bestFit = (matrix: any[][][], solutions: any[]) => {
9392
let bsi: number = 0
9493
solutions.forEach((s, idx) => {
9594
if (solutions[bsi].pos.x === false) {
@@ -105,8 +104,7 @@ const bestFit = (matrix: any[][][], solutions: any[]) => {
105104
{desc: solutions[bsi].desc})
106105
}
107106

108-
// orientation needed
109-
const placeItem = (matrix: TBin, item: any): IBinItemResult => {
107+
export const pack = (matrix: TBin, item: any): IBinItemResult => {
110108
const o: IBinItemPosition = getPosition(matrix, item)
111109
const solutions: IBinItemSolution[] = []
112110
solutions.push({pos: o, item, desc: 'Orientation: Default', rotation: false})
@@ -156,39 +154,14 @@ const placeItem = (matrix: TBin, item: any): IBinItemResult => {
156154
}
157155
}
158156

159-
const binpack = (boxSize: IBinSize, items: IBinItem[]): IBinResult => {
160-
const box = generateMatrix(boxSize.height, boxSize.width, boxSize.length)
157+
export const binpack = (boxSize: IBinSize, items: IBinItem[]): IBinResult => {
158+
const box = generateEmptyBin(boxSize.height, boxSize.width, boxSize.length)
161159
items.sort((a: IBinItem, b: IBinItem) => a.length * a.width * a.height > b.length * b.width * b.height ? -1 : 1)
162160
const results: any = []
163-
items.forEach((itm: IBinItem) => results.push(placeItem(box, itm)))
161+
items.forEach((item: IBinItem) => results.push(pack(box, item)))
164162
const unfit: number = results.filter((r: IBinItemResult) => r.code === 'OVERSIZED').length
165163
const rotations: number = results.filter((r: IBinItemResult) => r.code === 'ROTATION').length
166164
return { box, results, rotations, unfit }
167165
}
168166

169-
let items: IBinItem[] = [
170-
{length: 2, width: 2, height: 2, id: 'A'},
171-
{length: 1, width: 2, height: 3, id: 'B'},
172-
{length: 3, width: 1, height: 1, id: 'C'},
173-
{length: 2, width: 2, height: 2, id: 'D'},
174-
{length: 2, width: 4, height: 4, id: 'E'},
175-
{length: 1, width: 5, height: 1, id: 'F'},
176-
{length: 1, width: 2, height: 2, id: 'G'},
177-
{length: 1, width: 1, height: 3, id: 'H'},
178-
{length: 1, width: 3, height: 1, id: 'J'},
179-
{length: 1, width: 1, height: 1, id: 'K'},
180-
{length: 1, width: 3, height: 1, id: 'L'},
181-
{length: 1, width: 1, height: 3, id: 'M'},
182-
{length: 1, width: 1, height: 3, id: 'N'},
183-
{length: 1, width: 3, height: 1, id: 'O'},
184-
{length: 1, width: 2, height: 1, id: 'P'},
185-
{length: 1, width: 1, height: 2, id: 'Q'},
186-
{length: 2, width: 1, height: 1, id: 'R'},
187-
]
188-
189-
let bin = {width: 5, height: 5, length: 3}
190-
191-
console.time('BinPack time')
192-
const results = binpack(bin, items)
193-
console.log(results)
194-
console.timeEnd('BinPack time')
167+
export default binpack

package.json

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"name": "binpack-simple",
3+
"version": "1.0.0",
4+
"private": false,
5+
"description": "Simple binpack algorithm",
6+
"main": "binpack.js",
7+
"engines": {
8+
"node": ">=4.0.0"
9+
},
10+
"devDependencies": {
11+
"typescript": "3.7.2",
12+
"@types/jest": "^24.0.24",
13+
"@types/sinon": "^7.5.1",
14+
"chai": "^4.2.0",
15+
"jest": "^24.9.0",
16+
"sinon": "^7.5.0",
17+
"ts-jest": "^24.2.0",
18+
"tslint": "^5.20.1"
19+
},
20+
"scripts": {
21+
"test": "jest tests/*",
22+
"build": "npm run build:main && npm run build:demo",
23+
"build:main": "tsc binpack.ts",
24+
"build:demo": "tsc tests/usage.ts",
25+
"watch": "tsc -w tests/usage.ts",
26+
"test-usage": "node tests/usage.js"
27+
},
28+
"repository": {
29+
"type": "git",
30+
"url": "git+https://github.com/dcmox/binpacking.git"
31+
},
32+
"keywords": [
33+
"binpack",
34+
"3d packing",
35+
"packing"
36+
],
37+
"author": "Daniel Moxon ([email protected])",
38+
"license": "MIT",
39+
"bugs": {
40+
"url": "https://github.com/dcmox/binpacking/issues"
41+
},
42+
"homepage": "https://github.com/dcmox/binpacking#readme"
43+
}

tests/usage.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { binpack, IBinItem } from '../binpack'
2+
3+
const items: IBinItem[] = [
4+
{length: 2, width: 2, height: 2, id: 'A'},
5+
{length: 1, width: 2, height: 3, id: 'B'},
6+
{length: 3, width: 1, height: 1, id: 'C'},
7+
{length: 2, width: 2, height: 2, id: 'D'},
8+
{length: 2, width: 4, height: 4, id: 'E'},
9+
{length: 1, width: 5, height: 1, id: 'F'},
10+
{length: 1, width: 2, height: 2, id: 'G'},
11+
{length: 1, width: 1, height: 3, id: 'H'},
12+
{length: 1, width: 3, height: 1, id: 'J'},
13+
{length: 1, width: 1, height: 1, id: 'K'},
14+
{length: 1, width: 3, height: 1, id: 'L'},
15+
{length: 1, width: 1, height: 3, id: 'M'},
16+
{length: 1, width: 1, height: 3, id: 'N'},
17+
{length: 1, width: 3, height: 1, id: 'O'},
18+
{length: 1, width: 2, height: 1, id: 'P'},
19+
{length: 1, width: 1, height: 2, id: 'Q'},
20+
{length: 2, width: 1, height: 1, id: 'R'},
21+
]
22+
23+
const bin = {width: 5, height: 5, length: 3}
24+
25+
console.time('BinPack time')
26+
const results = binpack(bin, items)
27+
console.log(results)
28+
console.timeEnd('BinPack time')

0 commit comments

Comments
 (0)