Passed
Push — 1.x-dev ( 8f914b...081a6e )
by Doug
04:31
created

PackedBox::getPackedItems()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 6
ccs 3
cts 4
cp 0.75
crap 2.0625
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Box packing (3D bin packing, knapsack problem).
4
 *
5
 * @author Doug Wright
6
 */
7
8
namespace DVDoug\BoxPacker;
9
10
use RuntimeException;
11
12
/**
13
 * A "box" with items.
14
 *
15
 * @author Doug Wright
16
 */
17
class PackedBox
18
{
19
    /**
20
     * Box used.
21
     *
22
     * @var Box
23
     */
24
    protected $box;
25
26
    /**
27
     * Items in the box.
28
     *
29
     * @var ItemList
30
     */
31
    protected $items;
32
33
    /**
34
     * Total weight of box.
35
     *
36
     * @var int
37
     */
38
    protected $weight;
39
40
    /**
41
     * Total weight of items in the box.
42
     *
43
     * @var int
44
     */
45
    protected $itemWeight;
46
47
    /**
48
     * Remaining width inside box for another item.
49
     *
50
     * @var int
51
     */
52
    protected $remainingWidth;
53
54
    /**
55
     * Remaining length inside box for another item.
56
     *
57
     * @var int
58
     */
59
    protected $remainingLength;
60
61
    /**
62
     * Remaining depth inside box for another item.
63
     *
64
     * @var int
65
     */
66
    protected $remainingDepth;
67
68
    /**
69
     * Remaining weight inside box for another item.
70
     *
71
     * @var int
72
     */
73
    protected $remainingWeight;
74
75
    /**
76
     * Used width inside box for packing items.
77
     *
78
     * @var int
79
     */
80
    protected $usedWidth;
81
82
    /**
83
     * Used length inside box for packing items.
84
     *
85
     * @var int
86
     */
87
    protected $usedLength;
88
89
    /**
90
     * Used depth inside box for packing items.
91
     *
92
     * @var int
93
     */
94
    protected $usedDepth;
95
96
    /**
97
     * @var PackedItemList
98
     */
99
    protected $packedItemList;
100
101
    /**
102
     * Get box used.
103
     *
104
     * @return Box
105
     */
106 6
    public function getBox()
107
    {
108 6
        return $this->box;
109
    }
110
111
    /**
112
     * Get items packed.
113
     *
114
     * @return ItemList
115
     */
116 20
    public function getItems()
117
    {
118 20
        return $this->items;
119
    }
120
121
    /**
122
     * Get packed weight.
123
     *
124
     * @return int weight in grams
125
     */
126 2
    public function getWeight()
127
    {
128 2
        return $this->box->getEmptyWeight() + $this->getItemWeight();
129
    }
130
131
    /**
132
     * Get packed weight of the items only.
133
     *
134
     * @return int weight in grams
135
     */
136 3
    public function getItemWeight()
137
    {
138 3
        if (!is_null($this->itemWeight)) {
0 ignored issues
show
introduced by
The condition is_null($this->itemWeight) is always false.
Loading history...
139 1
            return $this->itemWeight;
140
        }
141 3
        $this->itemWeight = 0;
142
        /** @var Item $item */
143 3
        foreach (clone $this->items as $item) {
144 3
            $this->itemWeight += $item->getWeight();
145
        }
146
147 3
        return $this->itemWeight;
148
    }
149
150
    /**
151
     * Get remaining width inside box for another item.
152
     *
153
     * @return int
154
     */
155 1
    public function getRemainingWidth()
156
    {
157 1
        return $this->remainingWidth;
158
    }
159
160
    /**
161
     * Get remaining length inside box for another item.
162
     *
163
     * @return int
164
     */
165 1
    public function getRemainingLength()
166
    {
167 1
        return $this->remainingLength;
168
    }
169
170
    /**
171
     * Get remaining depth inside box for another item.
172
     *
173
     * @return int
174
     */
175 1
    public function getRemainingDepth()
176
    {
177 1
        return $this->remainingDepth;
178
    }
179
180
    /**
181
     * Used width inside box for packing items.
182
     *
183
     * @return int
184
     */
185
    public function getUsedWidth()
186
    {
187
        return $this->usedWidth;
188
    }
189
190
    /**
191
     * Used length inside box for packing items.
192
     *
193
     * @return int
194
     */
195
    public function getUsedLength()
196
    {
197
        return $this->usedLength;
198
    }
199
200
    /**
201
     * Used depth inside box for packing items.
202
     *
203
     * @return int
204
     */
205
    public function getUsedDepth()
206
    {
207
        return $this->usedDepth;
208
    }
209
210
    /**
211
     * Get remaining weight inside box for another item.
212
     *
213
     * @return int
214
     */
215 1
    public function getRemainingWeight()
216
    {
217 1
        return $this->remainingWeight;
218
    }
219
220
    /**
221
     * @return int
222
     */
223 2
    public function getInnerVolume()
224
    {
225 2
        return $this->box->getInnerWidth() * $this->box->getInnerLength() * $this->box->getInnerDepth();
226
    }
227
228
    /**
229
     * Get used volume of the packed box.
230
     *
231
     * @return int
232
     */
233 2
    public function getUsedVolume()
234
    {
235 2
        $volume = 0;
236
        /** @var PackedItem $item */
237 2
        foreach (clone $this->items as $item) {
238 2
            $volume += $item->getVolume();
239
        }
240
241 2
        return $volume;
242
    }
243
244
    /**
245
     * Get unused volume of the packed box.
246
     *
247
     * @return int
248
     */
249 1
    public function getUnusedVolume()
250
    {
251 1
        return $this->getInnerVolume() - $this->getUsedVolume();
252
    }
253
254
    /**
255
     * Get volume utilisation of the packed box.
256
     *
257
     * @return float
258
     */
259 2
    public function getVolumeUtilisation()
260
    {
261 2
        $itemVolume = 0;
262
263
        /** @var Item $item */
264 2
        foreach (clone $this->items as $item) {
265 2
            $itemVolume += $item->getVolume();
266
        }
267
268 2
        return round($itemVolume / $this->box->getInnerVolume() * 100, 1);
269
    }
270
271
    /**
272
     * @return PackedItemList
273
     */
274 1
    public function getPackedItems()
275
    {
276 1
        if (!$this->packedItemList instanceof PackedItemList) {
0 ignored issues
show
introduced by
$this->packedItemList is always a sub-type of DVDoug\BoxPacker\PackedItemList.
Loading history...
277
            throw new RuntimeException('No PackedItemList was set. Are you using the old constructor?');
278
        }
279 1
        return $this->packedItemList;
280
    }
281
282
    /**
283
     * @param PackedItemList $packedItemList
284
     */
285 22
    public function setPackedItems(PackedItemList $packedItemList)
286
    {
287 22
        $this->packedItemList = $packedItemList;
288 22
    }
289
290
    /**
291
     * Legacy constructor.
292
     *
293
     * @deprecated
294
     *
295
     * @param Box      $box
296
     * @param ItemList $itemList
297
     * @param int      $remainingWidth
298
     * @param int      $remainingLength
299
     * @param int      $remainingDepth
300
     * @param int      $remainingWeight
301
     * @param int      $usedWidth
302
     * @param int      $usedLength
303
     * @param int      $usedDepth
304
     */
305 22
    public function __construct(
306
        Box $box,
307
        ItemList $itemList,
308
        $remainingWidth,
309
        $remainingLength,
310
        $remainingDepth,
311
        $remainingWeight,
312
        $usedWidth,
313
        $usedLength,
314
        $usedDepth
315
    ) {
316 22
        $this->box = $box;
317 22
        $this->items = $itemList;
318 22
        $this->remainingWidth = $remainingWidth;
319 22
        $this->remainingLength = $remainingLength;
320 22
        $this->remainingDepth = $remainingDepth;
321 22
        $this->remainingWeight = $remainingWeight;
322 22
        $this->usedWidth = $usedWidth;
323 22
        $this->usedLength = $usedLength;
324 22
        $this->usedDepth = $usedDepth;
325 22
    }
326
327
    /**
328
     * The constructor from v3.
329
     *
330
     * @param Box            $box
331
     * @param PackedItemList $packedItems
332
     *
333
     * @return self
334
     */
335 22
    public static function fromPackedItemList(Box $box, PackedItemList $packedItems)
336
    {
337 22
        $maxWidth = $maxLength = $maxDepth = $weight = 0;
338
        /** @var PackedItem $item */
339 22
        foreach (clone $packedItems as $item) {
340 22
            $maxWidth = max($maxWidth, $item->getX() + $item->getWidth());
341 22
            $maxLength = max($maxLength, $item->getY() + $item->getLength());
342 22
            $maxDepth = max($maxDepth, $item->getZ() + $item->getDepth());
343 22
            $weight += $item->getItem()->getWeight();
344
        }
345
346 22
        $packedBox = new self(
347 22
            $box,
348 22
            $packedItems->asItemList(),
349 22
            $box->getInnerWidth() - $maxWidth,
350 22
            $box->getInnerLength() - $maxLength,
351 22
            $box->getInnerDepth() - $maxDepth,
352 22
            $box->getMaxWeight() - $box->getEmptyWeight() - $weight,
353 22
            $maxWidth,
354 22
            $maxLength,
355 22
            $maxDepth
356
        );
357 22
        $packedBox->setPackedItems($packedItems);
358
359 22
        return $packedBox;
360
    }
361
}
362