1 | <?php |
||
2 | /** |
||
3 | * Box packing (3D bin packing, knapsack problem). |
||
4 | * |
||
5 | * @author Doug Wright |
||
6 | */ |
||
7 | declare(strict_types=1); |
||
8 | |||
9 | namespace DVDoug\BoxPacker; |
||
10 | |||
11 | use function max; |
||
12 | use function min; |
||
13 | |||
14 | /** |
||
15 | * A packed layer. |
||
16 | * @internal |
||
17 | */ |
||
18 | class PackedLayer |
||
19 | { |
||
20 | /** |
||
21 | * @var PackedItem[] |
||
22 | */ |
||
23 | protected array $items = []; |
||
24 | |||
25 | /** |
||
26 | * Add a packed item to this layer. |
||
27 | */ |
||
28 | 97 | public function insert(PackedItem $packedItem): void |
|
29 | { |
||
30 | 97 | $this->items[] = $packedItem; |
|
31 | } |
||
32 | |||
33 | /** |
||
34 | * Get the packed items. |
||
35 | * |
||
36 | * @return PackedItem[] |
||
37 | */ |
||
38 | 99 | public function getItems(): array |
|
39 | { |
||
40 | 99 | return $this->items; |
|
41 | } |
||
42 | |||
43 | /** |
||
44 | * Calculate footprint area of this layer. |
||
45 | * |
||
46 | * @return int mm^2 |
||
47 | */ |
||
48 | 49 | public function getFootprint(): int |
|
49 | { |
||
50 | 49 | return $this->getWidth() * $this->getLength(); |
|
51 | } |
||
52 | |||
53 | 1 | public function getStartX(): int |
|
54 | { |
||
55 | 1 | if (!$this->items) { |
|
0 ignored issues
–
show
|
|||
56 | return 0; |
||
57 | } |
||
58 | |||
59 | 1 | $values = []; |
|
60 | 1 | foreach ($this->items as $item) { |
|
61 | 1 | $values[] = $item->x; |
|
62 | } |
||
63 | |||
64 | 1 | return min($values); |
|
65 | } |
||
66 | |||
67 | 97 | public function getEndX(): int |
|
68 | { |
||
69 | 97 | if (!$this->items) { |
|
0 ignored issues
–
show
The expression
$this->items of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
70 | return 0; |
||
71 | } |
||
72 | |||
73 | 97 | $values = []; |
|
74 | 97 | foreach ($this->items as $item) { |
|
75 | 97 | $values[] = $item->x + $item->width; |
|
76 | } |
||
77 | |||
78 | 97 | return max($values); |
|
79 | } |
||
80 | |||
81 | 49 | public function getWidth(): int |
|
82 | { |
||
83 | 49 | if (!$this->items) { |
|
0 ignored issues
–
show
The expression
$this->items of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
84 | return 0; |
||
85 | } |
||
86 | |||
87 | 49 | $start = []; |
|
88 | 49 | $end = []; |
|
89 | 49 | foreach ($this->items as $item) { |
|
90 | 49 | $start[] = $item->x; |
|
91 | 49 | $end[] = $item->x + $item->width; |
|
92 | } |
||
93 | |||
94 | 49 | return max($end) - min($start); |
|
95 | } |
||
96 | |||
97 | 1 | public function getStartY(): int |
|
98 | { |
||
99 | 1 | if (!$this->items) { |
|
0 ignored issues
–
show
The expression
$this->items of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
100 | return 0; |
||
101 | } |
||
102 | |||
103 | 1 | $values = []; |
|
104 | 1 | foreach ($this->items as $item) { |
|
105 | 1 | $values[] = $item->y; |
|
106 | } |
||
107 | |||
108 | 1 | return min($values); |
|
109 | } |
||
110 | |||
111 | 97 | public function getEndY(): int |
|
112 | { |
||
113 | 97 | if (!$this->items) { |
|
0 ignored issues
–
show
The expression
$this->items of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
114 | 95 | return 0; |
|
115 | } |
||
116 | |||
117 | 97 | $values = []; |
|
118 | 97 | foreach ($this->items as $item) { |
|
119 | 97 | $values[] = $item->y + $item->length; |
|
120 | } |
||
121 | |||
122 | 97 | return max($values); |
|
123 | } |
||
124 | |||
125 | 49 | public function getLength(): int |
|
126 | { |
||
127 | 49 | if (!$this->items) { |
|
0 ignored issues
–
show
The expression
$this->items of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
128 | return 0; |
||
129 | } |
||
130 | |||
131 | 49 | $start = []; |
|
132 | 49 | $end = []; |
|
133 | 49 | foreach ($this->items as $item) { |
|
134 | 49 | $start[] = $item->y; |
|
135 | 49 | $end[] = $item->y + $item->length; |
|
136 | } |
||
137 | |||
138 | 49 | return max($end) - min($start); |
|
139 | } |
||
140 | |||
141 | 96 | public function getStartZ(): int |
|
142 | { |
||
143 | 96 | if (!$this->items) { |
|
0 ignored issues
–
show
The expression
$this->items of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
144 | return 0; |
||
145 | } |
||
146 | |||
147 | 96 | $values = []; |
|
148 | 96 | foreach ($this->items as $item) { |
|
149 | 96 | $values[] = $item->z; |
|
150 | } |
||
151 | |||
152 | 96 | return min($values); |
|
153 | } |
||
154 | |||
155 | 1 | public function getEndZ(): int |
|
156 | { |
||
157 | 1 | if (!$this->items) { |
|
0 ignored issues
–
show
The expression
$this->items of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
158 | return 0; |
||
159 | } |
||
160 | |||
161 | 1 | $values = []; |
|
162 | 1 | foreach ($this->items as $item) { |
|
163 | 1 | $values[] = $item->z + $item->depth; |
|
164 | } |
||
165 | |||
166 | 1 | return max($values); |
|
167 | } |
||
168 | |||
169 | 97 | public function getDepth(): int |
|
170 | { |
||
171 | 97 | if (!$this->items) { |
|
0 ignored issues
–
show
The expression
$this->items of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
172 | return 0; |
||
173 | } |
||
174 | |||
175 | 97 | $start = []; |
|
176 | 97 | $end = []; |
|
177 | 97 | foreach ($this->items as $item) { |
|
178 | 97 | $start[] = $item->z; |
|
179 | 97 | $end[] = $item->z + $item->depth; |
|
180 | } |
||
181 | |||
182 | 97 | return max($end) - min($start); |
|
183 | } |
||
184 | |||
185 | 1 | public function getWeight(): int |
|
186 | { |
||
187 | 1 | $weight = 0; |
|
188 | 1 | foreach ($this->items as $item) { |
|
189 | 1 | $weight += $item->item->getWeight(); |
|
190 | } |
||
191 | |||
192 | 1 | return $weight; |
|
193 | } |
||
194 | |||
195 | 96 | public function merge(self $otherLayer): void |
|
196 | { |
||
197 | 96 | foreach ($otherLayer->items as $packedItem) { |
|
198 | 23 | $this->items[] = $packedItem; |
|
199 | } |
||
200 | } |
||
201 | } |
||
202 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.