@cratefit/pack 0.1.0
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/LICENSE +51 -0
- package/README.md +131 -0
- package/dist/index.cjs +360 -0
- package/dist/index.d.cts +1280 -0
- package/dist/index.d.ts +1280 -0
- package/dist/index.js +360 -0
- package/package.json +59 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1280 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v9.5.1
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CrateFit Core Types
|
|
5
|
+
*/
|
|
6
|
+
export interface Point3D {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
z: number;
|
|
10
|
+
}
|
|
11
|
+
export interface Dimensions3D {
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
depth: number;
|
|
15
|
+
}
|
|
16
|
+
export interface AABB {
|
|
17
|
+
minX: number;
|
|
18
|
+
maxX: number;
|
|
19
|
+
minY: number;
|
|
20
|
+
maxY: number;
|
|
21
|
+
minZ: number;
|
|
22
|
+
maxZ: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 6 rotation types for 3D items
|
|
26
|
+
* RT_WHD: W×H×D (original)
|
|
27
|
+
* RT_HWD: H×W×D
|
|
28
|
+
* RT_HDW: H×D×W
|
|
29
|
+
* RT_DHW: D×H×W
|
|
30
|
+
* RT_DWH: D×W×H
|
|
31
|
+
* RT_WDH: W×D×H
|
|
32
|
+
*/
|
|
33
|
+
export declare const RotationType: {
|
|
34
|
+
readonly RT_WHD: 0;
|
|
35
|
+
readonly RT_HWD: 1;
|
|
36
|
+
readonly RT_HDW: 2;
|
|
37
|
+
readonly RT_DHW: 3;
|
|
38
|
+
readonly RT_DWH: 4;
|
|
39
|
+
readonly RT_WDH: 5;
|
|
40
|
+
};
|
|
41
|
+
export type RotationTypeValue = (typeof RotationType)[keyof typeof RotationType];
|
|
42
|
+
export type RotationMode = "all" | "horizontal" | "fixed";
|
|
43
|
+
export interface ItemSpec {
|
|
44
|
+
id: string;
|
|
45
|
+
width: number;
|
|
46
|
+
height: number;
|
|
47
|
+
depth: number;
|
|
48
|
+
weight?: number;
|
|
49
|
+
rotationType?: RotationMode;
|
|
50
|
+
allowedRotations?: RotationTypeValue[];
|
|
51
|
+
maxStackWeight?: number;
|
|
52
|
+
requiresFloor?: boolean;
|
|
53
|
+
requiresSupport?: number;
|
|
54
|
+
groupId?: string;
|
|
55
|
+
incompatibleWith?: string[];
|
|
56
|
+
deliveryOrder?: number;
|
|
57
|
+
metadata?: Record<string, unknown>;
|
|
58
|
+
}
|
|
59
|
+
export interface PlacedItem {
|
|
60
|
+
item: ItemSpec;
|
|
61
|
+
position: Point3D;
|
|
62
|
+
rotation: RotationTypeValue;
|
|
63
|
+
dimensions: Dimensions3D;
|
|
64
|
+
}
|
|
65
|
+
export type ContainerType = "box" | "pallet" | "container" | "truck" | "shelf" | "custom";
|
|
66
|
+
export interface ScenarioConstraints {
|
|
67
|
+
maxStackHeight?: number;
|
|
68
|
+
overhangAllowed?: boolean;
|
|
69
|
+
palletPattern?: "column" | "interlock";
|
|
70
|
+
axleWeights?: {
|
|
71
|
+
front: number;
|
|
72
|
+
rear: number;
|
|
73
|
+
};
|
|
74
|
+
loadingDirection?: "rear" | "side";
|
|
75
|
+
shelfLevels?: number[];
|
|
76
|
+
accessibility?: "fifo" | "lifo" | "random";
|
|
77
|
+
maxGirth?: number;
|
|
78
|
+
maxLinearDim?: number;
|
|
79
|
+
volumetricDivisor?: number;
|
|
80
|
+
}
|
|
81
|
+
export interface BinSpec {
|
|
82
|
+
id: string;
|
|
83
|
+
type: ContainerType;
|
|
84
|
+
width: number;
|
|
85
|
+
height: number;
|
|
86
|
+
depth: number;
|
|
87
|
+
maxWeight?: number;
|
|
88
|
+
cost?: number;
|
|
89
|
+
existingItems?: PlacedItem[];
|
|
90
|
+
excludeZones?: AABB[];
|
|
91
|
+
constraints?: ScenarioConstraints;
|
|
92
|
+
}
|
|
93
|
+
export type AlgorithmType = "extreme-point" | "layer-building" | "wall-building" | "eb-afit";
|
|
94
|
+
export type PreprocessorType = "block-building" | "none";
|
|
95
|
+
export type EnhancerType = "genetic" | "simulated-annealing" | "tabu-search" | "none";
|
|
96
|
+
export type OptimizeTarget = "space" | "cost" | "balanced";
|
|
97
|
+
export type BinSelectionStrategy = "first-fit" | "best-fit" | "spread";
|
|
98
|
+
export type SpatialIndexType = "naive" | "octree";
|
|
99
|
+
export interface PackOptions {
|
|
100
|
+
preprocessor?: PreprocessorType;
|
|
101
|
+
algorithm?: AlgorithmType;
|
|
102
|
+
enhancer?: EnhancerType;
|
|
103
|
+
timeBudgetMs?: number;
|
|
104
|
+
features?: {
|
|
105
|
+
supportCheck?: boolean;
|
|
106
|
+
weightBalance?: boolean;
|
|
107
|
+
stackingLimit?: boolean;
|
|
108
|
+
};
|
|
109
|
+
constraints?: {
|
|
110
|
+
respectDeliveryOrder?: boolean;
|
|
111
|
+
keepGroupsTogether?: boolean;
|
|
112
|
+
enforceIncompatibility?: boolean;
|
|
113
|
+
};
|
|
114
|
+
optimize?: {
|
|
115
|
+
target?: OptimizeTarget;
|
|
116
|
+
};
|
|
117
|
+
binSelection?: BinSelectionStrategy;
|
|
118
|
+
spatialIndex?: SpatialIndexType;
|
|
119
|
+
}
|
|
120
|
+
export interface PackConfig {
|
|
121
|
+
bins: BinSpec[];
|
|
122
|
+
items: ItemSpec[];
|
|
123
|
+
options?: PackOptions;
|
|
124
|
+
}
|
|
125
|
+
export interface PackedBin {
|
|
126
|
+
bin: BinSpec;
|
|
127
|
+
items: PlacedItem[];
|
|
128
|
+
utilization: number;
|
|
129
|
+
weight: number;
|
|
130
|
+
centerOfGravity: Point3D;
|
|
131
|
+
}
|
|
132
|
+
export interface PackStats {
|
|
133
|
+
totalBins: number;
|
|
134
|
+
totalItems: number;
|
|
135
|
+
packedItems: number;
|
|
136
|
+
unpackedItems: number;
|
|
137
|
+
avgUtilization: number;
|
|
138
|
+
totalVolume: number;
|
|
139
|
+
usedVolume: number;
|
|
140
|
+
totalWeight: number;
|
|
141
|
+
totalCost?: number;
|
|
142
|
+
actualWeight: number;
|
|
143
|
+
volumetricWeight?: number;
|
|
144
|
+
chargeableWeight?: number;
|
|
145
|
+
}
|
|
146
|
+
export interface PackResult {
|
|
147
|
+
packed: PackedBin[];
|
|
148
|
+
unpacked: ItemSpec[];
|
|
149
|
+
stats: PackStats;
|
|
150
|
+
}
|
|
151
|
+
export interface SpatialIndex {
|
|
152
|
+
insert(item: PlacedItem): void;
|
|
153
|
+
remove(item: PlacedItem): void;
|
|
154
|
+
query(bounds: AABB): PlacedItem[];
|
|
155
|
+
clear(): void;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Core pack function
|
|
159
|
+
*/
|
|
160
|
+
/**
|
|
161
|
+
* Main pack function
|
|
162
|
+
*/
|
|
163
|
+
export declare function pack(config: PackConfig): PackResult;
|
|
164
|
+
/**
|
|
165
|
+
* Packer class - chainable API wrapper
|
|
166
|
+
*/
|
|
167
|
+
/**
|
|
168
|
+
* Chainable Packer class
|
|
169
|
+
*/
|
|
170
|
+
export declare class Packer {
|
|
171
|
+
private bins;
|
|
172
|
+
private items;
|
|
173
|
+
private options;
|
|
174
|
+
/**
|
|
175
|
+
* Add a bin/container
|
|
176
|
+
*/
|
|
177
|
+
addBin(bin: BinSpec): this;
|
|
178
|
+
/**
|
|
179
|
+
* Add multiple bins
|
|
180
|
+
*/
|
|
181
|
+
addBins(bins: BinSpec[]): this;
|
|
182
|
+
/**
|
|
183
|
+
* Add an item
|
|
184
|
+
*/
|
|
185
|
+
addItem(item: ItemSpec): this;
|
|
186
|
+
/**
|
|
187
|
+
* Add multiple items
|
|
188
|
+
*/
|
|
189
|
+
addItems(items: ItemSpec[]): this;
|
|
190
|
+
/**
|
|
191
|
+
* Set pack options
|
|
192
|
+
*/
|
|
193
|
+
setOptions(options: Partial<PackOptions>): this;
|
|
194
|
+
/**
|
|
195
|
+
* Execute packing
|
|
196
|
+
*/
|
|
197
|
+
pack(options?: Partial<PackOptions>): PackResult;
|
|
198
|
+
/**
|
|
199
|
+
* Reset packer state
|
|
200
|
+
*/
|
|
201
|
+
reset(): this;
|
|
202
|
+
/**
|
|
203
|
+
* Get current bins
|
|
204
|
+
*/
|
|
205
|
+
getBins(): BinSpec[];
|
|
206
|
+
/**
|
|
207
|
+
* Get current items
|
|
208
|
+
*/
|
|
209
|
+
getItems(): ItemSpec[];
|
|
210
|
+
/**
|
|
211
|
+
* Get current options
|
|
212
|
+
*/
|
|
213
|
+
getOptions(): PackOptions;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Create a new Packer instance
|
|
217
|
+
*/
|
|
218
|
+
export declare function createPacker(): Packer;
|
|
219
|
+
/**
|
|
220
|
+
* Extreme Point Algorithm (Optimized)
|
|
221
|
+
*
|
|
222
|
+
* An advanced heuristic algorithm that tracks "extreme points" (candidate positions)
|
|
223
|
+
* where items can be placed. This implementation includes:
|
|
224
|
+
* - Projection of extreme points to support surfaces
|
|
225
|
+
* - Multiple point generation strategies
|
|
226
|
+
* - Best-fit selection option
|
|
227
|
+
* - Efficient point management
|
|
228
|
+
*
|
|
229
|
+
* Based on research and improvements over basic First-Fit approaches like py3dbp.
|
|
230
|
+
*/
|
|
231
|
+
/**
|
|
232
|
+
* Pack items into a single bin using Extreme Point algorithm
|
|
233
|
+
*/
|
|
234
|
+
export declare function packWithExtremePoint(bin: BinSpec, items: ItemSpec[], options?: PackOptions): {
|
|
235
|
+
packed: PlacedItem[];
|
|
236
|
+
unpacked: ItemSpec[];
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* Layer Building Algorithm
|
|
240
|
+
*
|
|
241
|
+
* A height-based packing algorithm that builds horizontal layers.
|
|
242
|
+
* Well-suited for pallet packing where items need stable stacking.
|
|
243
|
+
*
|
|
244
|
+
* Key concepts:
|
|
245
|
+
* - Groups items by similar heights into layers
|
|
246
|
+
* - Uses 2D bottom-left placement within each layer
|
|
247
|
+
* - Builds layers from bottom to top
|
|
248
|
+
* - Ensures proper support between layers
|
|
249
|
+
*/
|
|
250
|
+
/**
|
|
251
|
+
* Pack items into a single bin using Layer Building algorithm
|
|
252
|
+
*/
|
|
253
|
+
export declare function packWithLayerBuilding(bin: BinSpec, items: ItemSpec[], options?: PackOptions): {
|
|
254
|
+
packed: PlacedItem[];
|
|
255
|
+
unpacked: ItemSpec[];
|
|
256
|
+
};
|
|
257
|
+
/**
|
|
258
|
+
* Layer information for analysis
|
|
259
|
+
*/
|
|
260
|
+
export interface Layer {
|
|
261
|
+
yLevel: number;
|
|
262
|
+
height: number;
|
|
263
|
+
items: PlacedItem[];
|
|
264
|
+
coverage: number;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Extract layer information from packed result
|
|
268
|
+
*/
|
|
269
|
+
export declare function extractLayers(packed: PlacedItem[], binWidth?: number, binDepth?: number): Layer[];
|
|
270
|
+
/**
|
|
271
|
+
* Wall Building Algorithm
|
|
272
|
+
*
|
|
273
|
+
* A depth-based packing algorithm that builds vertical "walls" from back to front.
|
|
274
|
+
* Well-suited for container loading with LIFO (Last In First Out) requirements.
|
|
275
|
+
*
|
|
276
|
+
* Key concepts:
|
|
277
|
+
* - Builds walls perpendicular to the Z-axis (depth direction)
|
|
278
|
+
* - Each wall is a 2D packing problem in the X-Y plane
|
|
279
|
+
* - Items are packed from the back of the container forward
|
|
280
|
+
* - Supports unloading order requirements
|
|
281
|
+
*/
|
|
282
|
+
/**
|
|
283
|
+
* Pack items into a single bin using Wall Building algorithm
|
|
284
|
+
*/
|
|
285
|
+
export declare function packWithWallBuilding(bin: BinSpec, items: ItemSpec[], options?: PackOptions): {
|
|
286
|
+
packed: PlacedItem[];
|
|
287
|
+
unpacked: ItemSpec[];
|
|
288
|
+
};
|
|
289
|
+
/**
|
|
290
|
+
* Wall information for analysis
|
|
291
|
+
*/
|
|
292
|
+
export interface Wall {
|
|
293
|
+
zStart: number;
|
|
294
|
+
zEnd: number;
|
|
295
|
+
items: PlacedItem[];
|
|
296
|
+
utilization: number;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Extract wall information from packed result
|
|
300
|
+
*/
|
|
301
|
+
export declare function extractWalls(packed: PlacedItem[], bin: BinSpec): Wall[];
|
|
302
|
+
/**
|
|
303
|
+
* EB-AFIT Algorithm
|
|
304
|
+
*
|
|
305
|
+
* Based on Erhan Baltacıoğlu's thesis at Air Force Institute of Technology (2001).
|
|
306
|
+
* A human intelligence-based heuristic approach for 3D bin packing.
|
|
307
|
+
*
|
|
308
|
+
* Key concepts:
|
|
309
|
+
* - Evaluates all possible layer heights based on item dimensions
|
|
310
|
+
* - Selects optimal layer height by analyzing potential space utilization
|
|
311
|
+
* - Uses sophisticated gap management for better packing
|
|
312
|
+
* - Considers both horizontal and vertical space optimization
|
|
313
|
+
*/
|
|
314
|
+
/**
|
|
315
|
+
* Pack items using EB-AFIT algorithm
|
|
316
|
+
*/
|
|
317
|
+
export declare function packWithEBAFIT(bin: BinSpec, items: ItemSpec[], options?: PackOptions): {
|
|
318
|
+
packed: PlacedItem[];
|
|
319
|
+
unpacked: ItemSpec[];
|
|
320
|
+
};
|
|
321
|
+
/**
|
|
322
|
+
* Block Building Preprocessor
|
|
323
|
+
*
|
|
324
|
+
* Groups identical or similar items into larger blocks to reduce problem complexity.
|
|
325
|
+
* This is a preprocessing step that can improve packing efficiency for homogeneous items.
|
|
326
|
+
*
|
|
327
|
+
* Key concepts:
|
|
328
|
+
* - Groups items with identical dimensions
|
|
329
|
+
* - Creates composite blocks from multiple items
|
|
330
|
+
* - Reduces the number of items to place
|
|
331
|
+
* - Expands blocks back to original items after placement
|
|
332
|
+
*/
|
|
333
|
+
export interface Block {
|
|
334
|
+
id: string;
|
|
335
|
+
originalItems: ItemSpec[];
|
|
336
|
+
width: number;
|
|
337
|
+
height: number;
|
|
338
|
+
depth: number;
|
|
339
|
+
weight: number;
|
|
340
|
+
count: number;
|
|
341
|
+
/** How items are arranged in the block */
|
|
342
|
+
arrangement: BlockArrangement;
|
|
343
|
+
}
|
|
344
|
+
export interface BlockArrangement {
|
|
345
|
+
countX: number;
|
|
346
|
+
countY: number;
|
|
347
|
+
countZ: number;
|
|
348
|
+
itemWidth: number;
|
|
349
|
+
itemHeight: number;
|
|
350
|
+
itemDepth: number;
|
|
351
|
+
}
|
|
352
|
+
export interface BlockBuildingOptions {
|
|
353
|
+
/** Minimum items to form a block */
|
|
354
|
+
minBlockSize?: number;
|
|
355
|
+
/** Maximum items in a block */
|
|
356
|
+
maxBlockSize?: number;
|
|
357
|
+
/** Tolerance for matching dimensions (as percentage, 0-1) */
|
|
358
|
+
tolerancePct?: number;
|
|
359
|
+
/** Prefer blocks that fit container dimensions well */
|
|
360
|
+
optimizeForContainer?: {
|
|
361
|
+
width: number;
|
|
362
|
+
height: number;
|
|
363
|
+
depth: number;
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Build blocks from items by grouping identical items
|
|
368
|
+
*/
|
|
369
|
+
export declare function buildBlocks(items: ItemSpec[], options?: BlockBuildingOptions): {
|
|
370
|
+
blocks: Block[];
|
|
371
|
+
remaining: ItemSpec[];
|
|
372
|
+
};
|
|
373
|
+
/**
|
|
374
|
+
* Expand blocks back to original items (for unpacked items)
|
|
375
|
+
*/
|
|
376
|
+
export declare function expandBlocks(blocks: Block[]): ItemSpec[];
|
|
377
|
+
/**
|
|
378
|
+
* Genetic Algorithm Enhancer
|
|
379
|
+
*
|
|
380
|
+
* Post-processing optimizer using genetic algorithm to improve packing results.
|
|
381
|
+
* Uses evolutionary strategies to find better item orderings and configurations.
|
|
382
|
+
*
|
|
383
|
+
* Key concepts:
|
|
384
|
+
* - Chromosome: An ordering of items (permutation)
|
|
385
|
+
* - Fitness: Packing utilization and quality metrics
|
|
386
|
+
* - Crossover: Combine good orderings from parents
|
|
387
|
+
* - Mutation: Random swaps and rotations
|
|
388
|
+
* - Selection: Keep best solutions
|
|
389
|
+
*/
|
|
390
|
+
export interface GeneticOptions {
|
|
391
|
+
/** Number of solutions in population */
|
|
392
|
+
populationSize?: number;
|
|
393
|
+
/** Number of generations to evolve */
|
|
394
|
+
generations?: number;
|
|
395
|
+
/** Probability of crossover (0-1) */
|
|
396
|
+
crossoverRate?: number;
|
|
397
|
+
/** Probability of mutation (0-1) */
|
|
398
|
+
mutationRate?: number;
|
|
399
|
+
/** Number of best solutions to preserve */
|
|
400
|
+
elitismCount?: number;
|
|
401
|
+
/** Maximum time budget in milliseconds */
|
|
402
|
+
timeBudgetMs?: number;
|
|
403
|
+
/** Base packing options to use */
|
|
404
|
+
packOptions?: PackOptions;
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Enhance packing result using genetic algorithm
|
|
408
|
+
*/
|
|
409
|
+
export declare function enhanceWithGenetic(result: PackResult, options?: GeneticOptions): PackResult;
|
|
410
|
+
/**
|
|
411
|
+
* Collision detection constraints
|
|
412
|
+
*/
|
|
413
|
+
/**
|
|
414
|
+
* Check if placing an item at a position would collide with existing items
|
|
415
|
+
*/
|
|
416
|
+
export declare function hasCollision(position: Point3D, dimensions: Dimensions3D, spatialIndex: SpatialIndex): boolean;
|
|
417
|
+
/**
|
|
418
|
+
* Check if item fits within bin boundaries
|
|
419
|
+
*/
|
|
420
|
+
export declare function fitsInBin(position: Point3D, dimensions: Dimensions3D, bin: BinSpec): boolean;
|
|
421
|
+
/**
|
|
422
|
+
* Check if position is within any exclude zone
|
|
423
|
+
*/
|
|
424
|
+
export declare function isInExcludeZone(position: Point3D, dimensions: Dimensions3D, bin: BinSpec): boolean;
|
|
425
|
+
/**
|
|
426
|
+
* Weight-related constraints
|
|
427
|
+
*/
|
|
428
|
+
/**
|
|
429
|
+
* Check if adding an item would exceed bin's max weight
|
|
430
|
+
*/
|
|
431
|
+
export declare function canAddWeight(existingItems: PlacedItem[], newItem: ItemSpec, bin: BinSpec): boolean;
|
|
432
|
+
/**
|
|
433
|
+
* Calculate total weight of placed items
|
|
434
|
+
*/
|
|
435
|
+
export declare function calcTotalWeight(items: PlacedItem[]): number;
|
|
436
|
+
/**
|
|
437
|
+
* Calculate center of gravity
|
|
438
|
+
*/
|
|
439
|
+
export declare function calcCenterOfGravity(items: PlacedItem[], bin: BinSpec): Point3D;
|
|
440
|
+
/**
|
|
441
|
+
* Check if weight distribution is balanced
|
|
442
|
+
*/
|
|
443
|
+
export declare function isWeightBalanced(items: PlacedItem[], bin: BinSpec, tolerance?: number): boolean;
|
|
444
|
+
/**
|
|
445
|
+
* Support/stability constraints
|
|
446
|
+
*/
|
|
447
|
+
/**
|
|
448
|
+
* Calculate supported area for an item
|
|
449
|
+
*/
|
|
450
|
+
export declare function calcSupportedArea(position: Point3D, dimensions: Dimensions3D, existingItems: PlacedItem[]): number;
|
|
451
|
+
/**
|
|
452
|
+
* Check if an item has sufficient support
|
|
453
|
+
*/
|
|
454
|
+
export declare function hasSufficientSupport(position: Point3D, dimensions: Dimensions3D, existingItems: PlacedItem[], minSupportRatio?: number): boolean;
|
|
455
|
+
/**
|
|
456
|
+
* Check stacking weight limit
|
|
457
|
+
*/
|
|
458
|
+
export declare function canStackOn(bottomItem: PlacedItem, topItemWeight: number, existingItems: PlacedItem[]): boolean;
|
|
459
|
+
/**
|
|
460
|
+
* Grouping and compatibility constraints
|
|
461
|
+
*/
|
|
462
|
+
/**
|
|
463
|
+
* Check if an item can be mixed with existing items in a bin
|
|
464
|
+
*/
|
|
465
|
+
export declare function canMixInBin(existingItems: PlacedItem[], newItem: ItemSpec): boolean;
|
|
466
|
+
/**
|
|
467
|
+
* Group items by groupId
|
|
468
|
+
*/
|
|
469
|
+
export declare function groupItems(items: ItemSpec[]): Map<string, ItemSpec[]>;
|
|
470
|
+
/**
|
|
471
|
+
* Sort items by delivery order (higher order = process first = pack at back)
|
|
472
|
+
*/
|
|
473
|
+
export declare function sortByDeliveryOrder(items: ItemSpec[]): ItemSpec[];
|
|
474
|
+
/**
|
|
475
|
+
* Sort items by volume (larger first by default)
|
|
476
|
+
*/
|
|
477
|
+
export declare function sortByVolume(items: ItemSpec[], ascending?: boolean): ItemSpec[];
|
|
478
|
+
/**
|
|
479
|
+
* Sort items by weight (heavier first by default)
|
|
480
|
+
*/
|
|
481
|
+
export declare function sortByWeight(items: ItemSpec[], ascending?: boolean): ItemSpec[];
|
|
482
|
+
/**
|
|
483
|
+
* Naive spatial index (linear search)
|
|
484
|
+
* Simple implementation for small item counts
|
|
485
|
+
*/
|
|
486
|
+
export declare class NaiveSpatialIndex implements SpatialIndex {
|
|
487
|
+
private items;
|
|
488
|
+
insert(item: PlacedItem): void;
|
|
489
|
+
remove(item: PlacedItem): void;
|
|
490
|
+
query(bounds: AABB): PlacedItem[];
|
|
491
|
+
clear(): void;
|
|
492
|
+
/**
|
|
493
|
+
* Get all items (for iteration)
|
|
494
|
+
*/
|
|
495
|
+
getAll(): PlacedItem[];
|
|
496
|
+
/**
|
|
497
|
+
* Get item count
|
|
498
|
+
*/
|
|
499
|
+
get size(): number;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Create a naive spatial index
|
|
503
|
+
*/
|
|
504
|
+
export declare function createNaiveIndex(): NaiveSpatialIndex;
|
|
505
|
+
/**
|
|
506
|
+
* Octree spatial index for efficient 3D collision queries
|
|
507
|
+
*
|
|
508
|
+
* Provides O(log n) query performance for large item counts,
|
|
509
|
+
* compared to O(n) for naive linear search.
|
|
510
|
+
*/
|
|
511
|
+
/**
|
|
512
|
+
* Configuration for Octree
|
|
513
|
+
*/
|
|
514
|
+
export interface OctreeConfig {
|
|
515
|
+
/** Maximum items per node before splitting (default: 8) */
|
|
516
|
+
maxItemsPerNode?: number;
|
|
517
|
+
/** Maximum tree depth (default: 8) */
|
|
518
|
+
maxDepth?: number;
|
|
519
|
+
/** Minimum node size - won't split below this (default: 1) */
|
|
520
|
+
minNodeSize?: number;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Octree spatial index implementation
|
|
524
|
+
*
|
|
525
|
+
* Efficiently organizes 3D items for fast spatial queries.
|
|
526
|
+
* Best for scenarios with 100+ items.
|
|
527
|
+
*/
|
|
528
|
+
export declare class OctreeIndex implements SpatialIndex {
|
|
529
|
+
private root;
|
|
530
|
+
private config;
|
|
531
|
+
private itemCount;
|
|
532
|
+
private itemMap;
|
|
533
|
+
constructor(bounds: AABB, config?: OctreeConfig);
|
|
534
|
+
/**
|
|
535
|
+
* Insert an item into the octree
|
|
536
|
+
*/
|
|
537
|
+
insert(item: PlacedItem): void;
|
|
538
|
+
/**
|
|
539
|
+
* Recursively insert item into appropriate node(s)
|
|
540
|
+
*/
|
|
541
|
+
private insertIntoNode;
|
|
542
|
+
/**
|
|
543
|
+
* Check if a node should be subdivided
|
|
544
|
+
*/
|
|
545
|
+
private shouldSubdivide;
|
|
546
|
+
/**
|
|
547
|
+
* Subdivide a node and redistribute its items
|
|
548
|
+
*/
|
|
549
|
+
private subdivideNode;
|
|
550
|
+
/**
|
|
551
|
+
* Remove an item from the octree
|
|
552
|
+
*/
|
|
553
|
+
remove(item: PlacedItem): void;
|
|
554
|
+
/**
|
|
555
|
+
* Recursively remove item from node and children
|
|
556
|
+
*/
|
|
557
|
+
private removeFromNode;
|
|
558
|
+
/**
|
|
559
|
+
* Query all items that intersect with the given bounds
|
|
560
|
+
*/
|
|
561
|
+
query(bounds: AABB): PlacedItem[];
|
|
562
|
+
/**
|
|
563
|
+
* Recursively query node and children
|
|
564
|
+
*/
|
|
565
|
+
private queryNode;
|
|
566
|
+
/**
|
|
567
|
+
* Clear all items from the octree
|
|
568
|
+
*/
|
|
569
|
+
clear(): void;
|
|
570
|
+
/**
|
|
571
|
+
* Get all items in the octree
|
|
572
|
+
*/
|
|
573
|
+
getAll(): PlacedItem[];
|
|
574
|
+
/**
|
|
575
|
+
* Get the number of items in the octree
|
|
576
|
+
*/
|
|
577
|
+
get size(): number;
|
|
578
|
+
/**
|
|
579
|
+
* Get statistics about the octree structure
|
|
580
|
+
*/
|
|
581
|
+
getStats(): OctreeStats;
|
|
582
|
+
private collectStats;
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Statistics about octree structure
|
|
586
|
+
*/
|
|
587
|
+
export interface OctreeStats {
|
|
588
|
+
totalNodes: number;
|
|
589
|
+
leafNodes: number;
|
|
590
|
+
maxDepth: number;
|
|
591
|
+
itemCount: number;
|
|
592
|
+
avgItemsPerLeaf: number;
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Create an octree spatial index
|
|
596
|
+
*/
|
|
597
|
+
export declare function createOctreeIndex(bounds: AABB, config?: OctreeConfig): OctreeIndex;
|
|
598
|
+
/**
|
|
599
|
+
* Integer conversion utilities for precision handling
|
|
600
|
+
*/
|
|
601
|
+
/**
|
|
602
|
+
* Set the scale factor for integer conversion
|
|
603
|
+
*/
|
|
604
|
+
export declare function setScale(scale: number): void;
|
|
605
|
+
/**
|
|
606
|
+
* Get the current scale factor
|
|
607
|
+
*/
|
|
608
|
+
export declare function getScale(): number;
|
|
609
|
+
/**
|
|
610
|
+
* Convert external value to internal integer
|
|
611
|
+
*/
|
|
612
|
+
export declare function toInternal(value: number): number;
|
|
613
|
+
/**
|
|
614
|
+
* Convert internal integer to external value
|
|
615
|
+
*/
|
|
616
|
+
export declare function toExternal(value: number): number;
|
|
617
|
+
/**
|
|
618
|
+
* Rotation utilities
|
|
619
|
+
*/
|
|
620
|
+
/**
|
|
621
|
+
* Get rotated dimensions based on rotation type
|
|
622
|
+
*/
|
|
623
|
+
export declare function getRotatedDimensions(width: number, height: number, depth: number, rotation: RotationTypeValue): Dimensions3D;
|
|
624
|
+
/**
|
|
625
|
+
* Get allowed rotations based on rotation mode
|
|
626
|
+
*/
|
|
627
|
+
export declare function getAllowedRotations(mode: RotationMode): RotationTypeValue[];
|
|
628
|
+
/**
|
|
629
|
+
* Get all rotation variants for an item
|
|
630
|
+
*/
|
|
631
|
+
export declare function getRotationVariants(width: number, height: number, depth: number, allowedRotations: RotationTypeValue[]): Array<{
|
|
632
|
+
rotation: RotationTypeValue;
|
|
633
|
+
dimensions: Dimensions3D;
|
|
634
|
+
}>;
|
|
635
|
+
/**
|
|
636
|
+
* Geometry utilities
|
|
637
|
+
*/
|
|
638
|
+
/**
|
|
639
|
+
* Create AABB from position and dimensions
|
|
640
|
+
*/
|
|
641
|
+
export declare function createAABB(position: Point3D, dimensions: Dimensions3D): AABB;
|
|
642
|
+
/**
|
|
643
|
+
* Check if two AABBs intersect
|
|
644
|
+
*/
|
|
645
|
+
export declare function intersectsAABB(a: AABB, b: AABB): boolean;
|
|
646
|
+
/**
|
|
647
|
+
* Check if AABB a contains AABB b
|
|
648
|
+
*/
|
|
649
|
+
export declare function containsAABB(a: AABB, b: AABB): boolean;
|
|
650
|
+
/**
|
|
651
|
+
* Calculate volume of AABB
|
|
652
|
+
*/
|
|
653
|
+
export declare function volumeAABB(aabb: AABB): number;
|
|
654
|
+
/**
|
|
655
|
+
* Calculate volume from dimensions
|
|
656
|
+
*/
|
|
657
|
+
export declare function volume(dims: Dimensions3D): number;
|
|
658
|
+
/**
|
|
659
|
+
* Get AABB of a placed item
|
|
660
|
+
*/
|
|
661
|
+
export declare function getItemAABB(item: PlacedItem): AABB;
|
|
662
|
+
/**
|
|
663
|
+
* Calculate overlap area on XZ plane (for support calculation)
|
|
664
|
+
*/
|
|
665
|
+
export declare function calcOverlapAreaXZ(a: AABB, b: AABB): number;
|
|
666
|
+
/**
|
|
667
|
+
* Check if item is directly above another (for stacking)
|
|
668
|
+
*/
|
|
669
|
+
export declare function isDirectlyAbove(top: PlacedItem, bottom: PlacedItem): boolean;
|
|
670
|
+
/**
|
|
671
|
+
* Validation utilities for packing results
|
|
672
|
+
*
|
|
673
|
+
* Verifies that packing results are correct:
|
|
674
|
+
* - No collisions between items
|
|
675
|
+
* - All items within bin boundaries
|
|
676
|
+
* - Volume calculations are accurate
|
|
677
|
+
* - All constraints are satisfied
|
|
678
|
+
*/
|
|
679
|
+
export interface ValidationResult {
|
|
680
|
+
valid: boolean;
|
|
681
|
+
errors: ValidationError[];
|
|
682
|
+
warnings: ValidationWarning[];
|
|
683
|
+
}
|
|
684
|
+
export interface ValidationOptions {
|
|
685
|
+
/** Check support constraint (items should not float) */
|
|
686
|
+
checkSupport?: boolean;
|
|
687
|
+
}
|
|
688
|
+
export interface ValidationError {
|
|
689
|
+
type: "collision" | "boundary" | "volume" | "count" | "support";
|
|
690
|
+
message: string;
|
|
691
|
+
items?: string[];
|
|
692
|
+
}
|
|
693
|
+
export interface ValidationWarning {
|
|
694
|
+
type: "utilization" | "balance" | "gap";
|
|
695
|
+
message: string;
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Validate a packing result
|
|
699
|
+
*/
|
|
700
|
+
export declare function validatePackingResult(bin: BinSpec, packed: PlacedItem[], unpacked: ItemSpec[], originalItems: ItemSpec[], options?: ValidationOptions): ValidationResult;
|
|
701
|
+
/**
|
|
702
|
+
* Quick validation check (returns true/false only)
|
|
703
|
+
*/
|
|
704
|
+
export declare function isValidPacking(bin: BinSpec, packed: PlacedItem[], unpacked: ItemSpec[], originalItems: ItemSpec[], options?: ValidationOptions): boolean;
|
|
705
|
+
/**
|
|
706
|
+
* Packing Instructions Types
|
|
707
|
+
*
|
|
708
|
+
* Types for generating human-readable packing instructions
|
|
709
|
+
*/
|
|
710
|
+
/**
|
|
711
|
+
* Action type for packing instruction
|
|
712
|
+
*/
|
|
713
|
+
export type InstructionAction = "place" | "rotate" | "stack";
|
|
714
|
+
/**
|
|
715
|
+
* Orientation description
|
|
716
|
+
*/
|
|
717
|
+
export type OrientationDescription = "upright" | "flat" | "sideways" | "rotated-90" | "rotated-180" | "custom";
|
|
718
|
+
/**
|
|
719
|
+
* Position description relative to bin or other items
|
|
720
|
+
*/
|
|
721
|
+
export interface PositionDescription {
|
|
722
|
+
/** Human-readable position description */
|
|
723
|
+
description: string;
|
|
724
|
+
/** Exact coordinates */
|
|
725
|
+
coordinates: Point3D;
|
|
726
|
+
/** Reference item ID (if stacking or adjacent) */
|
|
727
|
+
referenceItemId?: string;
|
|
728
|
+
/** Relationship to reference item */
|
|
729
|
+
relationship?: "above" | "beside" | "behind" | "in-front";
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Single packing instruction step
|
|
733
|
+
*/
|
|
734
|
+
export interface PackingInstruction {
|
|
735
|
+
/** Step number (1-indexed) */
|
|
736
|
+
step: number;
|
|
737
|
+
/** Action type */
|
|
738
|
+
action: InstructionAction;
|
|
739
|
+
/** Item ID */
|
|
740
|
+
itemId: string;
|
|
741
|
+
/** Human-readable item name (from metadata or ID) */
|
|
742
|
+
itemName: string;
|
|
743
|
+
/** Position information */
|
|
744
|
+
position: PositionDescription;
|
|
745
|
+
/** Item dimensions after rotation */
|
|
746
|
+
dimensions: Dimensions3D;
|
|
747
|
+
/** Orientation description */
|
|
748
|
+
orientation: OrientationDescription;
|
|
749
|
+
/** Layer number (1-indexed, from bottom) */
|
|
750
|
+
layer: number;
|
|
751
|
+
/** Additional notes/warnings */
|
|
752
|
+
notes: string[];
|
|
753
|
+
/** Original placed item reference */
|
|
754
|
+
placedItem: PlacedItem;
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Bin instruction summary
|
|
758
|
+
*/
|
|
759
|
+
export interface BinInstructionSummary {
|
|
760
|
+
/** Bin ID */
|
|
761
|
+
binId: string;
|
|
762
|
+
/** Bin type */
|
|
763
|
+
binType: string;
|
|
764
|
+
/** Bin dimensions (W x H x D) */
|
|
765
|
+
binDimensions: string;
|
|
766
|
+
/** Total item count */
|
|
767
|
+
itemCount: number;
|
|
768
|
+
/** Total weight */
|
|
769
|
+
totalWeight: number;
|
|
770
|
+
/** Layer count */
|
|
771
|
+
layerCount: number;
|
|
772
|
+
/** Space utilization percentage */
|
|
773
|
+
utilization: number;
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Instructions for a single bin
|
|
777
|
+
*/
|
|
778
|
+
export interface BinInstructions {
|
|
779
|
+
/** Bin summary info */
|
|
780
|
+
summary: BinInstructionSummary;
|
|
781
|
+
/** Ordered list of packing steps */
|
|
782
|
+
steps: PackingInstruction[];
|
|
783
|
+
/** General notes for this bin */
|
|
784
|
+
notes: string[];
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Complete packing instructions for all bins
|
|
788
|
+
*/
|
|
789
|
+
export interface PackingInstructions {
|
|
790
|
+
/** Generated timestamp */
|
|
791
|
+
generatedAt: string;
|
|
792
|
+
/** Total bins */
|
|
793
|
+
totalBins: number;
|
|
794
|
+
/** Total items */
|
|
795
|
+
totalItems: number;
|
|
796
|
+
/** Instructions per bin */
|
|
797
|
+
bins: BinInstructions[];
|
|
798
|
+
/** Global notes/warnings */
|
|
799
|
+
globalNotes: string[];
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Output format for instructions
|
|
803
|
+
*/
|
|
804
|
+
export type InstructionFormat = "json" | "markdown" | "html";
|
|
805
|
+
/**
|
|
806
|
+
* Language for instructions
|
|
807
|
+
*/
|
|
808
|
+
export type InstructionLanguage = "en" | "zh-TW";
|
|
809
|
+
/**
|
|
810
|
+
* Detail level for instructions
|
|
811
|
+
*/
|
|
812
|
+
export type InstructionDetailLevel = "simple" | "detailed";
|
|
813
|
+
/**
|
|
814
|
+
* Options for generating instructions
|
|
815
|
+
*/
|
|
816
|
+
export interface GenerateInstructionsOptions {
|
|
817
|
+
/** Output format */
|
|
818
|
+
format?: InstructionFormat;
|
|
819
|
+
/** Language */
|
|
820
|
+
language?: InstructionLanguage;
|
|
821
|
+
/** Detail level */
|
|
822
|
+
detailLevel?: InstructionDetailLevel;
|
|
823
|
+
/** Include coordinate details */
|
|
824
|
+
includeCoordinates?: boolean;
|
|
825
|
+
/** Include weight information */
|
|
826
|
+
includeWeight?: boolean;
|
|
827
|
+
/** Layer height threshold for grouping (in same units as dimensions) */
|
|
828
|
+
layerHeightThreshold?: number;
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Result of instruction generation
|
|
832
|
+
*/
|
|
833
|
+
export interface GenerateInstructionsResult {
|
|
834
|
+
/** Structured instructions */
|
|
835
|
+
instructions: PackingInstructions;
|
|
836
|
+
/** Formatted output string */
|
|
837
|
+
formatted: string;
|
|
838
|
+
/** Format used */
|
|
839
|
+
format: InstructionFormat;
|
|
840
|
+
/** Language used */
|
|
841
|
+
language: InstructionLanguage;
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* Packing Instructions Generator
|
|
845
|
+
*
|
|
846
|
+
* Converts PackResult to human-readable packing instructions
|
|
847
|
+
*/
|
|
848
|
+
/**
|
|
849
|
+
* Generate complete packing instructions from pack result
|
|
850
|
+
*/
|
|
851
|
+
export declare function generateInstructions(result: PackResult, options?: GenerateInstructionsOptions): GenerateInstructionsResult;
|
|
852
|
+
/**
|
|
853
|
+
* JSON Formatter for Packing Instructions
|
|
854
|
+
*/
|
|
855
|
+
/**
|
|
856
|
+
* Format instructions as JSON string
|
|
857
|
+
*/
|
|
858
|
+
export declare function formatAsJson(instructions: PackingInstructions, options: Required<GenerateInstructionsOptions>): string;
|
|
859
|
+
/**
|
|
860
|
+
* Markdown Formatter for Packing Instructions
|
|
861
|
+
*/
|
|
862
|
+
/**
|
|
863
|
+
* Format instructions as Markdown
|
|
864
|
+
*/
|
|
865
|
+
export declare function formatAsMarkdown(instructions: PackingInstructions, options: Required<GenerateInstructionsOptions>): string;
|
|
866
|
+
/**
|
|
867
|
+
* HTML Formatter for Packing Instructions
|
|
868
|
+
*
|
|
869
|
+
* Generates a print-friendly HTML document with embedded styles
|
|
870
|
+
*/
|
|
871
|
+
/**
|
|
872
|
+
* Format instructions as HTML document
|
|
873
|
+
*/
|
|
874
|
+
export declare function formatAsHtml(instructions: PackingInstructions, options: Required<GenerateInstructionsOptions>): string;
|
|
875
|
+
/**
|
|
876
|
+
* Online Packing Types
|
|
877
|
+
*
|
|
878
|
+
* Types for real-time/online bin packing where items arrive one at a time
|
|
879
|
+
* and placement decisions must be made immediately without knowing future items.
|
|
880
|
+
*/
|
|
881
|
+
/**
|
|
882
|
+
* Placement result for a single item
|
|
883
|
+
*/
|
|
884
|
+
export interface PlacementResult {
|
|
885
|
+
/** Whether the item was successfully placed */
|
|
886
|
+
success: boolean;
|
|
887
|
+
/** ID of the bin where item was placed (if successful) */
|
|
888
|
+
binId?: string;
|
|
889
|
+
/** Position where item was placed */
|
|
890
|
+
position?: Point3D;
|
|
891
|
+
/** Placed item details */
|
|
892
|
+
placedItem?: PlacedItem;
|
|
893
|
+
/** Reason for failure (if unsuccessful) */
|
|
894
|
+
reason?: "no-fit" | "weight-exceeded" | "no-bins";
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Current state of an online packer bin
|
|
898
|
+
*/
|
|
899
|
+
export interface OnlineBinState {
|
|
900
|
+
/** The bin specification */
|
|
901
|
+
bin: BinSpec;
|
|
902
|
+
/** Items currently placed in this bin */
|
|
903
|
+
items: PlacedItem[];
|
|
904
|
+
/** Current utilization (0-1) */
|
|
905
|
+
utilization: number;
|
|
906
|
+
/** Current total weight */
|
|
907
|
+
weight: number;
|
|
908
|
+
/** Remaining capacity (volume) */
|
|
909
|
+
remainingVolume: number;
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* Options for online packing
|
|
913
|
+
*/
|
|
914
|
+
export interface OnlinePackerOptions extends Pick<PackOptions, "features" | "constraints"> {
|
|
915
|
+
/** Algorithm to use for placement decisions */
|
|
916
|
+
algorithm?: "online-extreme-point" | "online-first-fit";
|
|
917
|
+
/** Strategy for selecting which bin to use */
|
|
918
|
+
binSelection?: "first-fit" | "best-fit" | "worst-fit";
|
|
919
|
+
/** Whether to automatically add new bins when needed */
|
|
920
|
+
autoAddBins?: boolean;
|
|
921
|
+
/** Template for auto-added bins (required if autoAddBins is true) */
|
|
922
|
+
binTemplate?: BinSpec;
|
|
923
|
+
/** Maximum number of bins to auto-create */
|
|
924
|
+
maxBins?: number;
|
|
925
|
+
}
|
|
926
|
+
/**
|
|
927
|
+
* Statistics for online packing session
|
|
928
|
+
*/
|
|
929
|
+
export interface OnlinePackerStats {
|
|
930
|
+
/** Total items processed */
|
|
931
|
+
totalItems: number;
|
|
932
|
+
/** Items successfully placed */
|
|
933
|
+
placedItems: number;
|
|
934
|
+
/** Items that could not be placed */
|
|
935
|
+
rejectedItems: number;
|
|
936
|
+
/** Number of bins in use */
|
|
937
|
+
binsInUse: number;
|
|
938
|
+
/** Average utilization across all bins */
|
|
939
|
+
avgUtilization: number;
|
|
940
|
+
/** Total weight packed */
|
|
941
|
+
totalWeight: number;
|
|
942
|
+
}
|
|
943
|
+
/**
|
|
944
|
+
* Event types for online packer
|
|
945
|
+
*/
|
|
946
|
+
export type OnlinePackerEventType = "item-placed" | "item-rejected" | "bin-added" | "bin-full";
|
|
947
|
+
/**
|
|
948
|
+
* Event data for online packer events
|
|
949
|
+
*/
|
|
950
|
+
export interface OnlinePackerEvent {
|
|
951
|
+
type: OnlinePackerEventType;
|
|
952
|
+
item?: ItemSpec;
|
|
953
|
+
bin?: BinSpec;
|
|
954
|
+
placement?: PlacementResult;
|
|
955
|
+
timestamp: number;
|
|
956
|
+
}
|
|
957
|
+
/**
|
|
958
|
+
* Event listener type
|
|
959
|
+
*/
|
|
960
|
+
export type OnlinePackerEventListener = (event: OnlinePackerEvent) => void;
|
|
961
|
+
/**
|
|
962
|
+
* Online Packer
|
|
963
|
+
*
|
|
964
|
+
* A stateful packer for real-time/online bin packing scenarios where items
|
|
965
|
+
* arrive one at a time and placement decisions must be made immediately.
|
|
966
|
+
*
|
|
967
|
+
* Key differences from offline packing:
|
|
968
|
+
* - Items are processed one at a time as they arrive
|
|
969
|
+
* - No knowledge of future items
|
|
970
|
+
* - Placement decisions are immediate and irreversible
|
|
971
|
+
* - State is maintained between item placements
|
|
972
|
+
*/
|
|
973
|
+
/**
|
|
974
|
+
* Online Packer Class
|
|
975
|
+
*
|
|
976
|
+
* Handles real-time bin packing where items arrive sequentially.
|
|
977
|
+
*/
|
|
978
|
+
export declare class OnlinePacker {
|
|
979
|
+
private options;
|
|
980
|
+
private binStates;
|
|
981
|
+
private binOrder;
|
|
982
|
+
private stats;
|
|
983
|
+
private eventListeners;
|
|
984
|
+
private autoAddCounter;
|
|
985
|
+
constructor(options?: OnlinePackerOptions & {
|
|
986
|
+
bins?: BinSpec[];
|
|
987
|
+
});
|
|
988
|
+
/**
|
|
989
|
+
* Add a new bin to the packer
|
|
990
|
+
*/
|
|
991
|
+
addBin(bin: BinSpec): void;
|
|
992
|
+
/**
|
|
993
|
+
* Remove a bin from the packer
|
|
994
|
+
*/
|
|
995
|
+
removeBin(binId: string): OnlineBinState | null;
|
|
996
|
+
/**
|
|
997
|
+
* Place a single item immediately
|
|
998
|
+
*
|
|
999
|
+
* This is the core method for online packing. It attempts to place
|
|
1000
|
+
* the item in one of the available bins using the configured algorithm.
|
|
1001
|
+
*/
|
|
1002
|
+
placeItem(item: ItemSpec): PlacementResult;
|
|
1003
|
+
/**
|
|
1004
|
+
* Check if an item can possibly fit in the bin template
|
|
1005
|
+
*/
|
|
1006
|
+
private canFitInTemplate;
|
|
1007
|
+
/**
|
|
1008
|
+
* Find a valid placement for an item across all bins
|
|
1009
|
+
*/
|
|
1010
|
+
private findPlacement;
|
|
1011
|
+
/**
|
|
1012
|
+
* Find placement within a specific bin
|
|
1013
|
+
*/
|
|
1014
|
+
private findPlacementInBin;
|
|
1015
|
+
/**
|
|
1016
|
+
* Update extreme points after placing an item
|
|
1017
|
+
*/
|
|
1018
|
+
private updateExtremePoints;
|
|
1019
|
+
/**
|
|
1020
|
+
* Get bin order based on selection strategy
|
|
1021
|
+
*/
|
|
1022
|
+
private getBinOrder;
|
|
1023
|
+
/**
|
|
1024
|
+
* Automatically add a new bin
|
|
1025
|
+
*/
|
|
1026
|
+
private autoAddBin;
|
|
1027
|
+
/**
|
|
1028
|
+
* Update average utilization statistic
|
|
1029
|
+
*/
|
|
1030
|
+
private updateAvgUtilization;
|
|
1031
|
+
/**
|
|
1032
|
+
* Get current statistics
|
|
1033
|
+
*/
|
|
1034
|
+
getStats(): OnlinePackerStats;
|
|
1035
|
+
/**
|
|
1036
|
+
* Get state of a specific bin
|
|
1037
|
+
*/
|
|
1038
|
+
getBinState(binId: string): OnlineBinState | null;
|
|
1039
|
+
/**
|
|
1040
|
+
* Get states of all bins
|
|
1041
|
+
*/
|
|
1042
|
+
getAllBinStates(): OnlineBinState[];
|
|
1043
|
+
/**
|
|
1044
|
+
* Get list of bin IDs
|
|
1045
|
+
*/
|
|
1046
|
+
getBinIds(): string[];
|
|
1047
|
+
/**
|
|
1048
|
+
* Reset the packer to initial state
|
|
1049
|
+
*/
|
|
1050
|
+
reset(): void;
|
|
1051
|
+
/**
|
|
1052
|
+
* Subscribe to events
|
|
1053
|
+
*/
|
|
1054
|
+
on(event: OnlinePackerEventType, listener: OnlinePackerEventListener): () => void;
|
|
1055
|
+
/**
|
|
1056
|
+
* Emit an event
|
|
1057
|
+
*/
|
|
1058
|
+
private emit;
|
|
1059
|
+
/**
|
|
1060
|
+
* Generate initial extreme points considering exclude zones
|
|
1061
|
+
*/
|
|
1062
|
+
private generateInitialExtremePoints;
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Pallet standard sizes
|
|
1066
|
+
*/
|
|
1067
|
+
export interface PalletStandard {
|
|
1068
|
+
width: number;
|
|
1069
|
+
depth: number;
|
|
1070
|
+
height: number;
|
|
1071
|
+
name: string;
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Standard pallet sizes (in mm)
|
|
1075
|
+
*/
|
|
1076
|
+
export declare const PALLET_STANDARDS: {
|
|
1077
|
+
readonly EUR1: {
|
|
1078
|
+
readonly width: 800;
|
|
1079
|
+
readonly depth: 1200;
|
|
1080
|
+
readonly height: 144;
|
|
1081
|
+
readonly name: "EUR1 (Euro Pallet)";
|
|
1082
|
+
};
|
|
1083
|
+
readonly EUR2: {
|
|
1084
|
+
readonly width: 1200;
|
|
1085
|
+
readonly depth: 1000;
|
|
1086
|
+
readonly height: 144;
|
|
1087
|
+
readonly name: "EUR2";
|
|
1088
|
+
};
|
|
1089
|
+
readonly EUR3: {
|
|
1090
|
+
readonly width: 1000;
|
|
1091
|
+
readonly depth: 1200;
|
|
1092
|
+
readonly height: 144;
|
|
1093
|
+
readonly name: "EUR3";
|
|
1094
|
+
};
|
|
1095
|
+
readonly EUR6: {
|
|
1096
|
+
readonly width: 600;
|
|
1097
|
+
readonly depth: 800;
|
|
1098
|
+
readonly height: 144;
|
|
1099
|
+
readonly name: "EUR6 (Half Pallet)";
|
|
1100
|
+
};
|
|
1101
|
+
readonly US: {
|
|
1102
|
+
readonly width: 1016;
|
|
1103
|
+
readonly depth: 1219;
|
|
1104
|
+
readonly height: 150;
|
|
1105
|
+
readonly name: "US (40\"\u00D748\")";
|
|
1106
|
+
};
|
|
1107
|
+
readonly US_GROCERY: {
|
|
1108
|
+
readonly width: 1016;
|
|
1109
|
+
readonly depth: 1219;
|
|
1110
|
+
readonly height: 150;
|
|
1111
|
+
readonly name: "US Grocery";
|
|
1112
|
+
};
|
|
1113
|
+
readonly ASIA: {
|
|
1114
|
+
readonly width: 1100;
|
|
1115
|
+
readonly depth: 1100;
|
|
1116
|
+
readonly height: 150;
|
|
1117
|
+
readonly name: "Asia Standard";
|
|
1118
|
+
};
|
|
1119
|
+
readonly AUSTRALIA: {
|
|
1120
|
+
readonly width: 1165;
|
|
1121
|
+
readonly depth: 1165;
|
|
1122
|
+
readonly height: 150;
|
|
1123
|
+
readonly name: "Australia Standard";
|
|
1124
|
+
};
|
|
1125
|
+
};
|
|
1126
|
+
export type PalletStandardName = keyof typeof PALLET_STANDARDS;
|
|
1127
|
+
/**
|
|
1128
|
+
* Get pallet standard by name
|
|
1129
|
+
*/
|
|
1130
|
+
export declare function getPalletStandard(name: PalletStandardName): PalletStandard;
|
|
1131
|
+
/**
|
|
1132
|
+
* Pallet packing function
|
|
1133
|
+
*/
|
|
1134
|
+
export interface PalletOptions {
|
|
1135
|
+
/** Pallet size - standard name or custom dimensions */
|
|
1136
|
+
palletSize?: PalletStandardName | {
|
|
1137
|
+
width: number;
|
|
1138
|
+
depth: number;
|
|
1139
|
+
};
|
|
1140
|
+
/** Maximum stack height (mm) */
|
|
1141
|
+
maxHeight?: number;
|
|
1142
|
+
/** Maximum weight (kg) */
|
|
1143
|
+
maxWeight?: number;
|
|
1144
|
+
/** Algorithm to use */
|
|
1145
|
+
algorithm?: "layer-building" | "eb-afit" | "extreme-point";
|
|
1146
|
+
/** Additional pack options */
|
|
1147
|
+
packOptions?: Partial<PackOptions>;
|
|
1148
|
+
}
|
|
1149
|
+
export interface PalletResult extends PackResult {
|
|
1150
|
+
/** Pallet specification used */
|
|
1151
|
+
palletSpec: BinSpec;
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Pack items onto a pallet
|
|
1155
|
+
*/
|
|
1156
|
+
export declare function packPallet(items: ItemSpec[], options?: PalletOptions): PalletResult;
|
|
1157
|
+
/**
|
|
1158
|
+
* Container standard sizes
|
|
1159
|
+
*/
|
|
1160
|
+
export interface ContainerStandard {
|
|
1161
|
+
width: number;
|
|
1162
|
+
height: number;
|
|
1163
|
+
depth: number;
|
|
1164
|
+
maxWeight: number;
|
|
1165
|
+
name: string;
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Standard container sizes (internal dimensions in mm, weight in kg)
|
|
1169
|
+
*/
|
|
1170
|
+
export declare const CONTAINER_STANDARDS: {
|
|
1171
|
+
readonly "20ft": {
|
|
1172
|
+
readonly width: 2352;
|
|
1173
|
+
readonly height: 2393;
|
|
1174
|
+
readonly depth: 5898;
|
|
1175
|
+
readonly maxWeight: 21770;
|
|
1176
|
+
readonly name: "20ft Standard";
|
|
1177
|
+
};
|
|
1178
|
+
readonly "40ft": {
|
|
1179
|
+
readonly width: 2352;
|
|
1180
|
+
readonly height: 2393;
|
|
1181
|
+
readonly depth: 12032;
|
|
1182
|
+
readonly maxWeight: 26680;
|
|
1183
|
+
readonly name: "40ft Standard";
|
|
1184
|
+
};
|
|
1185
|
+
readonly "40ftHC": {
|
|
1186
|
+
readonly width: 2352;
|
|
1187
|
+
readonly height: 2698;
|
|
1188
|
+
readonly depth: 12032;
|
|
1189
|
+
readonly maxWeight: 26460;
|
|
1190
|
+
readonly name: "40ft High Cube";
|
|
1191
|
+
};
|
|
1192
|
+
readonly "45ftHC": {
|
|
1193
|
+
readonly width: 2352;
|
|
1194
|
+
readonly height: 2698;
|
|
1195
|
+
readonly depth: 13556;
|
|
1196
|
+
readonly maxWeight: 25600;
|
|
1197
|
+
readonly name: "45ft High Cube";
|
|
1198
|
+
};
|
|
1199
|
+
};
|
|
1200
|
+
export type ContainerStandardName = keyof typeof CONTAINER_STANDARDS;
|
|
1201
|
+
/**
|
|
1202
|
+
* Get container standard by name
|
|
1203
|
+
*/
|
|
1204
|
+
export declare function getContainerStandard(name: ContainerStandardName): ContainerStandard;
|
|
1205
|
+
/**
|
|
1206
|
+
* Container packing function
|
|
1207
|
+
*/
|
|
1208
|
+
export interface ContainerOptions {
|
|
1209
|
+
/** Container size - standard name or custom dimensions */
|
|
1210
|
+
containerSize?: ContainerStandardName | {
|
|
1211
|
+
width: number;
|
|
1212
|
+
height: number;
|
|
1213
|
+
depth: number;
|
|
1214
|
+
};
|
|
1215
|
+
/** Maximum weight (kg) */
|
|
1216
|
+
maxWeight?: number;
|
|
1217
|
+
/** Loading direction */
|
|
1218
|
+
loadingDirection?: "rear" | "side";
|
|
1219
|
+
/** Respect delivery order (LIFO) */
|
|
1220
|
+
respectDeliveryOrder?: boolean;
|
|
1221
|
+
/** Algorithm to use */
|
|
1222
|
+
algorithm?: "wall-building" | "extreme-point" | "layer-building";
|
|
1223
|
+
/** Additional pack options */
|
|
1224
|
+
packOptions?: Partial<PackOptions>;
|
|
1225
|
+
}
|
|
1226
|
+
export interface ContainerResult extends PackResult {
|
|
1227
|
+
/** Container specification used */
|
|
1228
|
+
containerSpec: BinSpec;
|
|
1229
|
+
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Pack items into a container
|
|
1232
|
+
*/
|
|
1233
|
+
export declare function packContainer(items: ItemSpec[], options?: ContainerOptions): ContainerResult;
|
|
1234
|
+
/**
|
|
1235
|
+
* Truck loading function
|
|
1236
|
+
*/
|
|
1237
|
+
export interface TruckOptions {
|
|
1238
|
+
/** Truck cargo dimensions */
|
|
1239
|
+
truckSize: {
|
|
1240
|
+
width: number;
|
|
1241
|
+
height: number;
|
|
1242
|
+
depth: number;
|
|
1243
|
+
};
|
|
1244
|
+
/** Maximum weight (kg) */
|
|
1245
|
+
maxWeight?: number;
|
|
1246
|
+
/** Axle weight limits */
|
|
1247
|
+
axleWeights?: {
|
|
1248
|
+
front: number;
|
|
1249
|
+
rear: number;
|
|
1250
|
+
};
|
|
1251
|
+
/** Wheelbase position (distance from front) */
|
|
1252
|
+
wheelbase?: number;
|
|
1253
|
+
/** Front axle position from cargo area start */
|
|
1254
|
+
frontAxleOffset?: number;
|
|
1255
|
+
/** Algorithm to use */
|
|
1256
|
+
algorithm?: "wall-building" | "extreme-point";
|
|
1257
|
+
/** Additional pack options */
|
|
1258
|
+
packOptions?: Partial<PackOptions>;
|
|
1259
|
+
}
|
|
1260
|
+
export interface AxleWeightResult {
|
|
1261
|
+
front: number;
|
|
1262
|
+
rear: number;
|
|
1263
|
+
isValid: boolean;
|
|
1264
|
+
}
|
|
1265
|
+
export interface TruckResult extends PackResult {
|
|
1266
|
+
/** Truck specification used */
|
|
1267
|
+
truckSpec: BinSpec;
|
|
1268
|
+
/** Calculated axle weights */
|
|
1269
|
+
axleWeights: AxleWeightResult;
|
|
1270
|
+
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Calculate axle weights based on item positions
|
|
1273
|
+
*/
|
|
1274
|
+
export declare function calcAxleWeights(items: PlacedItem[], truckDepth: number, wheelbase?: number, frontAxleOffset?: number): AxleWeightResult;
|
|
1275
|
+
/**
|
|
1276
|
+
* Pack items into a truck
|
|
1277
|
+
*/
|
|
1278
|
+
export declare function packTruck(items: ItemSpec[], options: TruckOptions): TruckResult;
|
|
1279
|
+
|
|
1280
|
+
export {};
|