%PDF- %PDF-
Direktori : /home/bitrix/www/bitrix/modules/sale/lib/delivery/packing/ |
Current File : //home/bitrix/www/bitrix/modules/sale/lib/delivery/packing/container.php |
<? namespace Bitrix\Sale\Delivery\Packing; use Bitrix\Main\ArgumentOutOfRangeException; use Bitrix\Main\SystemException; /** * Class Container * Contains Boxes * @package Bitrix\Sale\Delivery\Packing */ class Container { /** @var Box[] Boxes list.*/ protected $boxes = array(); protected $availableVertexes = array( array (0,0,0) ); /** * @param int[] $boxDims Point move box to * @return bool */ public function addBox(array $boxDims) { $box = new Box($boxDims); foreach($this->availableVertexes as $vId => $v) { $box->move($v); if(!$this->isVertexSuitable($box)) continue; $this->boxes[] = $box; unset($this->availableVertexes[$vId]); $this->refreshVertexesAfterBoxAdd($box); return true; } return false; } public function addBoxToVertex(array $boxDims, $vertexIdx) { if(!isset($this->availableVertexes[$vertexIdx])) throw new SystemException('No such vertex'); $box = new Box($boxDims); $box->move($this->availableVertexes[$vertexIdx]); if(!$this->isVertexSuitable($box)) return false; $this->boxes[] = $box; unset($this->availableVertexes[$vertexIdx]); $this->refreshVertexesAfterBoxAdd($box); return true; } public function extractLastBox() { /** @var Box $box */ $box = array_pop($this->boxes); $this->availableVertexes[] = $box->getVMin(); usort($this->availableVertexes, __CLASS__.'::distanceCompare'); $box->move(array(0,0,0)); return $box; } public function insertBox(Box $box, $vertexId = 0) { $box->move($this->availableVertexes[$vertexId]); if($this->isVertexSuitable($box)) { $this->boxes[] = $box; unset($this->availableVertexes[$vertexId]); $this->refreshVertexesAfterBoxAdd($box); return true; } return false; } protected function refreshVertexesAfterBoxAdd(Box $box) { $bVert = $box->getVertexes(); $this->availableVertexes[] = array($bVert[1][0], $bVert[0][1], $bVert[0][2]); $this->availableVertexes[] = array($bVert[0][0], $bVert[1][1], $bVert[0][2]); $this->availableVertexes[] = array($bVert[0][0], $bVert[0][1], $bVert[1][2]); $this->availableVertexes[] = array($bVert[1][0], $bVert[1][1], $bVert[0][2]); usort($this->availableVertexes, __CLASS__.'::distanceCompare'); } /** * @return Box[] */ public function getBoxes() { $result = array(); foreach($this->boxes as $box) $result[] = clone $box; return $result; } public function getAvailableVertexes() { return $this->availableVertexes; } /** * Check if box can be added * @param Box $newBox * @return bool */ protected function isVertexSuitable(Box $newBox) { $result = true; foreach($this->boxes as $existBox) { if($this->isBoxesIntersects($existBox, $newBox)) { return false; break; } } return $result; } /** * Checks if boxes intersect * @param Box $box1 * @param Box $box2 * @return bool */ protected static function isBoxesIntersects(Box $box1, Box $box2) { $result = true; $v1 = $box1->getVertexes(); $v2 = $box2->getVertexes(); for($i = 0; $i < 3; $i++) $result = $result && self::isEdgesIntersects($v1[0][$i], $v1[1][$i], $v2[0][$i], $v2[1][$i]); return $result; } /** * Are edges intersect * @param int $min1 * @param int $max1 * @param int $min2 * @param int $max2 * @return bool */ protected static function isEdgesIntersects($min1, $max1, $min2, $max2) { return !($min1 >= $max2 || $max1 <= $min2); } /** * @return array Dimensions of space filled by boxes */ public function getFilledDimensions() { if(empty($this->boxes)) return(array(0,0,0)); $maxX = $maxY = $maxZ = 0; foreach($this->boxes as $box) { $v = $box->getVertexes(); if($maxX < $v[1][0]) $maxX = $v[1][0]; if($maxY < $v[1][1]) $maxY = $v[1][1]; if($maxZ < $v[1][2]) $maxZ = $v[1][2]; } return array($maxX, $maxY, $maxZ); } /** * @return int Volume of space filled by boxes */ public function getFilledVolume() { $dims = $this->getFilledDimensions(); return $dims[0]*$dims[1]*$dims[2]; } /** * @param int[] $p1 * @param int[] $p2 * @return int * @internal */ public static function distanceCompare(array $p1, array $p2) { $zero = array(0,0,0); $d1 = self::calculateDistance($p1, $zero); $d2 = self::calculateDistance($p2, $zero); if($d1 == $d2) return 0; return ($d1 < $d2) ? -1 : 1; } /** * Calculate distance between two points * @param array $p1 * @param array $p2 * @return float */ public static function calculateDistance(array $p1, array $p2) { return sqrt(pow($p1[0]-$p2[0], 2) + pow($p1[1]-$p2[1], 2) + pow($p1[2]-$p2[2], 2)); } }