Passed
Push — 3.x ( 3ac6d2...8ba8a4 )
by Doug
02:05
created

OrientatedItem::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 7
c 3
b 0
f 0
nc 1
nop 4
dl 0
loc 10
ccs 8
cts 8
cp 1
crap 1
rs 10
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 atan;
12
use JsonSerializable;
13
use function min;
14
use function sort;
15
16
/**
17
 * An item to be packed.
18
 *
19
 * @author Doug Wright
20
 */
21
class OrientatedItem implements JsonSerializable
22
{
23
    /**
24
     * @var Item
25
     */
26
    protected $item;
27
28
    /**
29
     * @var int
30
     */
31
    protected $width;
32
33
    /**
34
     * @var int
35
     */
36
    protected $length;
37
38
    /**
39
     * @var int
40
     */
41
    protected $depth;
42
43
    /**
44
     * @var int
45
     */
46
    protected $surfaceFootprint;
47
48
    /**
49
     * @var bool[]
50
     */
51
    protected static $stabilityCache = [];
52
53
    /**
54
     * @var array
55
     */
56
    protected $dimensionsAsArray;
57
58
    /**
59
     * Constructor.
60
     */
61 55
    public function __construct(Item $item, int $width, int $length, int $depth)
62
    {
63 55
        $this->item = $item;
64 55
        $this->width = $width;
65 55
        $this->length = $length;
66 55
        $this->depth = $depth;
67 55
        $this->surfaceFootprint = $width * $length;
68
69 55
        $this->dimensionsAsArray = [$width, $length, $depth];
70 55
        sort($this->dimensionsAsArray);
71 55
    }
72
73
    /**
74
     * Item.
75
     */
76 54
    public function getItem(): Item
77
    {
78 54
        return $this->item;
79
    }
80
81
    /**
82
     * Item width in mm in it's packed orientation.
83
     */
84 54
    public function getWidth(): int
85
    {
86 54
        return $this->width;
87
    }
88
89
    /**
90
     * Item length in mm in it's packed orientation.
91
     */
92 54
    public function getLength(): int
93
    {
94 54
        return $this->length;
95
    }
96
97
    /**
98
     * Item depth in mm in it's packed orientation.
99
     */
100 54
    public function getDepth(): int
101
    {
102 54
        return $this->depth;
103
    }
104
105
    /**
106
     * Calculate the surface footprint of the current orientation.
107
     */
108 39
    public function getSurfaceFootprint(): int
109
    {
110 39
        return $this->surfaceFootprint;
111
    }
112
113
    /**
114
     * Is this item stable (low centre of gravity), calculated as if the tipping point is >15 degrees.
115
     *
116
     * N.B. Assumes equal weight distribution.
117
     */
118 54
    public function isStable(): bool
119
    {
120 54
        $cacheKey = $this->width . '|' . $this->length . '|' . $this->depth;
121
122 54
        return static::$stabilityCache[$cacheKey] ?? (static::$stabilityCache[$cacheKey] = atan(min($this->length, $this->width) / ($this->depth ?: 1)) > 0.261);
123
    }
124
125
    /**
126
     * Is the supplied item the same size as this one?
127
     *
128
     * @internal
129
     */
130 52
    public function isSameDimensions(Item $item): bool
131
    {
132 52
        if ($item === $this->item) {
133 35
            return true;
134
        }
135
136 29
        $itemDimensions = [$item->getWidth(), $item->getLength(), $item->getDepth()];
137 29
        sort($itemDimensions);
138
139 29
        return $this->dimensionsAsArray === $itemDimensions;
140
    }
141
142
    /**
143
     * {@inheritdoc}
144
     */
145 1
    public function jsonSerialize()
146
    {
147
        return [
148 1
            'item' => $this->item,
149 1
            'width' => $this->width,
150 1
            'length' => $this->length,
151 1
            'depth' => $this->depth,
152
        ];
153
    }
154
155 1
    public function __toString(): string
156
    {
157 1
        return $this->width . '|' . $this->length . '|' . $this->depth;
158
    }
159
}
160